Zengar

02-16-2007, 12:21 PM

Several threads here and on beyond3d forums inspired me to do some tests on data compression. I implemented a simple shader using the shader designer (superb tool!) that show how to use bump-mapping without that annoying tangent attribute per vertex :-) The tangent space is calculated per-fragment and is used to transform the bump-map normal to the camera space. Below is the fragment shader (the vertex shader just transforms light, position and normal to camera space, so I left it out)

varying vec2 texCoord;

varying vec3 g_normal;

varying vec3 g_light;

varying vec3 g_pos;

void main()

{

vec3 color = texture2D(ColorMap, texCoord).rgb;

vec3 normal = texture2D(BumpMap, texCoord).rgb*2.0 - 1.0;

// compute tangent T and bitangent B

vec3 Q1 = dFdx(g_pos);

vec3 Q2 = dFdy(g_pos);

vec2 st1 = dFdx(texCoord);

vec2 st2 = dFdy(texCoord);

vec3 T = normalize(Q1*st2.t - Q2*st1.t);

vec3 B = normalize(-Q1*st2.s + Q2*st1.s);

// the transpose of texture-to-eye space matrix

mat3 TBN = mat3(T, B, g_normal);

// transform the normal to eye space

normal = normal*TBN;

// diffuse term

float diffuse = dot(g_light, normal);

// and the color...

gl_FragColor.rgb = diffuse*color;

}As said, I only tried it out with the Shader Designer, and there is no noticeable difference to standard approach (using the precomputed vertex attributes). The question is, of course, the performance. Unfortunately, I have no "real" bump-mapping code at hand to benchmark it have , so I thought, maybe someone here who already does camera-space bump-mapping can give it a try :-)

Just a side note: I did some tests with YCoCg color space and S3tc compression, being able to store a RGB+height texture at 4:1 compression rate, without any visible quality loss. The normal can be generated from height (this is pretty cheap too, only three texture fetches and some basic math). This is 1024*1024 color+bump map in 1Mb! I am not sure if it is still too early for per-pixel bump-map computation, but YCoCg color decompression is almost free.

varying vec2 texCoord;

varying vec3 g_normal;

varying vec3 g_light;

varying vec3 g_pos;

void main()

{

vec3 color = texture2D(ColorMap, texCoord).rgb;

vec3 normal = texture2D(BumpMap, texCoord).rgb*2.0 - 1.0;

// compute tangent T and bitangent B

vec3 Q1 = dFdx(g_pos);

vec3 Q2 = dFdy(g_pos);

vec2 st1 = dFdx(texCoord);

vec2 st2 = dFdy(texCoord);

vec3 T = normalize(Q1*st2.t - Q2*st1.t);

vec3 B = normalize(-Q1*st2.s + Q2*st1.s);

// the transpose of texture-to-eye space matrix

mat3 TBN = mat3(T, B, g_normal);

// transform the normal to eye space

normal = normal*TBN;

// diffuse term

float diffuse = dot(g_light, normal);

// and the color...

gl_FragColor.rgb = diffuse*color;

}As said, I only tried it out with the Shader Designer, and there is no noticeable difference to standard approach (using the precomputed vertex attributes). The question is, of course, the performance. Unfortunately, I have no "real" bump-mapping code at hand to benchmark it have , so I thought, maybe someone here who already does camera-space bump-mapping can give it a try :-)

Just a side note: I did some tests with YCoCg color space and S3tc compression, being able to store a RGB+height texture at 4:1 compression rate, without any visible quality loss. The normal can be generated from height (this is pretty cheap too, only three texture fetches and some basic math). This is 1024*1024 color+bump map in 1Mb! I am not sure if it is still too early for per-pixel bump-map computation, but YCoCg color decompression is almost free.