0

良い一日。シャドウ マップ メソッドを使用して影のあるシーンを描画します (ライトの視点からシーンをレンダリングして深度バッファーを取得し、シャドウ テクスチャを作成してシーンに投影し、カメラの視点からレンダリングする場合) 、もちろん、他のすべてのテクスチャ オブジェクトはテクスチャリングを失います。しかし、私は本当に影のあるテクスチャシーンが欲しいです:)マルチテクスチャリングについて読んで、実際に適用しようとしましたが、失敗しました。正確にはどうすればよいですか?(私は OpenGl superible からコードを取得しました) これが主なセットアップ手順のコードです。//<==== で新しい文字列 (マルチテクスチャリング用の文字列) をマークしました

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

    }

シーン レンダリング プロシージャ:

    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 テクスチャ生成プロシージャ:

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

1 に答える 1

3

マルチテクスチャリングを適用しようとしましたか? コードには表示されません。あなたはそれを使う必要があります。シャドウ テクスチャ用に 1 つのテクスチャ ユニット、拡散反射光マップ用に 1 つ。試した場合は、マルチテクスチャリングを使用してコードを表示する必要があります。

マルチテクスチャリングはglActiveTexture(および使用しているように見える固定機能については、テクスチャ座標の仕様を処理する glClientActiveTexture によって処理されます)。

いくつかのアドバイス:

  • シェーダーを使用すると、何をしているのかを正確に理解するのが簡単になります。
  • 深度テクスチャをテクスチャ ユニット 1 にマップしたい場合: シャドウ マッピング用のテクスチャ ユニットのセットアップは、glActiveTexture(GL_TEXTURE1)BindTexture、TexGen、およびテクスチャリング関連の有効化/無効化が先行する必要があります。もちろん、残りはテクスチャ ユニット 0 に戻す必要があります。
  • 深度マップに描画するときにテクスチャリングは必要ありません。
  • テクスチャにコピーするよりも、framebuffer_object 拡張機能を使用してテクスチャに直接描画する方が高速です

お役に立てれば。

編集:質問をかなり変更したので、コメントにいくつかのアドバイスと回答を追加させてください。

単一のテクスチャ ユニットは、常に単一のテクスチャ オブジェクトからフェッチされます。テクスチャ ユニットから取得するテクスチャを指定するにglActiveTextureは、その後に使用します。glBindTextureそのユニットのテクスチャリングを取得するには、そのユニットを呼び出す必要があることに注意してくださいglEnable(GL_TEXTURE_2D)

最初に何を適用するか...シェーダーを使用すると、議論が大幅に簡素化されます。一般に、適用の順序は、最終的にどのようなフラグメント計算を行いたいかによって完全に異なります。次の命名法を入れましょう。

  • T_0最初のテクスチャ フェッチの結果、
  • T_12 番目のテクスチャ フェッチの結果。
  • 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

それは何を教えてくれますか?

  • 乗算を実装するには、テクスチャ ユニット 0 とテクスチャ ユニット 1 の両方の TexEnv として変調する必要があります。
  • この場合、順序は重要ではありません (これは、乗算 (別名変調) が可換であるためです)。
  • 私が示したのは、ほとんどのシェーダー コードです。TexEnv 設定よりもはるかに読みやすいです。

さて、あなたの問題に戻りましょう... この時点で、描画時にOpenGL がどのような状態になるべきかを理解していただければ幸いです。ただし、コードを読んで実際にどのような状態にあるかを正確に把握しようとすることは、よくても危険な作業です。OpenGL を真剣に使用する場合は、次のいずれかをお勧めします。

  • OpenGL デバッガーを使用します。特定のドローコールで正確な状態を表示するツールは数多くあります。
  • 独自のデバッグ状態追跡を構築する
  • 描画時に対象の OpenGL 状態をダンプします。OpenGL は、その状態のすべてのビットに対して getter メソッドを提供します (または、ほとんどの場合、ここでは最も汚い詳細には立ち入りません)。これはデバッグ目的でのみ行いたいと考えています。Getter は効率的であるとはまったく保証されていません)。
于 2009-11-27T19:55:09.803 に答える