Jump to content
  • Advertisement
Sign in to follow this  
LiveAndFight

OpenGL Dual parabloid shadow problem on a Quake 3 based engine

This topic is 3036 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey, I am working on implementing dual parabloid shadow mapping, to replace my stencil buffer shadows. The problem is I can't get the lightmodelview matrix correct. My engine is based off of Quake 3, and I began to port it to DirectX and right now I'm trying to add a OpenGL rendering path because I see a lot more jobs for OpenGL programmers rather than DirectX programmers.

I've been basing my research and implementation on the Dual Paraboloid white paper as well as the implementation here(delphi3d is down): http://diaryofagraphicsprogrammer.blogspot.com/.

Picture of what it looks like now:



R_RotateForLight code:


void jmvBackEndLocal::R_RotateForLight( const trRefEntity_t *ent, orientationr_t *or ) {
float glMatrix[16];
idVec3_t delta;
float axisLength;

or->origin = ent->e.origin;
or->axis[0] = ent->e.axis[0];
or->axis[1] = ent->e.axis[1];
or->axis[2] = ent->e.axis[2];

glMatrix[0] = or->axis[0][0];
glMatrix[4] = or->axis[1][0];
glMatrix[8] = or->axis[2][0];
glMatrix[12] = or->origin[0];

glMatrix[1] = or->axis[0][1];
glMatrix[5] = or->axis[1][1];
glMatrix[9] = or->axis[2][1];
glMatrix[13] = or->origin[1];

glMatrix[2] = or->axis[0][2];
glMatrix[6] = or->axis[1][2];
glMatrix[10] = or->axis[2][2];
glMatrix[14] = or->origin[2];

glMatrix[3] = 0;
glMatrix[7] = 0;
glMatrix[11] = 0;
glMatrix[15] = 1;

qglMultMatrixf( glMatrix );
}


LightModelMatrix Gen code.


void jmvBackEndLocal::CreateLightModelMatrix ( dlight_t *light, int entityNum )
{
float m[16];

// Push the current modelview matrix to the stack.
qglPushMatrix();

// A = Bias Matrix.
qglLoadMatrixf( shadowBiasMatrix );

// B = Light Projection Matrix * A
// FIXME: The world projection matrix is in backEnd.or.ProjectionMatrix, lightProjectionMatrix,
// is TEMP in the front end viewParems.
qglMultMatrixf( tr.viewParms.projectionMatrix );

// C = LightViewMatrix * B
if( entityNum != ENTITYNUM_WORLD ) {
qglTranslatef( light->origin[ 0 ], light->origin[ 1 ], light->origin[ 2 ] );
R_RotateForLight( backEnd.currentEntity, &tr.lightOr );
}
else {
R_LookAt( idVec3_t( light->origin[ 0 ], light->origin[ 1 ], light->origin[ 2 ] ), idVec3_t( 0, 0, 0 ) );
}


// Generate the inverse of the current modelview matrix.
R_InvertMatrix4f( backEnd.or.modelMatrix, m );

// D = C * active inverse modelmatrix( set our light position at 0, 0, 0 ).
qglMultMatrixf( m );

// Get our lightmodelviewmatrix and copy it out.
qglGetFloatv(GL_MODELVIEW_MATRIX, tr.lightOr.modelMatrix );

// Restore the old modelviewmatrix
qglPopMatrix();
}


Vertex Program to generate the dual paraboloid maps.


vec4 inP = lightModelViewMatrix * gl_ModelViewMatrix * gl_PositionIn;
inP.z = inP.z * shadowDirection;
vec4 vertPos = inP / inP.w;

float L = length( vertPos );
vertPos = vertPos / L;

vertPos.z = vertPos.z + 1; // Halfway vector.

vertPos.x = vertPos.x / vertPos.z;
vertPos.y = vertPos.y / vertPos.z;

vertPos.z = (L - NearPlane) / (FarPlane - NearPlane); // scale the depth to [0, 1]
vertPos.w = 1; // set w to 1 so there is no w divide

gl_TexCoord.yz = vertPos.zw;

gl_Position = vec4( vertPos.x, vertPos.y, vertPos.z, vertPos.w );


This gets rendered into a FBO depth texture, and during the single pass lighting algorithm I use this(when I get this right I will switch over to textureArrays for now there is only ONE light in the scene.


vec3 ShadowPass( vec3 lightXyz, int lightNum, vec4 position, float LightAttenuation ) {
vec4 viewPos = lightModelMatrix[lightNum] * gl_ModelViewMatrix * position;

float L = length( viewPos );
float alpha = 0.5 + viewPos.z / LightAttenuation;

vec4 P0 = viewPos / L;
vec4 P1 = viewPos / L;

P0.z = 1.0f - P0.z;
P0.x = P0.x / P0.z;
P0.y = P0.y / P0.z;
P0.z = L / LightAttenuation;

P0.x = .5f * P0.x + .5f;
P0.y = -.5f * P0.y + .5f;

P1.z = 1.0f + P1.z;
P1.x = P1.x / P1.z;
P1.y = P1.y / P1.z;
P1.z = L / LightAttenuation;

P1.x = .5f * P1.x + .5f;
P1.y = -.5f * P1.y + .5f;

float depth = textureProj( shadowTexFront, vec4( P1.x, P1.y, P1.z, 1 ) ).r;
float depth2 = textureProj( shadowTexBack, vec4( P0.x, P0.y, P0.z, 1 ) ).r;

if( alpha < 0.5 ) {
depth = depth2;
}
return vec3( depth, depth, depth );
}


The reason why I set W to 1 is if I use P0.w or P1.w the shadow maps just renders white with a small sliver of black, to me right now it just looks inverted I've tried doing glRotate, glScale, etc still isn't working right.

Any help would be appreciated : ).

[Edited by - LiveAndFight on July 20, 2010 6:59:25 PM]

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!