Ogdc 2013 lets remake the wheel
-
Upload
son-aris -
Category
Technology
-
view
282 -
download
0
Embed Size (px)
Transcript of Ogdc 2013 lets remake the wheel

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