Deferred Lighting Headache OpenGL + NvidiaCG

Hello guys,

First of all, and I know that this topic is going to burn the forums but, I’m gonna get mad because of this.

I’m porting my forward render to Deferred, to get benefit of the light / shadow / ssao etc. But it seems that no matter the topics i’ve read and tutorials / examples… no body have this kind of mistake.

Cuz indeed most of the people have a similar problem… the lights moves when you move the camera… The solution is quite simple, re-view the code and check that all the vectors and matrices belong to same space, but my problem is quite different.

I’m trying to achieve point light, based in Fabio Policarpo paper and other ones. I tried everything… get all in screenspace, get all in view-space. But the problem persist, the whole screen gets almost totally lighter when I get closer to the point light with the camera, and gets darker (ambient contribution only) when I step back…

Here the fundamental parts.
CPU Part:

2D OrthoRender

/* Local Variables */
ddeMatrix ddeProjMat,
ddeViewMat;
ddeMath::mat4 invViewCam, invViewProjCam;
ddeMath::ivec2 scrSize;
ddeCamera myCamera = ( ddeCamera )this->sharedContainer->currCamera;
double d[3];
ddeMath::vec3 camPos, vVector[4];
#define Zfar 0.3f
#define Znear 1000.0f

//Determine the ModelView Matrix and Projection Matrix
if( mode != 4 )
{
//Set the Screen Size Properly to the fboTexture
scrSize.x = this->fboWidth;
scrSize.y = this->fboHeight;
}
else
{
//Set the Screen Size Properly to the Monitor
scrSize.x = this->sharedContainer->dimScrWidth;
scrSize.y = this->sharedContainer->dimScrHeight;
}

   /* Push GL Flags */

//glPushAttrib ( GL_ALL_ATTRIB_BITS );
glMatrixMode ( GL_PROJECTION );
glPushMatrix ( );
glLoadIdentity( );

/* Prepare the Projection Matrix */
glOrtho(0,scrSize.x,0,scrSize.y,-1,1);
glViewport( 0,0, scrSize.x, scrSize.y );

/* Prepare the ModelView Matrix*/
glMatrixMode ( GL_MODELVIEW );
glLoadIdentity( );

   //Possible 2D Options

switch ( mode )
{
case 0: //Ambient Pass
//Set the ambient Pass

  	break;
  case 1: // Lighting Pass
  	//Enable Blend Flag
  	glEnable( GL_BLEND );
  	//Select the Cg-Technique for the Inorganic Part
  	myCgTechnique = cgGetNamedTechnique( myCgEffect, "LightPass"  );
  	//Select the proper Cg-Pass for this ddeMesh-Part
  	myCgPass      = cgGetNamedPass     ( myCgTechnique, "p0"   );
  	cgSetPassState                     ( myCgPass              );
  	/* Get Light Position into View-Space */
                    ddelPosition = ddeMath::vec4(  myCamera->GetViewMatrix()  * ddeMath::vec4( ddelPosition, 1 ) ).xyz() ;
                    /* Send Camera in View Space (??)  Not necessary, only for testing */
  	camPos              = myCamera->GetEyeCenter(                                  );
  	camPos               = ddeMath::vec4(  myCamera->GetViewMatrix()  * ddeMath::vec4( camPos, 1 ) ).xyz() ;
                    //Set the Parameters into the GPU
  	cgGLSetParameter3f          ( myCgEyePos,       camPos.x, camPos.y, camPos.z                                           );
  	cgGLSetParameter3f         ( myCgLDcolor,       ddelDcolor.x,   ddelDcolor.y,   ddelDcolor.z                        );
  	cgGLSetParameter4f         ( myCgLScolor,       ddelScolor.x,   ddelScolor.y,   ddelScolor.z,  ddelScolor.w    );
                    cgGLSetParameter3f        ( myCgLposition,    ddelPosition.x, ddelPosition.y, ddelPosition.z                       );
  	checkForCgError( "Sending Fixed Values Camera and other Stuff..." );
  	glActiveTextureARB          ( GL_TEXTURE0_ARB                                              );
  	glEnable                           ( GL_TEXTURE_2D                                                  );
  	glBindTexture                  ( GL_TEXTURE_2D,          this->gBufferTexId[0]      ); //Albedo + Ambient
  	cgGLSetTextureParameter( myCgAlbedoTex,  (GLuint)this->gBufferTexId[0] );
  	glActiveTextureARB          ( GL_TEXTURE1_ARB                                              );
  	glEnable                           ( GL_TEXTURE_2D                                                  );
  	glBindTexture                  ( GL_TEXTURE_2D,          this->gBufferTexId[1]      ); //Normal with TBN
  	cgGLSetTextureParameter( myCgNormalTex,  (GLuint)this->gBufferTexId[1] );
  	glActiveTextureARB          ( GL_TEXTURE2_ARB                                             );
  	glEnable                           ( GL_TEXTURE_2D                                                 );
  	glBindTexture                  ( GL_TEXTURE_2D,          this->gBufferTexId[2]     ); //Position
  	cgGLSetTextureParameter( myCggBuff2Tex,  (GLuint)this->gBufferTexId[2] );
  	glActiveTextureARB          ( GL_TEXTURE3_ARB                                              );
  	glEnable                           ( GL_TEXTURE_2D                                                  );
  	glBindTexture                  ( GL_TEXTURE_2D,          this->gBufferTexId[3]      ); //Depth
  	cgGLSetTextureParameter( myCggBuff3Tex,  (GLuint)this->gBufferTexId[3]  );
  	break;
  case 4: //MainFrameBuffer Last Pass
  	
  	break;

}

    //Update Gpu Params cgUpdatePassParameters( myCgPass ); ... and Draw a gigant Quad...
    //Disable Texture units, Pop Proj Matrix.

