liuzewei

Members
  • Content count

    2
  • Joined

  • Last visited

Community Reputation

124 Neutral

About liuzewei

  • Rank
    Newbie
  1. Hi, My english is bad, but I just wanna share something here, because I learned alot in this forum. Maybe these stuff will help someone. Nowadays, I wanna to implement defered rendering on mobile device(ipad/iphone), because my project needs geometry-independent ligths, so many lights... After some searching and hard trying, I figured out these devices are not support MRT, and even not support half or single presicion float render target/texture. So, G-BUFFER is the first and biggest problem. It must use multi-pass technique to generate G-BUFFER. Have no choice is not a problem, so keep going. I use three RT and rendering pass to generate G-BUFFER. [PASS ONE] POSITION-RT: GL_RGBA GL_UNSIGNED_BYTE Compressed the position's depth value(float32 in projection space) into this RGBA8 RT, then unpacked/trans back to view-space in lighting stage. GOOGLE: pack 32-bit float into RGBA(8-bit per channel) render target [PASS TWO] NORMAL-RT: GL_RGBA GL_UNSIGNED_BYTE RGB stored the normal, alpha channel store shadow mask(main directional light's shadow) [PASS THREE] COLOR-RT: GL_RGBA GL_UNSIGNED_BYTE RGB stored the albedo. and alpha channel is free till now. It's just one 8-bit alpha channel remain, but still have two elements to store. These are specluar power and specular scale value. So, Here have two choice: 1. add a new RT and rendering pass, means rendering the entire scene more one time. 2. compress these two value in the free 8-bit space. Which is the better choice? problem come. I just cant accept rendering the entire scene four times, so compress is my choice. [MAIN CONCEPT] give scale value a [0, 2] range. give it 3-bit can represent 2^3=8 values in theory. precision is 2/8=0.25(0, 0.25, 0.5, 0.75 ... 2.0), this is acceptable. give power value a [0, 200] range. give it 5-bit can represent 2^5=32 value. precision is 200/32=6.25(0, 6, 12, 18...200), this "average-kind" of distribution is not acceptable. [KEY CONCEPT] I wanna more precision on small power values, and less precision on large ones, when the power value become larger and larger. someting like this: 0, 0.4, 1.2, 2.4, 4, 6, 8.4, 11.2, 14.4, 18, 22, 26.4 ...... 200 yes, the key-idea for this compression is "arithmetic progression". ---------------------------------------------------------------------- -- below is implement code snippet ---------------------------------------------------------------------- [deferred_gbuffer_normal.fsh] [code]uniform highp float uSpcPower; uniform highp float uSpcScale; varying highp vec3 vNormal; void main() { // normal gl_FragColor.rgb = 0.5 * (normalize(vNormal) + 1.0); // compress specular power value and specular scale value into 8-bit alpha channel // // compress // d: 0.43 step length // s(n) = s_n = (n^2*d - n*d) * 0.5 range: [0, 199] // n(s) = n_s = (d + sqrt(d^2 + 8*d*s_n)) / (2*d) range: [0, 31] // // power value range: [0, 199] aka s_n, precision: n*d(in other words, precision decreasing when power value become larger and larger) // scale value range: [0, 2) precision: 2/8 = 0.25 // final value range: [0, 1) // // output // integer part: floor(n_s+0.5) range: [0, 31] // float part: fract(uSpcScale*0.5) range: [0, 1) // final value: (integer_part + float_part) / 32 range: [0, 1) // // uncompress // alpha channel -> val // power value: (floor(val*32)^2*d - floor(val*32)*d) * 0.5 // scale value: fract(val*32) * 2.0 // // for example // original power value: 0.5 -> integer part: 2 // original scale value: 1.6 -> float part: 0.8 // final output value: 0.0875 // // uncompressed power value: 0.43 // uncompressed scale value: 1.44 // /* conceptual version const highp float d = 0.43; highp float s_n = uSpcPower; highp float n_s = (d + sqrt(d*d + 8.0*d*s_n)) / (2.0*d); highp float integer_part = floor(n_s + 0.5); highp float float_part = fract(uSpcScale * 0.5); highp float final_value = (integer_part + float_part) / 32.0; gl_FragColor.a = final_value;*/ // optimized version highp float n_s = (0.43 + sqrt(0.1849 + 3.44*uSpcPower)) * 1.1627907; highp float integer_part = floor(n_s + 0.5); highp float float_part = fract(uSpcScale * 0.5); gl_FragColor.a = (integer_part + float_part) * 0.03125; }[/code] [deferred_lighting_point.fsh] [code]uniform highp mat4 uInvPMat; uniform highp vec3 uLightPos; uniform highp vec3 uLightClr; uniform highp float uLightRadius; uniform lowp sampler2D uSamplePosition; uniform lowp sampler2D uSampleNormal; varying highp vec4 vTexCoord; const highp vec4 unpackFactors = vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0); void main() { highp vec2 screenPos = vTexCoord.xy / vTexCoord.w; highp vec2 texCoord = (screenPos + 1.0) * 0.5; // unpack pos highp float depthVal = dot(texture2D(uSamplePosition, texCoord), unpackFactors); depthVal = 2.0 * depthVal - 1.0; highp vec4 texPos; texPos.xy = screenPos; texPos.z = depthVal; texPos.w = 1.0; texPos = uInvPMat * texPos; texPos /= texPos.w; mediump vec4 texNorm = texture2D(uSampleNormal, texCoord); // dif lgt highp vec3 lgtDir = uLightPos - texPos.xyz; highp float lenLgtDir = length(lgtDir); lgtDir /= lenLgtDir; highp float attLgt = max(0.0, 1.0 - lenLgtDir/uLightRadius); highp vec3 norm = 2.0 * texNorm.rgb - 1.0; highp float NdL = max(0.0, dot(norm, lgtDir)); highp vec3 difLgt = attLgt * NdL * uLightClr; // spc lgt // uncompress specular power value and specular scale value from 8-bit alpha channel // alpha channel -> val // power value: (floor(val*32)^2*d - floor(val*32)*d) * 0.5 // scale value: fract(val*32) * 2.0 highp float scaleBackValue = texNorm.a * 32.0 + 0.004; highp float integer_part = floor(scaleBackValue); highp float float_part = fract(scaleBackValue); highp float spcPower = (integer_part*integer_part*0.43 - integer_part*0.43) * 0.5; highp float spcScale = float_part * 2.0; highp vec3 rflDir = normalize(reflect(-lgtDir, norm)); highp vec3 dirToCam = normalize(-texPos.rgb); highp float spcLgt = attLgt * spcScale * pow(max(0.0, dot(rflDir, dirToCam)), spcPower); gl_FragColor.rgb = difLgt; gl_FragColor.a = spcLgt; }[/code] ---------------------------------------------------------------------- -- and a screen shot -- this is captured on windows but I have tested on ipad, it's ok also. ---------------------------------------------------------------------- [attachment=6600:shot.jpg] zewei, liu