2009-11-27 49 views
0

美好的一天。 我使用陰影貼圖方法繪製了一個帶有陰影的場景(當我們從光照角度渲染場景以檢索深度緩衝區,製作陰影貼圖並將其投影到場景中時,從相機角度呈現) 當我使用陰影貼圖紋理,所有其他紋理對象,當然會丟失紋理。 但我真的很想要帶紋理的場景與陰影:) 我讀過多紋理,我居然嘗試應用它,但失敗了。 我該做什麼? (我從OpenGl超級寶典中取得代碼) 以下是主要設置程序的代碼。我打上// < ====新的字符串(那些多紋理)通過shadowmaps和其他紋理的陰影 - 如何結合? 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(); 
} 

這裏是陰影貼圖生成過程:

 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); 

    } 

場景渲染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(); 

} 

而一個紋理對象繪製示例:

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質地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); 
} 

回答

3

您嘗試應用多紋理?它不會顯示在您的代碼中。你確實需要使用它。一個用於陰影紋理的紋理單元,一個用於漫反射貼圖。如果你嘗試過,你應該用多紋理顯示代碼。

通過glActiveTexture(以及您似乎正在使用的固定功能,glClientActiveTexture處理紋理座標規範)處理多紋理。

建議的一些片段:

  • 很容易理解,如果你使用的着色器,你在做什麼。
  • 想要將深度紋理映射到紋理單元1:需要在陰影映射的紋理單元設置之後加上glActiveTexture(GL_TEXTURE1) - BindTexture,TexGen和紋理相關的啓用/禁用。當然,您需要切換回紋理單元0。
  • 當您繪製到深度圖時,不需要任何紋理。
  • 這是更快地直接繪製與framebuffer_object擴展質地,而不是複製到

希望這有助於。

編輯:既然你已經改變了不少你的問題,讓我的諮詢和解答的一些作品添加到您的評論:

單紋理單元總是會從一個單一的紋理對象獲取。您可以使用glActiveTexture,然後使用glBindTexture來指定將從該紋理單元中提取的紋理。請注意,要在該單元上獲得任何紋理,您仍需要爲該單元撥打glEnable(GL_TEXTURE_2D)

首先應用什麼...嗯,這是使用着色器簡化了很多討論的地方。一般來說,應用程序的順序完全取決於你想要結束的片段數學。讓我們把下面的命名:

  • T_0第一紋理的結果寄存,
  • T_1第二紋理的結果寄存。
  • C_f輸入顏色OpenGL的計算和光柵化該片段(您正在使用的固定功能照明,這就是我說的)
  • C_o片段
  • T_s結果的最終顏色陰影紋理獲取,
  • T_d漫反射紋理獲取的結果。

你會得到,有2個紋理單元啓用的結果,是一樣的東西

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

結果想可能

C_o = C_f * T_s * T_d 

是什麼告訴我們嗎?

  • 實現乘法,你想調節作爲TexEnv兩個紋理單元0和紋理單元1
  • 爲了在這種情況下並不重要(這是因爲乘法-aka調製 - 是交換)
  • 我所展示的是非常多的着色器代碼。比TexEnv設置更容易閱讀。

我們回到你的問題......在這一點上,我希望你明白OpenGL的狀態,你應該來繪製時間。然而,試圖確切地知道你閱讀你的代碼的實際狀態是最好的危險練習。如果您對使用OpenGL非常認真,我推薦以下任一項:

  • 使用OpenGL調試器。有很多工具可以顯示特定繪圖調用的確切狀態。
  • 構建您自己的調試狀態跟蹤
  • 在繪製時轉儲OpenGL感興趣的狀態。 OpenGL爲其狀態的每一點都提供getter方法(或者幾乎不會進入這裏最髒的細節),你只想爲了調試的目的而這樣做,Getters並不保證高效)。
+0

>>您嘗試應用多紋理?它不會顯示在您的代碼中。 是的,我試過了,我失敗了,我刪除了它:)我必須知道這一點:>>您想要將深度紋理映射到紋理單元1:需要在映射貼圖單元之前設置紋理單元glActiveTexture(GL_TEXTURE1) - BindTexture,TexGen和紋理相關的啓用/禁用。當然,您需要切換回其他紋理單元0 我會再次嘗試使用您的建議,然後告訴它是否工作:) – Irene

+0

>>使用framebuffer_object直接繪製紋理的速度更快擴展名,比複製到它 謝謝!我會嘗試 – Irene

+0

而我還有一個問題:一個紋理是一個紋理單元嗎?或者我可以在一個當前圖層中一直綁定更多的紋理? – Irene