2009-11-27 5 views
0

Bonne journée. Je dessine une scène avec des ombres en utilisant la méthode des cartes d'ombre (lorsque nous restituons une scène du point de vue de la lumière pour récupérer le tampon de profondeur, faire de la texture d'ombre et la projeter sur la scène). texture de l'image, tous les autres objets texturés, bien sûr, perdent leur texture. Mais je veux vraiment la scène texturée avec des ombres :) J'ai lu sur la multitexturing, j'ai effectivement essayé de l'appliquer, mais a échoué. Que dois-je faire exactement? (J'ai pris le code de OpenGl superbible) Voici le code de la procédure d'installation principale. J'ai marqué de nouvelles chaînes (pour les multitexturing) avec // < ====Ombres via des shadowmaps et d'autres textures - comment combiner? OpenGL

void SetupRC() 
{ 

     ambientShadowAvailable = GL_TRUE; 


     npotTexturesAvailable = GL_TRUE; 



    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); 

    fprintf(stdout, "Controls:\n"); 
    fprintf(stdout, "\tRight-click for menu\n\n"); 
    fprintf(stdout, "\tx/X\t\tMove +/- in x direction\n"); 
    fprintf(stdout, "\ty/Y\t\tMove +/- in y direction\n"); 
    fprintf(stdout, "\tz/Z\t\tMove +/- in z direction\n\n"); 
    fprintf(stdout, "\tf/F\t\tChange polygon offset factor +/-\n\n"); 
    fprintf(stdout, "\tq\t\tExit demo\n\n"); 

    // Black background 
    glClearColor(0.32f, 0.44f, 0.85f, 0.5f); 

    // Hidden surface removal 
    glEnable(GL_DEPTH_TEST); 
    glDepthFunc(GL_LEQUAL); 
    glPolygonOffset(factor, 0.0f); 

    // Set up some lighting state that never changes 
    glShadeModel(GL_SMOOTH); 
    glEnable(GL_LIGHTING); 
    glEnable(GL_COLOR_MATERIAL); 
    glEnable(GL_NORMALIZE); 
    glEnable(GL_LIGHT0); 

    // Set up some texture state that never changes 
    glActiveTexture(GL_TEXTURE1); //<===== 

    glGenTextures(1, &shadowTextureID); 
    glBindTexture(GL_TEXTURE_2D, shadowTextureID); 
    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_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); 
    // if (ambientShadowAvailable) 
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 
         0.5f); 
    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); 
    ::scene->fog->init(); 
    RegenerateShadowMap(); 
} 

Voici la procédure de génération shadowmap:

 void RegenerateShadowMap(void) 
    { 
     GLfloat lightToSceneDistance, nearPlane, fieldOfView; 
     GLfloat lightModelview[16], lightProjection[16]; 
     GLfloat sceneBoundingRadius = 200.0f; // based on objects in scene 

     // Save the depth precision for where it's useful 
     lightToSceneDistance = sqrt(lightPos[0] * lightPos[0] + 
            lightPos[1] * lightPos[1] + 
            lightPos[2] * lightPos[2]); 
     nearPlane = lightToSceneDistance - sceneBoundingRadius; 
     // Keep the scene filling the depth texture 
     fieldOfView = (GLfloat)m3dRadToDeg(2.0f * atan(sceneBoundingRadius/lightToSceneDistance)); 

     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 
     gluPerspective(fieldOfView, 1.0f, nearPlane, nearPlane + (2.0f * sceneBoundingRadius)); 
     glGetFloatv(GL_PROJECTION_MATRIX, lightProjection); 
     // Switch to light's point of view 
     glMatrixMode(GL_MODELVIEW); 
     glLoadIdentity(); 
     gluLookAt(lightPos[0], lightPos[1], lightPos[2], 
        0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); 
     glGetFloatv(GL_MODELVIEW_MATRIX, lightModelview); 
     glViewport(0, 0, shadowWidth, shadowHeight); 

     // Clear the depth buffer only 
     glClear(GL_DEPTH_BUFFER_BIT); 

     // All we care about here is resulting depth values 
     glShadeModel(GL_FLAT); 
     glDisable(GL_LIGHTING); 
     glDisable(GL_COLOR_MATERIAL); 
     glDisable(GL_NORMALIZE); 
     glActiveTexture(GL_TEXTURE0); //<===== 
     glDisable(GL_TEXTURE_2D); 
     glActiveTexture(GL_TEXTURE1); //<===== 
     glColorMask(0, 0, 0, 0); 

     // Overcome imprecision 
     glEnable(GL_POLYGON_OFFSET_FILL); 

     // Draw objects in the scene except base plane 
     // which never shadows anything 
     DrawModels(GL_FALSE); 

     // Copy depth values into depth texture 
     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 
         0, 0, shadowWidth, shadowHeight, 0); 

     // Restore normal drawing state 
     glShadeModel(GL_SMOOTH); 
     glEnable(GL_LIGHTING); 
     glEnable(GL_COLOR_MATERIAL); 
     glEnable(GL_NORMALIZE); 
     glActiveTexture(GL_TEXTURE0); //<===== 
     glEnable(GL_TEXTURE_2D); 
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
     glColorMask(1, 1, 1, 1); 
     glDisable(GL_POLYGON_OFFSET_FILL); 

     // Set up texture matrix for shadow map projection, 
     // which will be rolled into the eye linear 
     // texture coordinate generation plane equations 
     M3DMatrix44f tempMatrix; 
     m3dLoadIdentity44(tempMatrix); 
     m3dTranslateMatrix44(tempMatrix, 0.5f, 0.5f, 0.5f); 
     m3dScaleMatrix44(tempMatrix, 0.5f, 0.5f, 0.5f); 
     m3dMatrixMultiply44(textureMatrix, tempMatrix, lightProjection); 
     m3dMatrixMultiply44(tempMatrix, textureMatrix, lightModelview); 
     // transpose to get the s, t, r, and q rows for plane equations 
     m3dTransposeMatrix44(textureMatrix, tempMatrix); 

    } 