And at last here are the Light Vert and Frag.

Light Vert

void LitVPass( float3 positionIN : POSITION,
float2 texcoordIN : TEXCOORD0,
out float4 positionOUT : POSITION,
out float2 texcoordOUT : TEXCOORD0 )
{
float2 GBufferTextureSize = float2( 1360, 768 ); // Right Now the FBO’s and the screen Size are the same that’s why this is fixed here.

 //Pass the Interpolated Position
 positionOUT = mul( glstate.matrix.mvp, float4( positionIN, 1 ) );
 
 //Pass TexCoord
 texcoordOUT =  texcoordIN - float2( 1.0f / GBufferTextureSize.xy );  

}

Light Frag

void LitFPass( float4 position : POSITION,
float2 texCoord : TEXCOORD0,
float3 vVec : TEXCOORD1,

             float3 vPos                    : TEXCOORD2,
             float3 lPos                    : TEXCOORD3,
                      
             uniform sampler2D diffuse_map  : TEX0,
             uniform sampler2D normal_map   : TEX1,
             uniform sampler2D position_map : TEX2,
             uniform sampler2D depth_map    : TEX3,
             uniform _Light    Light,
             uniform float2    planes,
             uniform float3    eyeP,
             out     float4    color0       : COLOR0,
             out     float4    color1       : COLOR1         ) 

{
//Diffuse Map
float3 Diffuse = f3tex2D( diffuse_map, texCoord );

  //Position Map
  float4 Position = f4tex2D( position_map, texCoord ); //View-Space
  
  //Depth Map
  //float Depth     = f1tex2D( depth_map,    coords );      
  
      
  //Decode Normal
  float3 Normal = f3tex2D( normal_map, texCoord ) - 0.5; // Normal in View Space
       
     
  //Light Color and Position  
  float4 lColor    = float4( 0, 1, 0, 10 );   
  
  //Imaginary Specular
  float4 Specular = float4( 0.4f, 0.4f, 0.6f, 1.0f );                      
        
  
  //Return Phong Shaded Value       
  color0 =  Phong( eyeP,            
                   Light.lPosition, 
                   Position.xyz,    
                   Normal,          
                   Specular.xyz,    
                   Specular.w,       
                   Light.Dcolor.xyz, 
                   lColor.w,        
                   Diffuse           );
                   
  color1 =  float4( Diffuse , 1 );

}

//Phong Shader
float4 Phong(float3 eyePos,
float3 Lpos,
float3 Position,
float3 N,
float3 SpecularColor,
float SpecularPower,
float3 LightColor,
float LightIntensity ,
float3 DiffMaterial )
{
//Light Vector
float3 L = Lpos - Position;

//Calculate View Vector
float3 V = normalize( eyePos - Position );

//Half Vector
float3 H = normalize( V + L );

//Float Attenuation
float att = saturate ( 1.0f - length( L ) / LightIntensity );
L = normalize( L );

//Diffuse and Specular Terms
float3 Idiff = saturate( dot( L, N ) ) * DiffMaterial * LightColor;
//float3 Ispec = pow( saturate( dot( H, N ) ), SpecilarPower ) * SpecularColor * LightColor;

//Calculate Final Product
return float4( att * DiffMaterial , 1 );
}

Right now I’m using a Position Buffer to determine the vert Position in Camera ( View - Space ), because at first instance I believed that the problem was related with the Depth buffer…

Any Suggestion - Advice?

Thanks in advance.

One thing I see is that you don’t provide a normalized L into your half vector calculation:

float3 H = normalize( V + L );

Also, you seem to decode the Normal, but don’t normalize it to have unit length.

Since you seem to calculate everything in viewspace, this line looks suspicious:
float3 V = normalize( eyePos - Position );
Shouldn’t be eyePos always be (0,0,0) in viewspace?

These lines also look suspicious, since I can’t see the corresponding glPopMatrix() for it.
glMatrixMode ( GL_PROJECTION );
glPushMatrix ( );
glLoadIdentity( );

Another thing you should check is if the position data stored in the texture is correct. You might have accidently picked the wrong textureformat or so…

You’re totally right skynet, but I multiply eye position with viewmatrix at CPU (just for test!, I know that that will be equal to 0,0,0 ).

And the Projection matrix is popped later, It’s just that I didn’t pasted.

By the way I figured out what was the problem of the shader. ( And you can see it below).

The only problem that the shader has is this:

uniform sampler2D diffuse_map : TEX0

The TEX0 is totally incorrect!, the correct reserved word is TEXUNIT0 and so on.
But the shader and CG compiler is not complaining with this!, in fact is really strange, cuz the shader will load the texunit0 and texunit1, and the rest of the samplers will be a copy of texunit 1, so the shader was trying to get position from normal buffer!!!.

And by the way… I’m developing using Mac OSX with G5 (PowerPC), and its a pain to not have a debugger for shaders (Nvidia FX composer) is only for Windows… ¬_¬…

Thanks for your help skynet!.