Sign in to follow this  
dirtysanchez

Heightmap Shadowmapping

Recommended Posts

Before i start, a few screenshots would help you to understand the issue.. We have switched from tiles to Heightmaps in our MMO game, the Heightmap is built from triangles and it is 256x256. Shadowmapping is implemented to allow the movement of the sun and shadow during the day period, it works great but has a minor 'problem', nah, two problems actually. 1) If you look closer to the screen, you can see Shadowmapping is somehow doing artifacts on some parts of the HM. I have noticed that this happens only when a source of light (the one i am rendering the shadowmap from) is far away or too high. Any chance to overcome this? 2) ATI does like the : glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.5f); Call, Nvidia does not - how do i get those shadowmaps a bit transparent? It would look more realistic and would allow to blend them in the morning / when the night is coming.. On this shot you see the models having the same problem, well it has been fixed by switching to our own format - as MD3 didn't look good and were not skeletal animated. I belive also, as polycount is higher now on our models - this problem dissapeared.. I am trying to find out, what exactly artefacts the Shadowmapping ? Many thanks for any help, best regards - P.

Share this post


Link to post
Share on other sites
How about ambient shadows or set a weaker light for the shadow pass?
void BeginShadow()
{
glTexGenfv(GL_S, GL_EYE_PLANE, row0);
glTexGenfv(GL_T, GL_EYE_PLANE, row1);
glTexGenfv(GL_R, GL_EYE_PLANE, row2);
glTexGenfv(GL_Q, GL_EYE_PLANE, row3);

glEnable(GL_ALPHA_TEST);
glEnable(GL_TEXTURE_2D);

glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
}

...
...
// first pass (shadows)

glActiveTextureARB(GL_TEXTURE1_ARB);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER);
glPushAttrib(GL_ENABLE_BIT);
BeginShadow();

glLightfv(GL_LIGHT0, GL_DIFFUSE, clr);
RenderScene();

// second pass

glActiveTextureARB(GL_TEXTURE1_ARB);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );

glLightfv(GL_LIGHT0, GL_DIFFUSE, clr2);
RenderScene();...



clr is the darker (shadow) color clr2 is the actual light color.
Or you could do the same, but with altering the ambient color of the light source.

And for the artifact, maybe the far plane of the shadow projection should be further.
The far plane will be a problem for large scenes, I assume you use some king of View fitting (bounding box) for setting up the shadow projection matrix.
Or maybe the best thing would be to use cascade shadow mapping

Share this post


Link to post
Share on other sites
Great, thanks for the reply!


I don't think this is a far plane problem with the terrain, i would rather say this might come from the terrain mesh.

I am not doing:


for(int x=0;x<256;x++){
for(int y=0;y<256;y++){
..draw_triangle()..
}
}




the way i draw the HM is by:


#define STEP_SIZE 2
for(int x=0;x<256;x+=STEP_SIZE){
for(int y=0;y<256;y+=STEP_SIZE){
..draw_triangle()..
}
}



Can this cause a problem too ?

Share this post


Link to post
Share on other sites
No, if you render it in the same way in the shadow map rendering pass.
I think you should add some more screenshots, maybe the artifact is infact the shadow of an other hill. If not, it will be an issue with the shadow projection matrix (too little or something).

So the 'lighter shadows' thing worked?

[Edited by - szecs on September 15, 2009 1:23:30 PM]

Share this post


Link to post
Share on other sites
Szecs,


sorry for being late with this answer - i was off for a few days.


The transparent shadowmap 'trick' did not work, i render the scene in first pass with a light


float shadowlightcolor[4];
shadowlightcolor[0]=WORLD.lightcolor[0]*0.1;
shadowlightcolor[1]=WORLD.lightcolor[1]*0.1;
shadowlightcolor[2]=WORLD.lightcolor[2]*0.1;
shadowlightcolor[3]=WORLD.lightcolor[3]*0.1;

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);// Turn on lighting
glLightfv( GL_LIGHT0, GL_AMBIENT, shadowlightcolor);




and second pass with normal light (without *0.1) and the shadow is still totally black..



Damn i'm missing whole realism by this.. :/

[Edited by - dirtysanchez on September 14, 2009 2:43:34 PM]

Share this post


