3

私は OpenGL を丸 1 週間、またはそれと同等のもので遊んでいます。2Dの次は3Dに挑戦中です。http://johnnylee.net/projects/wii/の 3 番目のビデオで見られる 3D シーンを再現したいと思います。
テクスチャと深度ですべてを適切に機能させるのに苦労しました。

最近、視覚的に同じ影響を与える2つの問題が発生しました。

  • 2D で見つけた手法を使用しても、3D ではうまくブレンドできないテクスチャを持つもの。
  • オブジェクトが上から下に表示されるもの。ここで公開されている問題のように: OpenGL の深度バッファ

私は両方の問題を解決しましたが、特に 2 番目の点について、問題が解決したかどうかを知りたいです


最初のものについては、私はそれを持っていると思います。ディスクの外側にアルファがある丸いターゲットの画像があります。OpenGL内で問題なくロードされます。(Z オーダーの問題により) その背後にある他のターゲットの一部は、ペイントに使用した自然に正方形の四角形の透明な領域によって隠されていました。

その理由は、深度バッファに関して、テクスチャのすべての部分が完全に不透明であると想定されているためです。glEnable(GL_ALPHA_TEST)をテストで使用するとglAlphaFunc(GL_GREATER, 0.5f)、テクスチャのアルファ レイヤーがピクセルごとの (ブール値) 不透明度インジケーターとして機能するため、ブレンドがまったく役に立たなくなります (私の画像にはブール値の透明度があるため)。

補足質問:ちなみに、ブレンドに使用するアルファレイヤーとは別のソースをアルファテストに指定する手段はありますか?


第二に、問題の解決策を見つけました。色と深度のバッファをクリアする前に、デフォルトの深度を 0 に設定しglClearDepth(0.0f)、「より大きな」深度関数を使用しましglDepthFunc(GL_GREATER)た。

私にとって奇妙に見えるのは、深さが 1.0 であり、深さ関数がGL_LESSデフォルトで「少ない」ことです。オブジェクトが反転して表示されないように、基本的に反転しています...

私はそのようなハックをどこにも見たことがありませんが、一方、描画する順序に関係なく、オブジェクトが間違った順序で体系的に描画されるのを見たことはありません!


わかりました、ここにコードの一部があります(必要以上に削除されていないことを願っています)。これは現在、私が望むように機能しています。

    int main(int argc, char** argv) {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
        glutInitWindowSize(600, 600); // Size of the OpenGL window
        glutCreateWindow("OpenGL - 3D Test"); // Creates OpenGL Window
        glutDisplayFunc(display);
        glutReshapeFunc(reshape);

        PngImage* pi = new PngImage(); // custom class that reads well PNG with transparency
        pi->read_from_file("target.png");
        GLuint texs[1];
        glGenTextures(1, texs);
        target_texture = texs[0];
        glBindTexture(GL_TEXTURE_2D, target_texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, pi->getGLInternalFormat(), pi->getWidth(), pi->getHeight(), 0, pi->getGLFormat(), GL_UNSIGNED_BYTE, pi->getTexels());

        glutMainLoop(); // never returns!
        return 0;
    }

    void reshape(int w, int h) {
        glViewport(0, 0, (GLsizei) w, (GLsizei) h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(-1, 1, -1, 1);
        gluPerspective(45.0, w/(GLdouble)h, 0.5, 10.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }

    void display(void) {
        // The stared *** lines in this function make the (ugly?) fix for my second problem
        glClearColor(0, 0, 0, 1.00);
        glClearDepth(0);          // ***
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glShadeModel(GL_SMOOTH);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_DEPTH_FUNC);  // ***
        glDepthFunc(GL_GREATER);  // ***

        draw_scene();

        glutSwapBuffers();
        glutPostRedisplay();
    }

    void draw_scene() {
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        gluLookAt(1.5, 0, -3, 0, 0, 1, 0, 1, 0);

        glColor4f(1.0, 1.0, 1.0, 1.0);
        glEnable(GL_TEXTURE_2D);
        // The following 2 lines fix the first problem
        glEnable(GL_ALPHA_TEST);       // makes highly transparent parts
        glAlphaFunc(GL_GREATER, 0.2f); // as not existent/not drawn
        glBindTexture(GL_TEXTURE_2D, target_texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        // Drawing a textured target
        float x = 0, y = 0, z = 0, size = 0.2;
        glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(x-size, y-size, z);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(x+size, y-size, z);
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(x+size, y+size, z);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(x-size, y+size, z);
        glEnd();
        // Drawing an textured target behind the other (but drawn after)
        float x = 0, y = 0, z = 2, size = 0.2;
        glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(x-size, y-size, z);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(x+size, y-size, z);
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(x+size, y+size, z);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(x-size, y+size, z);
        glEnd();
    }
4

4 に答える 4

4

通常、デプス クリア値は 1 (事実上無限大) であり、デプス パス関数は LESS です。これは、前にあるものと後ろにあるものが見える現実世界をシミュレートするためです。深度バッファを 1 にクリアすることで、基本的に、最大深度よりも近いすべてのオブジェクトを描画する必要があると言っています。これらのパラメーターを変更することは、自分が何をしているのかを本当に理解していない限り、一般的にやりたいことではありません。

gluLookAt に渡すカメラ パラメータとオブジェクトの位置を使用すると、z=2 クワッドは z=0 オブジェクトよりもカメラから遠くなります。これが正しくないように見えるように、何を達成しようとしていますか?

順序どおりのアルファ ブレンディングを実現するための標準的な方法は、すべての不透明なオブジェクトをレンダリングしてから、すべての透明なオブジェクトを前後にレンダリングすることです。通常/デフォルトの深度関数が常に使用されます。

また、パースペクティブ マトリックスの設定方法によっては、奇妙な動作が発生する可能性があることに注意してください。通常、gluOrtho または gluPerspective を呼び出します。しかし、両方ではありません。これにより、2 つの異なる遠近行列が乗算されますが、これはおそらくあなたが望むものではありません。

于 2010-11-16T00:13:29.267 に答える
0

補足質問:ところで、ブレンドに使用されるアルファレイヤーとは異なるアルファテストのソースを指定する手段はありますか?

はい、シェーダーを使用すると、出力フラグメントのアルファ値を自分で計算できます。

于 2010-11-15T23:41:54.703 に答える
0

2 番目の問題について: modelViewProjection マトリックスに問題がある可能性が非常に高いです。

私は同じ問題を抱えていました(そしてあなたのハックでそれを「修正」することができました)。独自の行列生成を実装することで解決しました。

于 2010-12-08T11:10:13.397 に答える
0

標準の glOrtho 関数で実装された数式は、zNear を -1 に、zFar を 1 にマップします。これらは、デフォルトで [0,1] としてウィンドウ座標にマップされます (固定パイプラインの glDepthRange を介して変更可能で、その関数がまだサポートされているかどうかは不明です)。デプステストは実際にそれらの用語で機能します。これを回避する方法は、zNear が投影面から最も離れていると仮定するか、レガシー パイプラインを取り除きたい場合はとにかく必要になるマトリックスを自分で生成することです。

于 2016-06-15T12:41:24.963 に答える