ogdc 2013 lets remake the wheel

Post on 09-May-2015

281 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Let’s re-make the wheel

Nguyễn Trung Hưng

Firebat Game Studio - VNG

“DON’T RE-INVENT THE WHEEL”

Re-make GL shader

for 2D graphics

Our old “wheel”: 3D vertex shader

uniform mat4 uVPMatrix; attribute vec4 aPos;

void main() {

gl_Position = uVPMatrix * aPos; }

The old “wheel” was designed for

But we only need

Remake the old “wheel” for 2D

attribute vec2 aPos;

void main(){

gl_Position = vec4( aPos.x/HALF_WIDTH - 1.0,

1.0 - aPos.y/HALF_HEIGHT,

0.0, 1.0);

}

• Multiply ops: 16• Add ops: 12• Total: 28

• Multiply ops: 2• Add ops: 2• Total: 4

old “wheel”

28 VS 4

new “wheel”

Re-make GL shader

for ETC texture

ETC texture

• Ericsson Texture Compression (ETC)

• 6x compression 0f 24-bit RGB data

• No support images with Alpha component

Source: http://en.wikipedia.org/wiki/Ericsson_Texture_Compression

Old “wheel”: std fragment shader

uniform sampler2D uTexture;varying mediump vec2 vTexCoord;

void main() {

gl_FragColor = texture2D(uTexture, vTexCoord);}

We need a “wheel”

ETC texture + Alpha mask texture = ETC with alpha component

Remake the “wheel” for ETC

uniform sampler2D uTexture;uniform sampler2D uAlpha;varying mediump vec2 vTexCoord;

void main() {

vec4 color = texture2D(uTexture, vTexCoord);

vec4 alpha = texture2D(uAlpha, vTexCoord);

gl_FragColor = vec4(color.rgb, alpha.r);}

• Texture size: 100M • ETC size: 16.6M• Alpha mask size: 25M• Total: 41.6M

old “wheel”

100 VS 42

new “wheel”

How to bind 2 textures and pass them to fragment

shader ?

Re-make GL shader for

color transformation

Old “wheel” was designed for

But we really need

uniform sampler2D uTexture;uniform mat4 uColorTransformMatrix;varying mediump vec2 vTexCoord;

void main() {

Vector4 color = texture2D(uTexture, vTexCoord);

gl_FragColor = uColorTransformMatrix * color;}

Remake the old “wheel”

• Textures add: 3 • Textures add: 0

old “wheel”

3 VS 0

new “wheel”

How to make the color transform

matrix?

Re-make matrix funcs

for 2D graphics

void CMath::MATRIX_3x3_MULTIPLY(float* A, float* B, float* result){

result[0] = A[0]*B[0] + A[3]*B[1] + A[6]*B[2];

result[1] = A[1]*B[0] + A[4]*B[1] +A[7]*B[2];result[2] = A[2]*B[0] + A[5]*B[1] +A[8]*B[2];result[3] = A[0]*B[3] + A[3]*B[4] +A[6]*B[5];result[4] = A[1]*B[3] + A[4]*B[4] +A[7]*B[5];result[5] = A[2]*B[3] + A[5]*B[4] +A[8]*B[5];result[6] = A[0]*B[6]+ A[3]*B[7] +

A[6]*B[8];result[7] = A[1]*B[6] + A[4]*B[7] +A[7]*B[8];result[8] = A[2]*B[6] + A[5]*B[7] +A[8]*B[8];

}

Our old “wheel”

m11 m12 m13

m21 m22 m23

m31 m32 m33

Old “wheel” was designed for

We only need

m11 m12 m13

m21 m22 m23

0 0 1

Remake the old “wheel”void CMath::MATRIX_3x3_MULTIPLY(float* A, float* B, float* result){

result[0] = A[0]*B[0] + A[3]*B[1] + A[6]*0;result[1] = A[1]*B[0] + A[4]*B[1] + A[7]*0;result[2] = 0*B[0] + 0*B[1] + 1*0;

result[3] = A[0]*B[3] + A[3]*B[4] + A[6]*0;result[4] = A[1]*B[3] + A[4]*B[4] + A[7]*0;result[5] = 0*B[3] + 0*B[4] + 1*0;

result[6] = A[0]*B[6] + A[3]*B[7] + A[6]*1;result[7] = A[1]*B[6] + A[4]*B[7] + A[7]*1;result[8] = 0*B[6] + 0*B[7] + 1*1;

}

Remake the old “wheel”void CMath::MATRIX_3x3_MULTIPLY(float* A, float* B, float* result){

result[0] = A[0]*B[0] + A[3]*B[1];result[1] = A[1]*B[0] + A[4]*B[1];

result[3] = A[0]*B[3] + A[3]*B[4];result[4] = A[1]*B[3] + A[4]*B[4];

result[6] = A[0]*B[6] + A[3]*B[7] + A[6];result[7] = A[1]*B[6] + A[4]*B[7] + A[7];

}

• Multiply ops: 27• Add ops: 18• Total: 45

• Multiply ops: 12• Add ops: 8• Total: 20

old “wheel”

45 VS 20

new “wheel”

1 0 tx

0 1 ty

0 0 1

If the new “wheel” only run on

Remake the old “wheel”