Link to post
Share on other sites
AS you can see the code that I posted previously, I'm altering the diffuse light color, and don't alter the ambient component.
I usually work with high ambient in open scenes, so if you set 0,0,0,1 for diffuse color for the light, it should work. Alpha has to be 1.
And try to set higher light for the shadows.
If you think about that, shadows are ambient shadows in real life.
I usually set a light blue for ambient, because the sky is the main source of it in outdoor scenes.

your other thread
It worked nicely there, what happened?
I don't want to offend you, but you keep posting threads about shadow-mapping, And you are asking questions, that you already solved in a previous thread. Or these are completely different projects? Or one solution messes up the working things?

EDIT: you didn't use lighting there, so I'm sorry about that!

Share this post


Link to post
Share on other sites
szecs,

the link you have sent before - was a total disaster i made, there was a whole scene blending problem so everything in fact was blended - even the shadowmaps got blended somehow... And true, no lightning in that scene


I had to rewrite the whole rendering process and start all over again to have it in total default and running correctly, thus the shadowmapping transparency issue now.

Now to the right point, sorry for that i sound sometimes like repeating but continously i'm coming back to my root issue - transparent shadow maps on non ATI cards. I'll check your solution and if this will work i'll close down this subject and consider you as my guru ;)

Sorry anyways, hope i'll get this resolved.

[Edited by - dirtysanchez on September 15, 2009 3:27:42 AM]

Share this post


Link to post
Share on other sites
Ok, here is the update.


I render the lightning in first pass with:


float shadowlightcolor[4];
shadowlightcolor[0]=0.0f;
shadowlightcolor[1]=0.0f;
shadowlightcolor[2]=0.0f;
shadowlightcolor[3]=1.0f;
glLightfv( GL_LIGHT0, GL_DIFFUSE, shadowlightcolor);
shadowlightcolor[0]=110.0f;
shadowlightcolor[1]=110.0f;
shadowlightcolor[2]=110.0f;
shadowlightcolor[3]=111.0f;
glLightfv( GL_LIGHT0, GL_AMBIENT, shadowlightcolor);

//Draw the Terrain and Objects now//

glColor4f(0.3,0.3,0.3,1.0);
RenderHeightMap_notex(g_HeightMap);
glEnable(GL_TEXTURE_2D);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0.05);
glColor4f(0.3,0.3,0.3,1.0);
RENDER_gameobjects(0);
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);






The second pass is rendered with:


glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv( GL_LIGHT0, GL_DIFFUSE, WORLD.lightcolor ); // Set our ambience values (Default color without direct light)
glLightfv( GL_LIGHT0, GL_AMBIENT, WORLD.lightcolor ); // Set our ambience values (Default color without direct light)

glPushMatrix();
glTranslatef(0,0,0);
RenderHeightMap(g_HeightMap);
glPopMatrix();
glDisable(GL_TEXTURE_2D);





So i apply diffuse 0,0,0,1 to the first pass and high ambient value,

then i come back in second pass to WORLD.lightcolor which is set to be 5.0,5.0,5.0,1.0 for now.


Still the same..

Any chance for you to post your shadowmap texture during from the first pass, mine does not change - if i mangle with the diffuse/ambient in first pass..

Share this post


Link to post
Share on other sites
void BeginShadow()
{
glTexGenfv(GL_S, GL_EYE_PLANE, row0);
glTexGenfv(GL_T, GL_EYE_PLANE, row1);
glTexGenfv(GL_R, GL_EYE_PLANE, row2);
glTexGenfv(GL_Q, GL_EYE_PLANE, row3);

glEnable(GL_ALPHA_TEST);
glEnable(GL_TEXTURE_2D);

glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
}

...
...
// first pass (shadows)

glColor4f(1, 1, 1, 0); //!!!!!!!!!!!!!!!
glColorMask(1, 1, 1, 1);

float clr[] = {0.3,0.3,0.3,1};
float clr2[] = {1,1,1,1};

glActiveTextureARB(GL_TEXTURE1_ARB);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER);
glPushAttrib(GL_ENABLE_BIT);
BeginShadow();

glLightfv(GL_LIGHT0, GL_DIFFUSE, clr);
RenderScene();

// second pass

glActiveTextureARB(GL_TEXTURE1_ARB);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );

