PDA

View Full Version : shadowmapping problems



Dragon89
05-23-2007, 10:46 AM
im having some problems with shadow mapping... been trying to figure this out for a few hours.. but im about to give up... this is my first time implementing it so i guess ive missed something... any ideas what i might have done wrong?

thx...


const GLdouble bias[] = {0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0};
class CSHADOWMAP
{
public:

Init()
{
ShadowShader = new GLSLProgram("Shaders/TexDefault.vert", "Shaders/ShadowMap.frag", "Shaders/ShadowMap.log");

LightPos = vec3(500,500,500);
size = 1024;

glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &shadowtex);
glBindTexture(GL_TEXTURE_2D, shadowtex);
glTexImage2D(GL_TEXTURE_2D, 0 , GL_DEPTH_COMPONENT, size, size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);


glPushMatrix();
glLoadIdentity();
gluPerspective(45.0f, 1.0f, 1.0f, 10000.0f);
glGetDoublev(GL_MODELVIEW_MATRIX, ProjMatrix);

glLoadIdentity();
gluLookAt(LightPos.x, LightPos.y, LightPos.z,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f);

glGetDoublev(GL_MODELVIEW_MATRIX, ViewMatrix);
glPopMatrix();

}

GLSLProgram* ShadowShader;

int size;

GLuint shadowtex;

vec3 LightPos;

GLdouble ProjMatrix[16];
GLdouble ViewMatrix[16];
};



void CWORLD::RenderShadowPass()
{

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, ShadowMap.shadowtex);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glMatrixMode(GL_PROJECTION);
glLoadMatrixd(ShadowMap.ProjMatrix);

glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(ShadowMap.ViewMatrix);

glViewport(0, 0, ShadowMap.size, ShadowMap.size);

ShadowMap.ShadowShader->use();

glCullFace(GL_FRONT);

Ground.Render(m_Cam->Position, LightPos, vec3(0.0,0.0,0.0));

Veg.Render(m_Cam->Position, LightPos, vec3(0,0,0));

glCullFace(GL_BACK);


glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, ShadowMap.size, ShadowMap.size);

ShadowMap.ShadowShader->disable();


void CWORLD::Render(bool* keys, vec2 MouseCoord, vec2 MouseButton)
{
RenderShadowPass();

Update(keys, MouseCoord, MouseButton);

if (WireFrame)
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
else
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

glViewport(0,0,1024,768);
gluPerspective(45.0f, (GLfloat)1024/(GLfloat)768, 1.0f, 10000.0f);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

m_Cam->Update(keys); // glulookat function

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, ShadowMap.shadowtex);

glMatrixMode(GL_TEXTURE);
glLoadMatrixd(bias);
glMultMatrixd(ShadowMap.ProjMatrix);
glMultMatrixd(ShadowMap.ViewMatrix);
glMatrixMode(GL_MODELVIEW);

Ground.ObjectShader->use();
Ground.ObjectShader->sendUniform("ShadowMap", 0);
Ground.Render(m_Cam->Position, LightPos, vec3(0,0,0));
Ground.ObjectShader->disable();

glEnable( GL_BLEND );
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.3);

Veg.ObjectShader->use();
Veg.ObjectShader->sendUniform("ShadowMap", 0);
Veg.ObjectShader->sendUniform("Time", Time);
Veg.Render(m_Cam->Position, LightPos, vec3(0,0.0,0));

Veg.ObjectShader->disable();

glDisable(GL_ALPHA_TEST);
glDisable( GL_BLEND );


//vertex:
#version 110

varying vec3 ViewDir;
varying vec3 LightDir;

uniform vec3 LightPos;
uniform vec3 CamPos;
uniform vec3 ObjPos;

varying vec4 ProjShadow;
uniform sampler2DShadow ShadowMap;

void main()
{


gl_TexCoord[0] = gl_MultiTexCoord0;
vec3 VertPos = gl_Vertex.xyz;

ProjShadow = gl_TextureMatrix[0] * gl_Vertex;

vec3 Normal = normalize(gl_Normal.xyz);
vec3 Tangent = normalize(gl_Color.xyz);
vec3 BiNormal = cross(Tangent,Normal);

mat3 TBN = mat3(Tangent, BiNormal, Normal);

LightDir = LightPos*TBN;//(LightPos - VertPos)*TBN;
ViewDir = (CamPos - VertPos)*TBN;

gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz,1.0);
}

// fragment

#version 110
varying vec3 LightDir;
varying vec3 ViewDir;


uniform sampler2D TextureMap;
uniform sampler2D NormalMap;
uniform sampler2D OpicatyMap;
uniform sampler2D SpecularMap;

uniform sampler2DShadow ShadowMap;
varying vec4 ProjShadow;

uniform float NormalMapSize;

uniform float Shininess;

const float ParallaxScale = 0.04;

float GetShadow(vec3 TexCoord, vec3 L);

vec3 GetParallax_TexCoord(vec3 TexCoord, vec3 V, float detail, float max);
vec3 GetParallax_Normal(vec2 TexCoord);

vec3 GetLighting_BlinnPhong(vec3 N, vec3 L, vec3 V, vec3 TexCoord, float specamount);

void main()
{
vec3 nViewDir = normalize(ViewDir);
vec3 nLightDir = normalize(LightDir);
vec3 TexCoord = vec3(gl_TexCoord[0].st,0.0);
vec3 Normal = vec3(0.0,0.0,1.0);


TexCoord = GetParallax_TexCoord(TexCoord, nViewDir, 15.0, 10);
Normal = GetParallax_Normal(TexCoord.xy);//texture2D(NormalMap, TexCoord.xy).rgb;


vec4 Color = texture2D(TextureMap, TexCoord.xy).rgba;
vec3 Brightness = GetLighting_BlinnPhong(Normal, nLightDir, nViewDir, TexCoord, Color.a*1.5);

Brightness = shadow2DProj(ShadowMap, ProjShadow).rrr;

gl_FragColor = Brightness.xxxx;//vec4(Brightness.xxxx*Color.rgb, Color.a); ;//TexCoord.xxxx;//

}on the plane im rendering this results in a black area where z > 0 and white where z < 0. and the model shadows i render with Veg.Render are nowhere to be seen...

Komat
05-23-2007, 03:00 PM
When you are posting shaders, post them in original form if possible or, if you really need to simplify them, ensure that anything relevant is still present (i.e. calculation of the ProjShadow varying.)

Only full featured texture units (reported by glGetInteger with enum GL_MAX_TEXTURE_UNITS) have associated texture matrices. There are up to GL_MAX_TEXTURE_IMAGE_UNITS texture units (at least 16 on current GLSL capable hw) which can have bound texture and GL_MAX_TEXTURE_COORD_UNITS texture units (at least 8 on current GLSL capable hw) which can have associated texture coordinates however only first GL_MAX_TEXTURE_UNITS units have texture matrices, texgens and texture environments.

As far as I know no card exposes more than eight full featured texture units and Nvidia cards expose only four of them. The code that setups the texture matrix will attempt to modify texture matrix for currently selected texture unit (GL_TEXTURE9) and it will fail with error if that unit is not full featured one which is almost certain.

You can use the GLIntercept (http://glintercept.nutty.org/) tool to detect errors reported by OpenGL.

Dragon89
05-23-2007, 04:00 PM
thx fo the answer... ive tried changing to GL_TEXTURE0... but now all i get is pure black... doent seem to get any error from shader...

i looked at glintercept.. but i dont quite understand how to use it... ill have to look into it some more..

EDIT:: ive tried to jsut send any random texture instead of the shadowmap.. and then the other texture works... so it seems like im doin somethin wrong with the shadow texture..

Dragon89
05-29-2007, 01:44 PM
ok.. ive been workin some more on this but im still unable to get a depth-component map workin... this is what i do... ive simplified it as much as possible...

i simply render a scene to the FBO and then try to render the FBO on a fullscreen quad... right now all i get is black...

the projection and stuff like that works since it works when using regular RGB textures..

after several hours of searching i finally found that u write to the depth component using gl_FragDepth.. dont know if im using it right though...




// i set up the FBO liek this

size = _size;

glActiveTexture(GL_TEXTURE10);

// Setup our FBO
glGenFramebuffersEXT(1, &amp;fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

// Create the render buffer for depth
glGenRenderbuffersEXT(1, &amp;depthBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size, size);

// Now setup a texture to render to
glGenTextures(1, &amp;img);
glBindTexture(GL_TEXTURE_2D, img);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, size, size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);


//glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
//glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );

// And attach it to the FBO so we can render to it
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, img, 0);

// Attach the depth render buffer to the FBO as it's depth attachment
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind the FBO for now

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);


// i rende rto the shadowmap like this..

#version 110

varying float Depth;

void main()
{
vec4 Pos = gl_TextureMatrix[0] * gl_Vertex;

gl_Position = Pos;
Depth = abs(Pos.z); // since im using ortho projeciton the values are alrdy in range of 0-1
}

#version 110

varying float Depth;

void main()
{
gl_FragDepth = Depth;
}


// i then render to the fullscreenquad liek this
#version 110


void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

}


#version 110

uniform sampler2DShadow Shadow;


void main()
{

vec4 shadmap = shadow2D(Shadow,gl_TexCoord[0].xyz );


gl_FragColor = shadow2D(Shadow,gl_TexCoord[0].xyz);

}one thing i dont udnerstadn is whay shadow2D needs a 3d vector for texture coordinates?

any hlp is very much appreciated!

Komat
05-30-2007, 01:00 AM
Originally posted by Dragon89:
after several hours of searching i finally found that u write to the depth component using gl_FragDepth.. dont know if im using it right though...
While it is possible to modify the resulting depth of fragment, doing so is not necessary unless you need to modify the distribution of depth values and it can significantly reduce performance of the rendering.



one thing i dont udnerstadn is whay shadow2D needs a 3d vector for texture coordinates?
Well that third coordinate is the most important thing the shadow2D needs. The value returned by that function is calculated by comparing value it got in third coordinate with value sampled from the texture. Basically (ignoring the possibility of bilinear filtering for now and using the compare function and compare mode you have): If the value in texture is smaller than value of the third coordinate, black is returned and otherwise white is returned.

To correctly render into GL_DEPTH_COMPONENT textures you need to attach them to GL_DEPTH_ATTACHMENT_EXT attachment point (see example marked as "Render to depth texture with no color attachments" inside EXT_framebuffer_object (http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt) specification.

BTW. glCheckFramebufferStatusEXT checks status of currently bound FBO so calling it when no FBO is bound is not usefull.