rendu de la scène proc:

void RenderScene(void) 
{ 
    // Track camera angle 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    if (windowWidth > windowHeight) 
    { 
     GLdouble ar = (GLdouble)windowWidth/(GLdouble)windowHeight; 
     glFrustum(-ar * cameraZoom, ar * cameraZoom, -cameraZoom, cameraZoom, 1.0, 1000.0); 
    } 
    else 
    { 
     GLdouble ar = (GLdouble)windowHeight/(GLdouble)windowWidth; 
     glFrustum(-cameraZoom, cameraZoom, -ar * cameraZoom, ar * cameraZoom, 1.0, 1000.0); 
    } 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(cameraPos[0], cameraPos[1], cameraPos[2], 
       0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); 

    glViewport(0, 0, windowWidth, windowHeight); 

    // Track light position 
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos); 

    // Clear the window with current clearing color 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    if (showShadowMap) 
    { 
     // Display shadow map for educational purposes 
     glActiveTexture(GL_TEXTURE1); //<===== 
     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 
     glMatrixMode(GL_MODELVIEW); 
     glLoadIdentity(); 
     glMatrixMode(GL_TEXTURE); 
     glPushMatrix(); 
     glLoadIdentity(); 
     glEnable(GL_TEXTURE_2D); 
     glDisable(GL_LIGHTING); 
     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); 
     // Show the shadowMap at its actual size relative to window 
     glBegin(GL_QUADS); 
      glTexCoord2f(0.0f, 0.0f); 
      glVertex2f(-1.0f, -1.0f); 
      glTexCoord2f(1.0f, 0.0f); 
      glVertex2f(((GLfloat)shadowWidth/(GLfloat)windowWidth)*2.0f-1.0f, 
         -1.0f); 
      glTexCoord2f(1.0f, 1.0f); 
      glVertex2f(((GLfloat)shadowWidth/(GLfloat)windowWidth)*2.0f-1.0f, 
         ((GLfloat)shadowHeight/(GLfloat)windowHeight)*2.0f-1.0f); 
      glTexCoord2f(0.0f, 1.0f); 
      glVertex2f(-1.0f, 
         ((GLfloat)shadowHeight/(GLfloat)windowHeight)*2.0f-1.0f); 
     glEnd(); 
     glDisable(GL_TEXTURE_2D); 
     glEnable(GL_LIGHTING); 
     glPopMatrix(); 
     glMatrixMode(GL_PROJECTION); 
     gluPerspective(45.0f, 1.0f, 1.0f, 1000.0f); 
     glMatrixMode(GL_MODELVIEW); 
    } 
    else if (noShadows) 
    { 
     // Set up some simple lighting 
     glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); 
     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); 

     // Draw objects in the scene including base plane 
     DrawModels(GL_TRUE); 
    } 
    else 
    { 
     if (!ambientShadowAvailable) 
     { 
      GLfloat lowAmbient[4] = {0.1f, 0.1f, 0.1f, 1.0f}; 
      GLfloat lowDiffuse[4] = {0.35f, 0.35f, 0.35f, 1.0f}; 

      // Because there is no support for an "ambient" 
      // shadow compare fail value, we'll have to 
      // draw an ambient pass first... 
      glLightfv(GL_LIGHT0, GL_AMBIENT, lowAmbient); 
      glLightfv(GL_LIGHT0, GL_DIFFUSE, lowDiffuse); 

      // Draw objects in the scene, including base plane 
      DrawModels(GL_TRUE); 

      // Enable alpha test so that shadowed fragments are discarded 
      glAlphaFunc(GL_GREATER, 0.9f); 
      glEnable(GL_ALPHA_TEST); 
     } 
     glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); 
     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); 

     // Set up shadow comparison 
     glActiveTexture(GL_TEXTURE1); //<===== 
     glEnable(GL_TEXTURE_2D); 
     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, 
         GL_COMPARE_R_TO_TEXTURE); 

     // Set up the eye plane for projecting the shadow map on the scene 
     glEnable(GL_TEXTURE_GEN_S); 
     glEnable(GL_TEXTURE_GEN_T); 
     glEnable(GL_TEXTURE_GEN_R); 
     glEnable(GL_TEXTURE_GEN_Q); 
     glTexGenfv(GL_S, GL_EYE_PLANE, &textureMatrix[0]); 
     glTexGenfv(GL_T, GL_EYE_PLANE, &textureMatrix[4]); 
     glTexGenfv(GL_R, GL_EYE_PLANE, &textureMatrix[8]); 
     glTexGenfv(GL_Q, GL_EYE_PLANE, &textureMatrix[12]); 

     // Draw objects in the scene, including base plane 
     DrawModels(GL_TRUE); 
     //glPushMatrix(); 
     //glScalef(1, -1, 1); 
     //DrawModels(GL_TRUE); 
     //glPopMatrix(); 
     glDisable(GL_ALPHA_TEST); 
     glDisable(GL_TEXTURE_2D); 
     glDisable(GL_TEXTURE_GEN_S); 
     glDisable(GL_TEXTURE_GEN_T); 
     glDisable(GL_TEXTURE_GEN_R); 
     glDisable(GL_TEXTURE_GEN_Q); 
    } 

    if (glGetError() != GL_NO_ERROR) 
     fprintf(stderr, "GL Error!\n"); 
    //glBindTexture 
    // Flush drawing commands 
    glutSwapBuffers(); 
    //RegenerateShadowMap(); 

} 

