#242090 - 07/22/08 10:31 AM
Re: Help with Cascading Shadowmapping
[Re: Mars_999]
|
Newbie
Registered: 06/27/08
Posts: 40
Loc: Russia, Moscow
|
I am trying to do some cascading shadow mapping, and I get this artifact and have no idea why this would be? Anyone have any ideas what would cause this?
Do you use shadowTextureArray on <cascade> ? What kind of filter do you use ?
|
|
Top
|
|
|
|
#242097 - 07/22/08 11:33 AM
Re: Help with Cascading Shadowmapping
[Re: innuendo]
|
Regular Contributor
  
Registered: 03/09/01
Posts: 224
Loc: Sioux Falls, SD, USA
|
Wow thanks all for the help and ideas, I do render the back faces, I am using the PolygonOffset that the tutorial used. I am not using sampler2DArray so no need for GL_COMPARE_R_TO_TEXTURE. I am using GL_LINEAR filtering as does the tutorial on Nvidia this is free PCF. What I can tell is it happens at the splits mainly the first split. I don't know if this matters, but the user made the demo using a fps type camera and I am using a 3rd person camera where the camera has the chase view going on. I have tried the tutorial and added in my heightmap and I can't get it to do what is happening on my terrain. This only happens with the terrain rendering, not with any of the models. I have also removed any culling techniques and brute force rendered all the terrain polygons and that doesn't matter either. I am going to post my code if anyone wants to look through it.
class ShadowMap
{
public:
FrustumData f[MAX_SPLITS];
float shad_cpm[MAX_SPLITS][16];
float shad_modelview[16];
float cam_proj[16];
float cam_modelview[16];
float cam_inverse_modelview[16];
float far_bound[MAX_SPLITS];
float split_weight;
int depth_size;
int cur_num_splits;
GLuint depth_fb;
GLuint depth_tex_ar;
GLSL shader;
ShadowMap()
{
split_weight = .75f;
depth_size = 2048;
cur_num_splits = 4;// MAX_SPLITS is the largest
depth_tex_ar = 0;
depth_fb = 0;
}
~ShadowMap(){}
void Setup(void);
void ShowDepthTex(void);
void CameraInverse(float dst[16], float src[16]);
void UpdateFrustumPoints(FrustumData& f, vec3& center, vec3& view_dir);
void UpdateSplitDist(FrustumData f[MAX_SPLITS], float nd, float fd);
void MakeShadowMap(void);
void DrawShadowFrustum(void);
void DrawLightPosition(void);
float ApplyCropMatrix(FrustumData& f);
};
void ShadowMap::Setup(void)
{
glGenFramebuffersEXT(1, &depth_fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, depth_fb);
glDrawBuffer(GL_NONE);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glGenTextures(1, &depth_tex_ar);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, depth_tex_ar);
glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, gameSetupData.enableFPDepthBuffer == false ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT32F_NV,
depth_size, depth_size, MAX_SPLITS, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
CheckFBOStatus();
double aspect = (double)gameSetupData.screenWidth/(double)gameSetupData.screenHeight;
for(int i = 0; i < MAX_SPLITS; ++i)
{
f[i].fov = gameSetupData.fov/PI_180_OVER_PI+.2f;
f[i].ratio = aspect;
}
shader.SetupShaders(std::string("shaders/view_vertex.vsp"), std::string("shaders/view_fragment.fsp"));
shader.textureLocation[0] = glGetUniformLocation(shader.program, "shadowmap");
glUniform1i(shader.textureLocation[0], 0);
shader.shaderVariable[0] = glGetUniformLocation(shader.program, "layer");
glUniform1f(shader.shaderVariable[0], 0.0f);
shader.UnBindShader();
}
void ShadowMap::ShowDepthTex(void)
{
glPushAttrib(GL_VIEWPORT_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
shader.BindShader();
for(int i=0; i<cur_num_splits; i++)
{
glViewport(130*i, 0, 128, 128);
glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, depth_tex_ar);
glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glUniform1f(shader.shaderVariable[0], (float)i);
glBegin(GL_QUADS);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
}
shader.UnBindShader();
glViewport(gameSetupData.screenWidth - 129, 0, 128, 128);
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_CULL_FACE);
glPopAttrib();
}
void ShadowMap::CameraInverse(float dst[16], float src[16])
{
dst[0] = src[0];
dst[1] = src[4];
dst[2] = src[8];
dst[3] = 0.0f;
dst[4] = src[1];
dst[5] = src[5];
dst[6] = src[9];
dst[7] = 0.0f;
dst[8] = src[2];
dst[9] = src[6];
dst[10] = src[10];
dst[11] = 0.0f;
dst[12] = -(src[12] * src[0]) - (src[13] * src[1]) - (src[14] * src[2]);
dst[13] = -(src[12] * src[4]) - (src[13] * src[5]) - (src[14] * src[6]);
dst[14] = -(src[12] * src[8]) - (src[13] * src[9]) - (src[14] * src[10]);
dst[15] = 1.0f;
}
void ShadowMap::UpdateFrustumPoints(FrustumData& f, vec3& center, vec3& view_dir)
{
vec3 up(0.0f, 1.0f, 0.0f);
vec3 right = Cross(view_dir, up);
vec3 fc = center + view_dir*f.fard;
vec3 nc = center + view_dir*f.neard;
right.Normalize();
up = Cross(right, view_dir);
up.Normalize();
float near_height = tan(f.fov/2.0f) * f.neard;
float near_width = near_height * f.ratio;
float far_height = tan(f.fov/2.0f) * f.fard;
float far_width = far_height * f.ratio;
f.point[0] = nc - up*near_height - right*near_width;
f.point[1] = nc + up*near_height - right*near_width;
f.point[2] = nc + up*near_height + right*near_width;
f.point[3] = nc - up*near_height + right*near_width;
f.point[4] = fc - up*far_height - right*far_width;
f.point[5] = fc + up*far_height - right*far_width;
f.point[6] = fc + up*far_height + right*far_width;
f.point[7] = fc - up*far_height + right*far_width;
}
void ShadowMap::UpdateSplitDist(FrustumData f[MAX_SPLITS], float nd, float fd)
{
float lambda = split_weight;
float ratio = fd/nd;
f[0].neard = nd;
for(int i = 1; i < cur_num_splits; ++i)
{
float si = i / (float)cur_num_splits;
f[i].neard = lambda*(nd*powf(ratio, si)) + (1-lambda)*(nd + (fd - nd)*si);
f[i-1].fard = f[i].neard * 1.005f;
}
f[cur_num_splits-1].fard = fd;
}
float ShadowMap::ApplyCropMatrix(FrustumData& f)
{
float shad_proj[16] = {0.0f};
float shad_crop[16] = {0.0f};
float shad_mvp[16] = {0.0f};
float maxX = -1000.0f;
float maxY = -1000.0f;
float maxZ = 0.0f;
float minX = 1000.0f;
float minY = 1000.0f;
float minZ = 0.0f;
Matrix4x4 nv_mvp;
vec4 transf;
glGetFloatv(GL_MODELVIEW_MATRIX, shad_modelview);
nv_mvp = shad_modelview;
transf = nv_mvp*vec4(f.point[0], 1.0f);
minZ = transf.z;
maxZ = transf.z;
for(int i = 1; i < 8; ++i)
{
transf = nv_mvp*vec4(f.point[i], 1.0f);
if(transf.z > maxZ) maxZ = transf.z;
if(transf.z < minZ) minZ = transf.z;
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -maxZ, -minZ);
glGetFloatv(GL_PROJECTION_MATRIX, shad_proj);
glPushMatrix();
glMultMatrixf(shad_modelview);
glGetFloatv(GL_PROJECTION_MATRIX, shad_mvp);
glPopMatrix();
nv_mvp = shad_mvp;
for(int i = 0; i < 8; ++i)
{
transf = nv_mvp*vec4(f.point[i], 1.0f);
transf.x /=transf.w;
transf.y /=transf.w;
if(transf.x > maxX) maxX = transf.x;
if(transf.x < minX) minX = transf.x;
if(transf.y > maxY) maxY = transf.y;
if(transf.y < minY) minY = transf.y;
}
float scaleX = 2.0f/(maxX - minX);
float scaleY = 2.0f/(maxY - minY);
float offsetX = -0.5f*(maxX + minX)*scaleX;
float offsetY = -0.5f*(maxY + minY)*scaleY;
nv_mvp.Identity();
nv_mvp.matrix[0] = scaleX;
nv_mvp.matrix[5] = scaleY;
nv_mvp.matrix[3] = offsetX;
nv_mvp.matrix[7] = offsetY;
nv_mvp = nv_mvp.Transpose();
memcpy(shad_crop, nv_mvp.matrix, sizeof(float) * 16);
glLoadMatrixf(shad_crop);
glMultMatrixf(shad_proj);
return minZ;
}
void ShadowMap::MakeShadowMap(void)
{
glDisable(GL_TEXTURE_2D);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
gluLookAt(0.0, 0.0, 0.0, -mapData.lightVec.vec[0], -mapData.lightVec.vec[1], -mapData.lightVec.vec[2], -1.0, 0.0, 0.0);
glGetFloatv(GL_MODELVIEW_MATRIX, shad_modelview);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, depth_fb);
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, depth_size, depth_size);
glPolygonOffset(1.0f, 4096.0f);
glEnable(GL_POLYGON_OFFSET_FILL);
// draw all faces since our terrain is not closed.
glDisable(GL_CULL_FACE);
UpdateSplitDist(f, gameSetupData.nearPlane, gameSetupData.farPlane);
for(int i = 0; i < cur_num_splits; ++i)
{
UpdateFrustumPoints(f[i], camera.pos, camera.facing);
float minZ = ApplyCropMatrix(f[i]);
glFramebufferTextureLayerEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depth_tex_ar, 0, i);
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
// draw the scene
physx->Draw(true);
glMatrixMode(GL_PROJECTION);
glMultMatrixf(shad_modelview);
glGetFloatv(GL_PROJECTION_MATRIX, shad_cpm[i]);
}
// revert to normal back face culling as used for rendering
glEnable(GL_CULL_FACE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDisable(GL_POLYGON_OFFSET_FILL);
glPopAttrib();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
//main rendering function
Matrix4x4 nm;
shadowMap->MakeShadowMap();
double aspect = double(gameSetupData.screenWidth) / double(gameSetupData.screenHeight);
float sky_color[4] = {0.8f, mapData.lightVec.vec[1]*0.1f + 0.7f, mapData.lightVec.vec[1]*0.4f + 0.5f, 1.0f};
glClearColor(sky_color[0], sky_color[1], sky_color[2], sky_color[3]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camera.LookAt();
glGetFloatv(GL_MODELVIEW_MATRIX, shadowMap->cam_modelview);
shadowMap->CameraInverse(shadowMap->cam_inverse_modelview, shadowMap->cam_modelview);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(gameSetupData.fov, aspect, shadowMap->f[0].neard, shadowMap->f[shadowMap->cur_num_splits-1].fard);
glGetFloatv(GL_PROJECTION_MATRIX, shadowMap->cam_proj);
for(int i=shadowMap->cur_num_splits; i<MAX_SPLITS; i++)
shadowMap->far_bound[i] = 0;
for(int i = 0; i < shadowMap->cur_num_splits; ++i)
{
shadowMap->far_bound[i] = 0.5f*(-shadowMap->f[i].fard*shadowMap->cam_proj[10]+shadowMap->cam_proj[14])/shadowMap->f[i].fard+0.5f;
glActiveTexture(GL_TEXTURE0+(GLenum)i);
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(MATRIX_BIAS);
glMultMatrixf(shadowMap->shad_cpm[i]);
glMultMatrixf(shadowMap->cam_inverse_modelview);
glGetFloatv(GL_TEXTURE_MATRIX, nm.matrix);
nm.Inverse();
nm.Transpose();
glActiveTexture(GL_TEXTURE0+(GLenum)(i+4));
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(nm.matrix);
}
|
|
Top
|
|
|
|
#242172 - 07/23/08 06:16 PM
Re: Help with Cascading Shadowmapping
[Re: Mars_999]
|
Regular Contributor
  
Registered: 03/09/01
Posts: 224
Loc: Sioux Falls, SD, USA
|
|
|
Top
|
|
|
|
|
24934 Members
12 Forums
52392 Topics
271540 Posts
Max Online: 482 @ 08/11/08 06:19 PM
|
|
|