PDA

View Full Version : Another GLSL shadow volume problem!!!!



bobGL
02-28-2008, 03:38 AM
I try to implement stencil shadow in my engine, and it kinda work right now... except that I have 2 problems...

1. Im trying using the shader below to simulate a point light that emit shadow in every direction ie: If the light is in the middle of some objects the shadow should be projected on the left, right, up and down but... right now it's working but always in the same direction... My question is how can I get the world position of the gl_Vertex (after transformation and inside the world) so I can do my calculations in world space.




[ extrusion shader ]

void main( void )
{
vec3 localLightDirection = normalize( gl_LightSource[0].specular.xyz - gl_Vertex.xyz );

vec4 p = gl_ModelViewProjectionMatrix * vec4( -localLightDirection, 0.0 );
vec4 q = ftransform();

float ndl = dot( gl_Normal, localLightDirection.xyz );

if( ndl < 0.0 )
{ p = q; }

gl_Position = p;
}




2. Concerning the shadow volume... I've been trying the implement zfail, I've check the code many times but I still get the problem that the shadow is inverted when Im entering the shadow. Can someone point me what Im doing wrong cuz it looks good to me but it obviously not working as it should





[ shadow volume ]

...
...
...

// Light position in world space (point light)
glLightfv( GL_LIGHT0, GL_SPECULAR, light->pos );


glClear( GL_STENCIL_BUFFER_BIT );

glDepthFunc( GL_GEQUAL );
glEnable( GL_CULL_FACE );

glDepthMask( GL_FALSE );

glColorMask( GL_FALSE,
GL_FALSE,
GL_FALSE,
GL_FALSE );

glEnable( GL_STENCIL_TEST );



glClear( GL_STENCIL_BUFFER_BIT );
glStencilFunc( GL_ALWAYS, 1, 0xffffffff );



glCullFace( GL_FRONT );
glStencilOp( GL_KEEP, GL_INCR, GL_KEEP );

bind_shader(3); // Extrusion shader

draw_object( tmp );

unbind_shader();


glCullFace( GL_BACK );
glStencilOp( GL_KEEP, GL_DECR, GL_KEEP );

bind_shader(3); // Extrusion shader

draw_object( tmp );

unbind_shader();




glCullFace( GL_BACK );

glDepthMask( GL_TRUE );
glColorMask( GL_TRUE,
GL_TRUE,
GL_TRUE,
GL_TRUE );


glStencilFunc( GL_NOTEQUAL, 0, 0xffffffff );
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);



glDepthMask( GL_TRUE );

glColorMask( GL_TRUE,
GL_TRUE,
GL_TRUE,
GL_TRUE );


glColor4f(0.0f, 0.0f, 0.0f, 0.5f);

glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );


Enter2D( 0,0,800,600 );
{
glPushMatrix();
glLoadIdentity();

glBegin( GL_QUADS );
glVertex3f( 0.0f , 0.0f , 0.0f );
glVertex3f( 800.0f, 0.0f , 0.0f );
glVertex3f( 800.0f, 600.0f, 0.0f );
glVertex3f( 0.0f , 600.0f, 0.0f );
glEnd();

glPopMatrix();
}
Leave2D();


glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

glDisable(GL_BLEND);

glDisable( GL_STENCIL_TEST );

glEnable( GL_CULL_FACE );

glDepthFunc( GL_LEQUAL );

...
...
...




Tks in advance!

Y-tension
02-29-2008, 11:02 AM
My question is how can I get the world position of the gl_Vertex (after transformation and inside the world) so I can do my calculations in world space.
Strange that you should ask that. The answer of course is gl_ModelViewMatrix*gl_Vertex.
Lights in OpenGL are already stored in world space so you needn't store anything in the specular component.
However I see you use local coordinates in your shader so you should transform the world light position to local position like this:


void main()
{
vec4 lightLocal = gl_ModelViewMatrixInverse*gl_Light[0].position;
vec4 lightDirection = vec4((lightLocal - gl_Vertex).xyz, 0.0);
vec4 v = (dot(lightDirection, gl_Normal) < 0.0) ? lightDirection : gl_Vertex;

gl_Position = gl_ModelViewProjectionMatrix*v;
}
As for the inverted problem, you should leave glDepthFunc to GL_LEQUAL.

Komat
02-29-2008, 04:47 PM
My question is how can I get the world position of the gl_Vertex (after transformation and inside the world) so I can do my calculations in world space.
Strange that you should ask that. The answer of course is gl_ModelViewMatrix*gl_Vertex.

That is eye space. For world space you need to send the Model matrix (or inverse of view matrix) separately as.



uniform mat4 my_word_matrix ;
my_word_matrix * gl_Vertex


OR

uniform mat4 my_inverse_of_view_matrix ;
my_inverse_of_view_matrix * ( gl_ModelViewMatrix * gl_Vertex )




Lights in OpenGL are already stored in world space so you needn't store anything in the specular component.

Fixed function lighting expects them to be in eye space. For shader it can be any space you want.

_NK47
03-02-2008, 02:56 PM
I pass the light position to the shader myself in special uniform.
Before doing that though i transform light position into eye-space, so all calculation can be done in eye-space!

In shader then:
vec3 epos = vec3(gl_ModelViewMatrix * gl_Vertex);
vec3 normal = vec3(gl_NormalMatrix * gl_Normal);
vec3 lightDir = c_light[0].pos - epos;
// c_light[0].pos is in eye space!