Junky

11-27-2012, 05:00 PM

Hi everyone,

I'm making changes to my deferred system. I want to delete the position texture (too much expensive GL_RGB32F) so in the light pass I have to reconstruct the pixel position from depth.

I tried for a few days without luke, so now I'm some how frustated.

What works (old position texture):

Geometry pass - Vertex:

vsPosition = ( ModelViewMatrix * vec4(in_Position, 1.0) ).xyz;

...

gl_Position = MVP * vec4(in_Position, 1.0);

Geometry pass - Fragment:

fsPosition = vsPosition;

This is how I store old pixel positions on geometry pass.

So next is to figure how to get this without the texture. I tried MANY things that I found around the net (without luke...), what i have now is:

Light pass - fragment:

vec2 calcTexCoord()

{

return gl_FragCoord.xy / ScreenSize;

}

vec3 positionFromDepth()

{

vec2 sp = calcTexCoord();

float depth = texture2D(Texture4, sp).x * 2.0 - 1.0;

vec4 pos = InvProjectionMatrix * vec4( sp*2.0-1.0, depth, 1.0);

return pos.xyz/pos.w;

}

vec3 computePhongPointLight()

{

vec3 color = vec3(0.0);

vec2 texCoord = calcTexCoord();

//vec3 position = texture2D( Texture0, texCoord ).xyz;

vec3 position = positionFromDepth();

vec3 difColor = texture2D( Texture1, texCoord ).xyz;

vec3 specColor = texture2D( Texture2, texCoord ).xyz;

vec3 normColor = texture2D( Texture3, texCoord ).xyz;

vec3 lightDir = Light.position.xyz - position;

vec3 lightDirNorm = normalize( lightDir );

float sDotN = max( dot(lightDirNorm, normColor), 0.0);

float att = 1.0;

float distSqr = dot(lightDir, lightDir);

float invAtt = (Light.constantAtt +

(Light.linearAtt*sqrt(distSqr)) +

(Light.quadraticAtt*distSqr));

att = 0.0;

if (invAtt != 0.0)

att = 1.0/invAtt;

vec3 diffuse = difColor.rgb * Light.diffuse * sDotN;

vec3 ambient = difColor.rgb * Light.ambient; // Cheat here

vec3 vertexToEye = normalize(position);

vec3 r = normalize(reflect(lightDirNorm, normColor));

// SpecularPower

vec3 specular = vec3(0.0);

if ( sDotN > 0.0 )

{

specular = Light.specular.rgb *

specColor *

pow( max( dot(vertexToEye, r), 0.0), 60.0 ); // Change specular here!!!! value 60 must be an uniform

}

return (diffuse + specular + ambient)*att;

}

Where Texture0 is old position texture, Texture4 is depth texture, InvProjectionMatrix is the inverse projection matrix, and Light.position is computed as ViewMatrix * light_position.

I did some debug and I output the absolute diference:

vec3 pos1 = positionFromDepth();

vec3 pos2 = texture2D(Texture0, calcTexCoord()).xyz;

fragColor = vec4(abs(pos2.x-pos1.x), abs(pos2.y-pos1.y), abs(pos2.z-pos1.z), 1.);

The output is all black minus empty zones that are white.

I think it's space error, something like: light position in view space and pixel position is in other space so "vec3 lightDir = Light.position - position" give bad results. But I can't figure what's happening, and how to solve it...

I will really apreciate any help (cause I don't know what more to do), and I hope that someone with better math can help me :)

Sorry for my bad English and thanks in advance.

I'm making changes to my deferred system. I want to delete the position texture (too much expensive GL_RGB32F) so in the light pass I have to reconstruct the pixel position from depth.

I tried for a few days without luke, so now I'm some how frustated.

What works (old position texture):

Geometry pass - Vertex:

vsPosition = ( ModelViewMatrix * vec4(in_Position, 1.0) ).xyz;

...

gl_Position = MVP * vec4(in_Position, 1.0);

Geometry pass - Fragment:

fsPosition = vsPosition;

This is how I store old pixel positions on geometry pass.

So next is to figure how to get this without the texture. I tried MANY things that I found around the net (without luke...), what i have now is:

Light pass - fragment:

vec2 calcTexCoord()

{

return gl_FragCoord.xy / ScreenSize;

}

vec3 positionFromDepth()

{

vec2 sp = calcTexCoord();

float depth = texture2D(Texture4, sp).x * 2.0 - 1.0;

vec4 pos = InvProjectionMatrix * vec4( sp*2.0-1.0, depth, 1.0);

return pos.xyz/pos.w;

}

vec3 computePhongPointLight()

{

vec3 color = vec3(0.0);

vec2 texCoord = calcTexCoord();

//vec3 position = texture2D( Texture0, texCoord ).xyz;

vec3 position = positionFromDepth();

vec3 difColor = texture2D( Texture1, texCoord ).xyz;

vec3 specColor = texture2D( Texture2, texCoord ).xyz;

vec3 normColor = texture2D( Texture3, texCoord ).xyz;

vec3 lightDir = Light.position.xyz - position;

vec3 lightDirNorm = normalize( lightDir );

float sDotN = max( dot(lightDirNorm, normColor), 0.0);

float att = 1.0;

float distSqr = dot(lightDir, lightDir);

float invAtt = (Light.constantAtt +

(Light.linearAtt*sqrt(distSqr)) +

(Light.quadraticAtt*distSqr));

att = 0.0;

if (invAtt != 0.0)

att = 1.0/invAtt;

vec3 diffuse = difColor.rgb * Light.diffuse * sDotN;

vec3 ambient = difColor.rgb * Light.ambient; // Cheat here

vec3 vertexToEye = normalize(position);

vec3 r = normalize(reflect(lightDirNorm, normColor));

// SpecularPower

vec3 specular = vec3(0.0);

if ( sDotN > 0.0 )

{

specular = Light.specular.rgb *

specColor *

pow( max( dot(vertexToEye, r), 0.0), 60.0 ); // Change specular here!!!! value 60 must be an uniform

}

return (diffuse + specular + ambient)*att;

}

Where Texture0 is old position texture, Texture4 is depth texture, InvProjectionMatrix is the inverse projection matrix, and Light.position is computed as ViewMatrix * light_position.

I did some debug and I output the absolute diference:

vec3 pos1 = positionFromDepth();

vec3 pos2 = texture2D(Texture0, calcTexCoord()).xyz;

fragColor = vec4(abs(pos2.x-pos1.x), abs(pos2.y-pos1.y), abs(pos2.z-pos1.z), 1.);

The output is all black minus empty zones that are white.

I think it's space error, something like: light position in view space and pixel position is in other space so "vec3 lightDir = Light.position - position" give bad results. But I can't figure what's happening, and how to solve it...

I will really apreciate any help (cause I don't know what more to do), and I hope that someone with better math can help me :)

Sorry for my bad English and thanks in advance.