Et une exemple d'objet texturé dessiner:

CTeapot::CTeapot(std::string fn, float s, float iX, float iY, float iZ) 
{ 
    this->setCoords(iX, iY, iZ); 
    this->size = s; 
    glActiveTexture(GL_TEXTURE0); //<===== 
    try 
    { 
    this->texture = new C2DTexture(fn); 
    } 
    catch(ERR::CError err) 
    { 
     throw err; 
    } 
    glActiveTexture(GL_TEXTURE1); //<===== 
} 

void CTeapot::draw() 
{ 
    glPushMatrix(); 
    glTranslatef(this->coords[0], this->coords[1], this->coords[2]); 
    if(this->angle[0] != 0.0f) 
     glRotatef(this->angle[0], 1.0f, 0.0f, 0.0f); 
    if(this->angle[1] != 0.0f) 
     glRotatef(this->angle[1], 0.0f, 1.0f, 0.0f); 
    if(this->angle[2] != 0.0f) 
     glRotatef(this->angle[2], 0.0f, 0.0f, 1.0f); 
    glScalef(this->size, this->size, this->size); 
    glActiveTexture(GL_TEXTURE0); //<===== 
    //glEnable(GL_TEXTURE_2D); 
    glBindTexture(GL_TEXTURE_2D, this->texture->getGLTexture()); 
    glutSolidTeapot(this->size); 
    glPopMatrix(); 
    glActiveTexture(GL_TEXTURE1); //<===== 
    //glEnable(GL_TEXTURE_2D); 
} 

C2DTexture texture generaton proc:

C2DTexture::C2DTexture(std::string fn) 
{ 
    this->filename = fn; 
    this->imgTexture = auxDIBImageLoad(this->filename.c_str()); 
    if(this->imgTexture == NULL) 
     throw ERR::CError(ERR::ERR_NOSUCHFILE, ERR::ERR_NOSUCHFILETEXT + this->filename); 
    // Creating a texture 
    glGenTextures(1, &this->glTexture); 
    glBindTexture(GL_TEXTURE_2D, this->glTexture); 
    // Setting filters 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, 3, this->imgTexture->sizeX, this->imgTexture->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, this->imgTexture->data); 
} 

Répondre

3

Vous avez essayé d'appliquer multi-texturing? Cela n'apparaît pas dans votre code. Vous avez besoin de l'utiliser. Une unité de texture pour la texture d'ombre, une pour votre carte diffuse. Si vous avez essayé, vous devriez montrer le code avec multi-texturing.

La texturation multiple est gérée par glActiveTexture (et pour la fonction fixe que vous semblez utiliser, glClientActiveTexture gère les spécifications de coordonnées de texture).

quelques conseils:

  • il est plus facile de comprendre exactement ce que vous faites si vous utilisez shaders.
  • Vous souhaitez mapper la texture de profondeur à l'unité de texture 1: la configuration de l'unité de texture pour le mappage d'ombre doit être précédée d'un glActiveTexture(GL_TEXTURE1) - BindTexture, TexGen et l'option Enable/Disable associée à la texturation. Bien sûr, vous devez revenir à l'unité de texture 0 pour le reste.
  • Vous ne voulez pas de textures lorsque vous dessinez sur la carte de profondeur.
  • Il est plus rapide de dessiner directement à la texture avec l'extension framebuffer_object, que de copier ce

Hope this helps.

Edit: Depuis que vous avez changé tout à fait un peu votre question, permettez-moi d'ajouter quelques conseils et des réponses à vos commentaires:

Une unité de texture unique sera toujours chercher à partir d'un seul objet de texture. Vous utilisez glActiveTexture suivi de glBindTexture pour spécifier la texture à extraire de cette unité de texture. Notez que pour obtenir une texturation sur cette unité, vous devez toujours appeler glEnable(GL_TEXTURE_2D) pour cette unité. Ce qui s'applique en premier ... Eh bien, c'est ici que l'utilisation de shaders simplifie énormément la discussion.En général, l'ordre d'application dépend entièrement de la fragmentation mathématique que vous souhaitez obtenir. Mettons la nomenclature suivante:

  • T_0 le résultat de la première texture Fetch,
  • T_1 le résultat de la seconde texture chercher.
  • C_f La couleur d'entrée qui OpenGL calculée et pixellisée pour ce fragment (Vous utilisez l'éclairage de fonction fixe, c'est ce dont je parle)
  • C_o La couleur finale du fragment
  • T_s le résultat de l'extraction de texture d'ombre,
  • T_d le résultat de l'analyse de texture diffuse.

Le résultat que vous obtiendrez, avec 2 unités de texture activée, est quelque chose comme

C_o = TexEnv1(TexEnv0(C_f,T_0), T_1) 

Le résultat vous besoin est probablement

C_o = C_f * T_s * T_d 

Qu'est-ce que cela nous dit?

  • pour mettre en œuvre les multiplications, vous voulez moduler comme TexEnv pour les deux unités de texture 0 et une unité de texture 1
  • l'ordre n'a pas d'importance dans ce cas (car la multiplication -aka modulation- est commutative)
  • ce que j'ai montré est à peu près le shader code. Beaucoup plus facile à lire que les paramètres TexEnv.

Maintenant, pour revenir à votre problème ... À ce moment-là, je l'espère, vous comprenez ce que OpenGL vous déclarez devez venez tirer le temps. Cependant, essayer de savoir exactement quel état vous avez réellement de lire votre code est un exercice périlleux au mieux. Si vous êtes sérieux au sujet de l'utilisation d'OpenGL, je recommande l'un des suivants:

  • utiliser un débogueur OpenGL. Il existe un certain nombre d'outils qui montreront l'état exact à un appel de tirage spécifique.
  • Créez votre propre suivi d'état de débogage
  • vider l'état d'intérêt OpenGL au moment du tirage. OpenGL fournit des méthodes getter pour chaque bit de son état (ou presque, je ne vais pas entrer dans les détails les plus sales ici), vous ne voulez faire cela qu'à des fins de débogage, Getters n'est pas garanti pour être efficace du tout).
+0

>> Vous avez essayé d'appliquer la multi-texturation? Cela n'apparaît pas dans votre code. Oui, j'ai essayé, j'ai échoué et je l'ai enlevé :) Je devais savoir ceci: >> vous voulez mapper la texture de profondeur à l'unité de texture 1: la configuration de l'unité de texture pour la projection d'ombre doit être précédée par un glActiveTexture (GL_TEXTURE1) - la BindTexture, le TexGen, et le texturing lié Enable/Disable.Bien sûr, vous devez revenir à l'unité de texture 0 pour le reste Je vais essayer à nouveau en utilisant votre conseil, puis dire si cela a fonctionné :) – Irene

+0

>> Il est plus rapide de dessiner directement à la texture avec le framebuffer_object extension, que pour copier Merci! Je vais essayer – Irene

+0

Et j'ai une autre question: est une unité de texture pour une texture? Ou je peux lier plus de textures comme toujours dans un calque courant? – Irene

Questions connexes