简体   繁体   中英

Sphere image texture is distorted by shadow map - OpenGL

I am doing shadow mapping in OpenGL using the fixed-function pipeline, not shaders. I have managed to implement the shadow maps fine, but without textures on the thing that shadows are cast on.

When I add my texture to my sphere just before it renders, it appears distorted. I can move around my light source and it distorts it more/less depending on the position of the light source.

What are the possible causes of this?

This is my glLightfv(GL_LIGHT1, GL_DIFFUSE, white); glLightfv(GL_LIGHT1, GL_SPECULAR, white);

//Calculate texture matrix for projection
//This matrix takes us from eye space to the light's clip space
//It is postmultiplied by the inverse of the current view matrix when specifying texgen
static MATRIX4X4 biasMatrix(0.5f, 0.0f, 0.0f, 0.0f,
                            0.0f, 0.5f, 0.0f, 0.0f,
                            0.0f, 0.0f, 0.5f, 0.0f,
                            0.5f, 0.5f, 0.5f, 1.0f);    //bias from [-1, 1] to [0, 1]
MATRIX4X4 textureMatrix=biasMatrix*lightProjectionMatrix*lightViewMatrix;

//Set up texture coordinate generation.
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGenfv(GL_S, GL_EYE_PLANE, textureMatrix.GetRow(0));
glEnable(GL_TEXTURE_GEN_S);

glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGenfv(GL_T, GL_EYE_PLANE, textureMatrix.GetRow(1));
glEnable(GL_TEXTURE_GEN_T);

glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGenfv(GL_R, GL_EYE_PLANE, textureMatrix.GetRow(2));
glEnable(GL_TEXTURE_GEN_R);

glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGenfv(GL_Q, GL_EYE_PLANE, textureMatrix.GetRow(3));
glEnable(GL_TEXTURE_GEN_Q);

//Bind & enable shadow map texture
glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
glEnable(GL_TEXTURE_2D);

//Enable shadow comparison
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);

//Shadow comparison should be true (ie not in shadow) if r<=texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);

//Shadow comparison should generate an INTENSITY result
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);

//Set alpha test to discard false comparisons
glAlphaFunc(GL_GEQUAL, 0.99f);
glEnable(GL_ALPHA_TEST);
glColor4f(1.0f, 0.0f, 1.0f, 1.0f);
world->textured = true;
renderObjects();

sun->center = Vertex(lightX, lightY, lightZ);
glDisable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
  glColor3f(1,1,0);
  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;  
  glTranslatef(sun->center.x, sun->center.y, sun->center.z);
  sun->lighting = false;
  sun->z = -lightZ +1;
  sun->render();
  glColor3f(1, 1, 1);
glDisable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);

//Disable textures and texgen
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
//Restore other states
glDisable(GL_LIGHTING);
glDisable(GL_ALPHA_TEST);

//reset matrices
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
update();

Render Objects:

void Widget::renderObjects()
{
  glPushMatrix();
    glColor4f(1.0, 1.0, 1.0, 1.0);
    glPushMatrix();
      //glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emission); 
      //glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); 
      arcBall->q.rotate();
      world->render();
      glPushMatrix();
        torso->frame = frame;
        torso->draw();
        glPushMatrix();
          renderParticles();
        glPopMatrix();
      glPopMatrix();
    glPopMatrix();
  glPopMatrix();
}

And for kicks, here's my first & second pass too.

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
lightPosition = VECTOR3D(lightX, lightY, lightZ);
glLoadIdentity();
gluLookAt(  lightPosition.x, lightPosition.y, lightPosition.z,
            0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f);
glGetFloatv(GL_MODELVIEW_MATRIX, lightViewMatrix);




glMatrixMode(GL_PROJECTION);
glLoadMatrixf(lightProjectionMatrix);

glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(lightViewMatrix);

//Use viewport the same size as the shadow map
glViewport(0, 0, shadowMapSize, shadowMapSize);

//Draw back faces into the shadow map
glCullFace(GL_FRONT);

//Disable color writes, and use flat shading for speed
glShadeModel(GL_FLAT);
glColorMask(0, 0, 0, 0);
//Draw the scene
renderObjects();

//Read the depth buffer into the shadow map texture
glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, shadowMapSize, shadowMapSize);

//restore states
glCullFace(GL_BACK);
glShadeModel(GL_SMOOTH);
glColorMask(1, 1, 1, 1);


//2nd pass - Draw from camera's point of view
glClear(GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_PROJECTION);
glLoadMatrixf(cameraProjectionMatrix);

glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(cameraViewMatrix);

glViewport(0, 0, windowWidth, windowHeight);

//Use dim light to represent shadowed areas
glLightfv(GL_LIGHT1, GL_POSITION, VECTOR4D(lightPosition));
glLightfv(GL_LIGHT1, GL_AMBIENT, white*0.2f);
glLightfv(GL_LIGHT1, GL_DIFFUSE, white*0.2f);
glLightfv(GL_LIGHT1, GL_SPECULAR, black);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);

renderObjects();

Since you are doing this using the fixed-function pipeline, I imagine you are using texture matrices (a per-Texture Image Unit state).

Are you sure the texture matrices are setup appropriately when you try to sample from your regular textures? It sounds to me like you are using the same matrices for your diffuse texture as you used for your shadow map. Generally you would want identity matrices when sampling everything except the shadow map.

Consider the following example:

glActiveTexture (GL_TEXTURE0);
glMatrixMode    (GL_TEXTURE);
glLoadMatrixf   (shadow_matrix);

glBindTexture   (shadow_map);

// Draw shadow pass

glBindTexture   (diffuse_map);

// Draw the base diffuse pass

In this example, the second draw is still being affected by the matrix you had to load for the shadow map. You can solve this two ways:

  1. Dedicate a Texture Image Unit to sampling your shadow map
  2. Push/pop or load an identity texture matrix after you apply your shadow map

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM