OGDC2013_Lets remake the wheel_ Mr Nguyen Trung Hung

2,574 views

Published on

Presentation in OGDC 2013 organized by VNG Corp

Published in: Technology, Art & Photos
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,574
On SlideShare
0
From Embeds
0
Number of Embeds
1,250
Actions
Shares
0
Downloads
68
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Vertex Shader - OpenGL ES graphics code for rendering the vertices of a shape.Fragment Shader - OpenGL ES code for rendering the face of a shape with colors or textures.Program - An OpenGL ES object that contains the shaders you want to use for drawing one or more shapes.
  • What’s ETC ?Why should we use ETC texture ?But ETC don’t support alpha channel !!!
  • Q&A
  • Load texturefor (inti = 0 ; i < n ; ++i) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, texture_ids[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, ...); }Use texturefor (i = 0 ; i < n; ++i) { ... glUniform1i(texture_location, i); ... glDrawElements(...); }
  • References:http://beesbuzz.biz/code/hsv_color_transforms.phphttp://www.rapidtables.com/convert/color/rgb-to-hsv.htmhttp://www.cs.rit.edu/~ncs/color/t_convert.html
  • OGDC2013_Lets remake the wheel_ Mr Nguyen Trung Hung

    1. 1. Nguyễn Trung Hưng Firebat Game Studio - VNG
    2. 2. “DON’T RE-INVENT THE WHEEL”
    3. 3. Our old “wheel”: 3D vertex shader uniform mat4 uVPMatrix; attribute vec4 aPos; void main() { gl_Position = uVPMatrix * aPos; }
    4. 4. The old “wheel” was designed for
    5. 5. But we only need
    6. 6. 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); }
    7. 7. • Multiply ops: 16 • Add ops: 12 • Total: 28 • Multiply ops: 2 • Add ops: 2 • Total: 4 old “wheel” 28 VS 4 new “wheel”
    8. 8. 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
    9. 9. Old “wheel”: std fragment shader uniform sampler2D uTexture; varying mediump vec2 vTexCoord; void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }
    10. 10. We need a “wheel” ETC texture + Alpha mask texture = ETC with alpha component
    11. 11. 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); }
    12. 12. • Texture size: 100M • ETC size: 16.6M • Alpha mask size: 25M • Total: 41.6M old “wheel” 100 VS 42 new “wheel”
    13. 13. How to bind 2 textures and pass them to fragment shader ?
    14. 14. Old “wheel” was designed for
    15. 15. But we really need
    16. 16. 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”
    17. 17. • Textures add: 3 • Textures add: 0 old “wheel” 3 VS 0 new “wheel”
    18. 18. How to make the color transform matrix?
    19. 19. 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”
    20. 20. m11 m12 m13 m21 m22 m23 m31 m32 m33 Old “wheel” was designed for
    21. 21. We only need m11 m12 m13 m21 m22 m23 0 0 1
    22. 22. 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; }
    23. 23. 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]; }
    24. 24. • Multiply ops: 27 • Add ops: 18 • Total: 45 • Multiply ops: 12 • Add ops: 8 • Total: 20 old “wheel” 45 VS 20 new “wheel”
    25. 25. 1 0 tx 0 1 ty 0 0 1 If the new “wheel” only run on
    26. 26. 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]; }
    27. 27. 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]; }
    28. 28. Remake the old “wheel” void CMath::MATRIX_3x3_TRANSLATE(float* M, float tx, float ty) { M[6] += tx; M[7] += ty; }
    29. 29. • Multiply ops: 27 • Add ops: 18 • Total: 45 • Multiply ops: 0 • Add ops: 2 • Total: 2 old “wheel” 45 VS 2 new “wheel”
    30. 30. sx 0 0 0 sy 0 0 0 1 If the new “wheel” run on
    31. 31. 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; }
    32. 32. • Multiply ops: 27 • Add ops: 18 • Total: 45 • Multiply ops: 6 • Add ops: 0 • Total: 6 old “wheel” 45 VS 6 new “wheel”
    33. 33. 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”
    34. 34. 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”
    35. 35. 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”
    36. 36. public void RenderImage(…) { … glVertexPointer(2, GL_FLOAT, 0, vertex_data); glTexCoordPointer(2, GL_FLOAT, 0, tex_coord); glDrawElements(GL_TRIANGLES, …); … } Remake the old “wheel”
    37. 37. old “wheel” N VS 0 new “wheel”
    38. 38. Our old “wheel” • Encode binary content to string (Base64) • Use HTTP GET method • Decode url string to binary
    39. 39. 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
    40. 40. 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();
    41. 41. old “wheel” 100KB new “wheel” 48KB
    42. 42. Our old “wheel” function void UpdateMoney(int delta) { int money = ReadDB(“userid_money”); WriteDB(“userid_money”, money + delta); }
    43. 43. Old “wheel” was designed for single thread But we need multi-thread !!!
    44. 44. 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$
    45. 45. class CompareAndSet { Object value; long token; } new “wheel”
    46. 46. 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”
    47. 47. old wheel “earn” ±100$ new wheel “earn” 0$
    48. 48. The “wheel” which you found on internet, may be not designed for your “vehicle”. My exp
    49. 49. Understand your need if you want to remake your “wheel”. My exp
    50. 50. Remaking usually helps you get a better result. My exp
    51. 51. Even when it doesn’t get a better result, it always helps you gain more exp. My exp

    ×