void CMath::MATRIX_3x3_MULTIPLY(float* A, float* B, float* result){

result[0] = 1*B[0] + 0*B[1];result[1] = 0*B[0] + 1*B[1];

result[3] = 1*B[3] + 0*B[4];result[4] = 0*B[3] + 1*B[4];

result[6] = 1*B[6] + 0*B[7] + A[6];result[7] = 0*B[6] + 1*B[7] + A[7];

}

Remake the old “wheel”

void CMath::MATRIX_3x3_MULTIPLY(float* A, float* B, float* result){

result[0] = B[0];result[1] = B[1];

result[3] = B[3];result[4] = B[4];

result[6] = B[6] + A[6];result[7] = B[7] + A[7];

}

Remake the old “wheel”

void CMath::MATRIX_3x3_TRANSLATE(float* M, float tx, float ty){

M[6] += tx;M[7] += ty;

}

• Multiply ops: 27• Add ops: 18• Total: 45

• Multiply ops: 0• Add ops: 2• Total: 2

old “wheel”

45 VS 2

new “wheel”

sx 0 0

0 sy 0

0 0 1

If the new “wheel” run on

Remake the old “wheel”

void CMath::MATRIX_3x3_SCALE(float* M, float sx, float sy){

M[0] *= sx;M[1] *= sy;

M[3] *= sx;M[4] *= sy;

M[6] *= sx;M[7] *= sy;

}

• Multiply ops: 27• Add ops: 18• Total: 45

• Multiply ops: 6• Add ops: 0• Total: 6

old “wheel”

45 VS 6

new “wheel”

Re-make

GL vertex data to

remove dynamic

transformation

public float[] MakeImageVertexData(float x, float y, short w, short h){

xy[0] = x; xy[1] = y;

xy[2] = x; xy[3] = (h + y);

xy[4] = (w + x); xy[5] = (h + y);

xy[6] = (w + x); xy[7] = y;}

Our old “wheel”

public void RenderImage(…){

glPushMatrix(); glScalef(sx, sy, sz); glTranslatef(tx, ty, tz); glRotatef(angle, vx, vy, vz); … glVertexPointer(2, GL_FLOAT, 0, vertex_data); glTexCoordPointer(2, GL_FLOAT, 0, tex_coord); glDrawElements(GL_TRIANGLES, …); glPopMatrix();

}

Our old “wheel”

MakeImageVertexData(float x, float y, short w, short h, float m11, float m12,

float m21, float m22){

xy[0] = x; xy[1] = y;

xy[2] = h*m12 +x; xy[3] = h*m22 + y;

xy[4] = w*m11 + h*m12 + x; xy[5] = w*m21 + h*m22 + y;

xy[6] = w*m11 + x; xy[7] = w*m21 + y;}

Remake the old “wheel”

public void RenderImage(…){

… glVertexPointer(2, GL_FLOAT, 0, vertex_data); glTexCoordPointer(2, GL_FLOAT, 0, tex_coord); glDrawElements(GL_TRIANGLES, …);…

}

Remake the old “wheel”

old “wheel”

N VS 0

new “wheel”

Re-make HTTP request

to sending binary

content

Our old “wheel”

• Encode binary content to string (Base64)

• Use HTTP GET method

• Decode url string to binary

Our new “wheel”

• No encode

• Use HTTP POST method- With “Content-Type: application/octet-stream”- Maybe with "Content-Encoding: gzip“- And "Content-MD5: …"

• No decode

HttpURLConnection http_conn = (HttpURLConnection)url.openConnection();http_conn.setRequestMethod(”POST”);http_conn.setDoOutput(true);

byte[] final_content = GZIP(_binary_data);

http_conn.setRequestProperty("Content-Type", "application/octet-stream");http_conn.setRequestProperty("Content-Encoding", "gzip");http_conn.setRequestProperty("Content-MD5", MD5(final_content));

http_conn.setFixedLengthStreamingMode(final_content.length);

//send the POST content OutputStream out = http_conn.getOutputStream(); out.write(final_content);out.close();

old “wheel”

100KB

new “wheel”

48KB

Re-make code

for thread-safe

Our old “wheel”

function void UpdateMoney(int delta){

int money = ReadDB(“userid_money”);WriteDB(“userid_money”, money +

delta);}

Old “wheel” was designed for single thread

But we need multi-

thread !!!

function void UpdateMoney(int delta){1. int money = ReadDB(“userid_money”);2. WriteDB(“userid_money”, money + delta);}

•A:1 => A:2 => B:1 => B:2•A:1 => B:1 => A:2 => B:2•A:1 => B:1 => B:2 => A:2

• Thread A: -100$• Thread B: +100$

class CompareAndSet{

Object value;

long token;}

new “wheel”

function boolean UpdateMoney(int delta){1. CAS casMoney = CasReadDB(“userid_money”);

2. return CasWriteDB( “userid_money”, casMoney.value + delta,casMoney.token);

}

•A:1(t1) => A:2(t2 = t1++) => B:1(t2)

=> B:2(t3 = t2++)

•A:1(t1) => B:1(t1) => A:2(t2 = t1++)

=> B:2(t1 != t2)

new “wheel”

old wheel “earn”

±100$

new wheel “earn”

0$

The “wheel” which

you found on

internet, may be

not designed for

your “vehicle”.

My exp

Understand your need if you want to remake your “wheel”.

My exp

Remaking usually helps you get a better result.

My exp

Even when it doesn’t get a better result, it always helps you gain more exp.

My exp

top related