glLightfv(GL_LIGHT0, GL_DIFFUSE, clr2);
RenderScene();...
glPopAttrib();


Ambient (set at initialization): float ambient0[] = { 1.6, 1.6, 1.6, 1 };
You can copy the code completely in yours.

Share this post


Link to post
Share on other sites
Sh!@# still the same..



FIRST PASS


//SHADOW PASS 1
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glViewport(0, 0, (int)SHADOW_WIDTH, (int)SHADOW_HEIGHT);
glMatrixMode(GL_PROJECTION);

float ambient0[] = { 1.6, 1.6, 1.6, 1 };
float clr[] = {0.3,0.3,0.3,1};
glEnable(GL_LIGHTING);
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient0 );
glLightfv(GL_LIGHT0, GL_DIFFUSE, clr);
glColor4f(1, 1, 1, 0); //!!!!!!!!!!!!!!!
glColorMask(1, 1, 1, 1);

glPushMatrix();
glLoadMatrixf(g_mProjection);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(g_mModelView);
glPolygonOffset( 1.5f,0.0f);
glEnable(GL_POLYGON_OFFSET_FILL);
RenderHeightMap_notex(g_HeightMap);
glEnable(GL_TEXTURE_2D);
// glEnable(GL_ALPHA_TEST);
// glAlphaFunc(GL_GREATER,0.05);
RENDER_gameobjects(0);
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);

glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, shadowtexture[SHADOW_ID]);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, (int)SHADOW_WIDTH, (int)SHADOW_HEIGHT);
glDisable(GL_POLYGON_OFFSET_FILL);
glViewport(0, 0, (int)GAME_X, (int)GAME_Y);

glMatrixMode(GL_PROJECTION);

glPopMatrix();





Lets go into details for every pass i make.

Anything wrong here? i disabled alpha testing on the models to have it clear..

Share this post


Link to post
Share on other sites
I think that's irrelevant, since GL_TEXTURE_COMPARE_FUNC_ARB returns 1.0 or 0.0, but
glAlphaFunc(GL_GREATER,0.5);

But I think I can't help you more, or do you want me to post my entire code here?

I can't see

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER);
and
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);

Anywhere in your code
COPY MY CODE, REPLACE RenderScene WITH YOURS!

Or my codes are invisible for you?
My last reply, sorry, rate me down if you want.

Share this post


Link to post
Share on other sites
Last question szecs


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,GL_COMPARE_R_TO_TEXTURE_ARB);

do you use that ? what compare mode do you apply for

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);

Share this post


Link to post
Share on other sites
Did you see this code snippet he posted? Also, you didn't copy his code line for line like he instructed you to do. Please read his replies to you again line for line.


void BeginShadow()
{
glTexGenfv(GL_S, GL_EYE_PLANE, row0);
glTexGenfv(GL_T, GL_EYE_PLANE, row1);
glTexGenfv(GL_R, GL_EYE_PLANE, row2);
glTexGenfv(GL_Q, GL_EYE_PLANE, row3);

glEnable(GL_ALPHA_TEST);
glEnable(GL_TEXTURE_2D);

glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
}

...
...
// first pass (shadows)

glColor4f(1, 1, 1, 0); //!!!!!!!!!!!!!!!
glColorMask(1, 1, 1, 1);

float clr[] = {0.3,0.3,0.3,1};
float clr2[] = {1,1,1,1};

glActiveTextureARB(GL_TEXTURE1_ARB);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER);
glPushAttrib(GL_ENABLE_BIT);
BeginShadow();

glLightfv(GL_LIGHT0, GL_DIFFUSE, clr);
RenderScene();

// second pass

glActiveTextureARB(GL_TEXTURE1_ARB);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );

glLightfv(GL_LIGHT0, GL_DIFFUSE, clr2);
RenderScene();...
glPopAttrib();

Share this post


Link to post
Share on other sites
void init_ShadowMap()
{
glGenTextures(1, &ShadowTextID);

glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, ShadowTextID);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//NEAREST);

glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHDW_MAP_SIZE, SHDW_MAP_SIZE, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
}

Share this post


Link to post
Share on other sites
I think I wasn't clear:
in the pass, that I call first, the shadowed areas are drawn, but the shadowmaps are being generated before it! (in the "zero" pass), but I didn't post that code, since it works fine for you.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this