Page 1 of 2 1 2 >
Topic Options
Rate This Topic
#242041 - 07/21/08 07:25 PM Help with Cascading Shadowmapping
Mars_999 Offline
Regular Contributor
****

Registered: 03/09/01
Posts: 224
Loc: Sioux Falls, SD, USA
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?


Top
#242043 - 07/21/08 09:38 PM Re: Help with Cascading Shadowmapping [Re: Mars_999]
oc2k1 Offline
Regular Contributor
*****

Registered: 01/30/07
Posts: 171
Loc: germany
Looks like a (near) clipping problem, check your shadow volumes...
_________________________
Lumina platform independent GLSL IDE

Top
#242044 - 07/21/08 11:06 PM Re: Help with Cascading Shadowmapping [Re: oc2k1]
Mars_999 Offline
Regular Contributor
****

Registered: 03/09/01
Posts: 224
Loc: Sioux Falls, SD, USA
Thanks for reply, but I am not sure what you mean by check the shadow volumes? I have moved the near plane to like .1 and didn't fix anything? If that is what you mean?

If I move my split_weights to like .4 or less it stops happening, but the resolution becomes crap. Also it only happens on my terrain mesh never on the models?

Top
#242057 - 07/22/08 03:52 AM Re: Help with Cascading Shadowmapping [Re: Mars_999]
Eosie Offline
Regular Contributor
*****

Registered: 01/19/04
Posts: 125
Loc: Czech Republic, EU
This looks like a self-shadowing issue. Try to increase your depth bias.

Top
#242064 - 07/22/08 04:31 AM Re: Help with Cascading Shadowmapping [Re: Eosie]
zed Offline
OpenGL Guru
*****

Registered: 07/06/00
Posts: 2600
Loc: S41.16.25 E173.16.21
what issue?, if u mean the zfighting artifacts on the terrain (cause of the hills geometry)

then u will have to do something like Eosie suggested eg depth bias or PolygonOffset (theres plenty of info on the web about this, most shadowmap papers from a few years ago mention it)

also only render either the front or black faces into the depthbuffer (normally the back, ie the opposite to the normal rendering)

another method is to have your away from light facing normals + the shadowambient color to be similar (like reallife)
_________________________
www.zedzeek.com

Top
#242090 - 07/22/08 10:31 AM Re: Help with Cascading Shadowmapping [Re: Mars_999]
innuendo Offline
Newbie

Registered: 06/27/08
Posts: 40
Loc: Russia, Moscow
 Originally Posted By: Mars_999
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]
Mars_999 Offline
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.

 Code:
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
#242170 - 07/23/08 04:45 PM Re: Help with Cascading Shadowmapping [Re: Mars_999]
Mars_999 Offline
Regular Contributor
****

Registered: 03/09/01
Posts: 224
Loc: Sioux Falls, SD, USA
Anyone? I am at my sanity's end. I have tried everything I can think of, I have used Nvidia's math lib instead of my own, and still I get the chopped off effect. I have put my camera class in their demo, and my camera works fine with there demo. Argh...

Top
#242172 - 07/23/08 06:16 PM Re: Help with Cascading Shadowmapping [Re: Mars_999]
Mars_999 Offline
Regular Contributor
****

Registered: 03/09/01
Posts: 224
Loc: Sioux Falls, SD, USA
delete

Top
#242175 - 07/23/08 10:23 PM Re: Help with Cascading Shadowmapping [Re: Mars_999]
zed Offline
OpenGL Guru
*****

Registered: 07/06/00
Posts: 2600
Loc: S41.16.25 E173.16.21
theres really no way to fix it easily.

have u tried making the shading away from the sun darker (more like reality), ie both areas arent recieving direct sunlight thats only indirect light thats why theyre darker

this should lessen its appearence.

see this video here
http://www.gametrailers.com/player/usermovies/242790.html
the same precision errors are there also but theyre very difficult to spot. (true its pretty dark, but even in full sunlight theyre lesser)

another way to lessen it is to do some shadowmap softening eg a blur (perhaps screenspace) or PCF or VSM


Edited by zed (07/23/08 10:24 PM)
_________________________
www.zedzeek.com

Top
Page 1 of 2 1 2 >


Moderator:  dorbie, Eric, Tom Nuydens, Zengar 
Who's Online
4 registered (Nonozor, Irena, Maire Nicolas, aronsatie), 54 Guests and 95 Spiders online.
Key: Admin, Global Mod, Mod
Newest Members
Nonozor, Maire Nicolas, minakshee, Koter, pixelwrangler
24934 Registered Users
Top Posters (30 Days)
Alfonse Reinheart 152
ZbuffeR 92
Dark Photon 73
marshats 47
Brolingstanz 44
Ilian Dinev 41
Iulian B 38
Stephen A 37
Kip Warner 28
devdept 26
igorgiv 23
skynet 23
Pierre 23
DarkShadow44 23
Yann LE PETITCORPS 22
scratt 21
Abdallah DIB 21
Aleksandar 20
mikeynovemberoscar 19
Pierre Boudier 19
Forum Stats
24934 Members
12 Forums
52392 Topics
271540 Posts

Max Online: 482 @ 08/11/08 06:19 PM