0

私はこれで2日間壁に頭をぶつけてきました。私は可能な限り単純な OpenGL コア ~2.0-3.2 描画シーケンスを抽出して、そこからコードを構築し、API を本当に理解できるようにしようとしています。私が直面している問題は、チュートリアルに、使用している OpenGL のバージョンを示す便利なタグが付いていないように見えることです。これは、コンテキストから特定のバージョンを要求する方法についてのドキュメントに出くわしたのは、純粋に運が良かったからです。

即時モードの描画でエラーがスローされるため、3.2 コアが有効になっていることは確かです (これは良いことです! 即時モードを残したい!)。また、座標変換や三角形の巻線などの空想的なものを取り除こうとしました。それは私のディスプレイを台無しにするかもしれません。問題は、画面に何も表示されないことです。

このプログラムの以前の反復では、ランダムな座標を使用して画面上に白い三角形を表示することできましたが、頂点が適切に設定されていないように思われ、奇妙なビットの組み合わせが奇妙な結果を生み出します。三角形が出現する場所の符号は問題ではありませんでした。したがって、私の理論では、頂点情報が頂点シェーダーに適切に転送されていないか、シェーダーがそれを台無しにしているということです。問題は、私が見つけたすべての結果とログをチェックしていて、シェーダーが見事にコンパイルされ、リンクされていることです。

以下にリンクとコードを提供しますが、三角形を画面上に表示するだけでなく、シェーダー プログラムでテキストや診断値をシェーダー情報ログに吐き出すことはできますか? これにより、デバッグプロセスが大幅に簡素化されます。

私が相談しているさまざまなチュートリアルは...

http://arcsynthesis.org/gltut/Basics/Tutorial%2001.html http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Introduction https://en.wikipedia.org/wiki/Vertex_Buffer_Object http://www .opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_(C_/_SDL) http://antongerdelan.net/opengl/hellotriangle.html http://lwjgl.org/wiki/index.php?title=The_Quad_with_DrawArrays http ://lwjgl.org/wiki/index.php?title=Using_Vertex_Buffer_Objects_(VBO) http://www.opengl.org/wiki/Vertex_Rendering

http://www.opengl.org/wiki/Layout_Qualifier_(GLSL) (提供されたコードには存在しませんが、私が試したのはレイアウト修飾子 0 (in_Position) および 1 (in_Color) を持つ #version 420 でした)

コード (LWJGL + Groovy)

package com.thoughtcomplex.gwdg.core

import org.lwjgl.input.Keyboard
import org.lwjgl.opengl.ContextAttribs
import org.lwjgl.opengl.Display
import org.lwjgl.opengl.GL11
import org.lwjgl.opengl.GL15
import org.lwjgl.opengl.GL20
import org.lwjgl.opengl.GL30
import org.lwjgl.opengl.PixelFormat
import org.lwjgl.util.glu.GLU

import java.nio.ByteBuffer
import java.nio.FloatBuffer

/**
 * Created by Falkreon on 5/21/2014.
 */
class GwDG {

    static final String vertexShader = """
        #version 150
        in vec2 in_Position;
        in vec3 in_Color;

        smooth out vec3 ex_Color;
        void main(void) {
            gl_Position = vec4(in_Position,0.0,1.0);
            ex_Color = in_Color;
        }

    """;

    static final String fragmentShader = """
        #version 150

        smooth in vec3 ex_Color;
        out vec4 fragColor;

        void main(void) {
            //fragColor = vec4(ex_Color, 1.0);
            fragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
    """;

    static int vaoHandle = -1;
    static int vboHandle = -1;
    protected static int colorHandle = -1;
    static int vertexShaderHandle = -1;
    static int fragmentShaderHandle = -1;
    static int shaderProgram = -1;

    protected static FloatBuffer vboBuffer = ByteBuffer.allocateDirect(6*4).asFloatBuffer();
    protected static FloatBuffer colorBuffer = ByteBuffer.allocateDirect(9*4).asFloatBuffer();


    public static void main(String[] args) {
        //Quick and dirty hack to get something on the screen; this *works* for immediate mode drawing
        System.setProperty("org.lwjgl.librarypath", "C:\\Users\\Falkreon\\IdeaProjects\\GwDG\\native\\windows");

        Display.setTitle("Test");
        ContextAttribs attribs = new ContextAttribs();
        attribs.profileCompatibility = false;
        attribs.profileCore = true;
        attribs.majorVersion = 3;
        attribs.minorVersion = 2;
        Display.create( new PixelFormat().withDepthBits(24).withSamples(4).withSRGB(true), attribs );

        //Kill any possible winding error
        GL11.glDisable(GL11.GL_CULL_FACE);

        vaoHandle = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(vaoHandle);

        reportErrors("VERTEX_ARRAY");

        vboHandle = GL15.glGenBuffers();
        colorHandle = GL15.glGenBuffers();

        vertexShaderHandle = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
        fragmentShaderHandle = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
        reportErrors("CREATE_SHADER");

        GL20.glShaderSource( vertexShaderHandle, vertexShader );
        GL20.glShaderSource( fragmentShaderHandle, fragmentShader );

        GL20.glCompileShader( vertexShaderHandle );
        String vertexResult = GL20.glGetShaderInfoLog( vertexShaderHandle, 700 );
        if (!vertexResult.isEmpty()) System.out.println("Vertex result: "+vertexResult);

        GL20.glCompileShader( fragmentShaderHandle );
        String fragmentResult = GL20.glGetShaderInfoLog( fragmentShaderHandle, 700 );
        if (!fragmentResult.isEmpty()) System.out.println("Fragment result: "+fragmentResult);

        shaderProgram = GL20.glCreateProgram();
        reportErrors("CREATE_PROGRAM");
        GL20.glAttachShader( shaderProgram, vertexShaderHandle );
        GL20.glAttachShader( shaderProgram, fragmentShaderHandle );
        GL20.glLinkProgram(shaderProgram);
        int result = GL20.glGetProgrami( shaderProgram, GL20.GL_LINK_STATUS );
        if (result!=1) System.out.println("LINK STATUS: "+result);
        reportErrors("SHADER_LINK");

        //Attribs
        int vertexParamID = GL20.glGetAttribLocation(shaderProgram, "in_Position");
        int colorParamID = GL20.glGetAttribLocation(shaderProgram, "in_Color");

        while (!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {

            //Intentional flicker so I can see if something I did freezes or lags the program
            GL11.glClearColor(Math.random()/6 as Float, Math.random()/8 as Float, (Math.random()/8)+0.4 as Float, 1.0f);
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT );

            float[] coords = [
                 0.0f,  0.8f,
                -0.8f, -0.8f,
                 0.8f, -0.8f
            ];

            vboBuffer.clear();
            coords.each {
                vboBuffer.put it;
            }
            vboBuffer.flip();

            float[] colors = [
                1.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 1.0f
            ];

            colorBuffer.clear();
            colors.each {
                colorBuffer.put it;
            }
            colorBuffer.flip();

            //System.out.println(dump(vboBuffer));
            reportErrors("SETUP_TRIANGLE_DATA");

            GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboHandle);
            GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vboBuffer, GL15.GL_STATIC_DRAW);
            reportErrors("BIND_VBO_AND_FILL_DATA");

            GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, colorHandle);
            GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colorBuffer, GL15.GL_STATIC_DRAW);
            reportErrors("BIND_COLOR_BUFFER_AND_FILL_DATA");

            GL20.glEnableVertexAttribArray( vertexParamID );
            GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboHandle);
            GL20.glVertexAttribPointer(
                    vertexParamID, 2, GL11.GL_FLOAT, false, 0, 0
            );
            GL20.glEnableVertexAttribArray( colorParamID );
            GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, colorHandle);
            GL20.glVertexAttribPointer(
                    colorParamID, 3, GL11.GL_FLOAT, false, 0, 0
            );

            reportErrors("VERTEX_ATTRIB_POINTERS");

            GL20.glUseProgram( shaderProgram );
            GL11.glDrawArrays( GL11.GL_TRIANGLES, 0, 3 );

            reportErrors("POST_RENDER");

            Display.update(true);
            Thread.sleep(12);
            Keyboard.poll();
        }
        Display.destroy();
    }


    private static String dump(FloatBuffer f) {
        String result = "[ ";
        f.position(0);
        //f.rewind();
        for(it in 0..<f.limit()) {
            result+= f.get(it);
            if (it!=f.limit()-1) result+=", ";
        }
        result +=" ]";
        f.position(0);
        result;
    }

    private static void reportErrors(String prefix) {
        int err = GL11.glGetError();
        if (err!=0) System.out.println("["+prefix + "]: "+GLU.gluErrorString(err)+" ("+err+")");
    }
}

重要ではありませんが、カードは GL4 をサポートする ATI Radeon HD 8550G (A8 APU の一部) です。

リクエストに応じてさらに情報を更新しますが、これを診断するのに他に何が役立つかわかりません.

編集: Reto Koradi によって提案された変更を反映するために上記のコードを更新しました。別の頂点宣言を使用して実行されるコードのバリアントもあります。

float[] coords = [
    0.0f,  0.8f,
    -0.8f, -0.8f,
    Math.random(), Math.random(),
    //0.8f, -0.8f,
];

これは実際には画面上にラスタライズされたものを生成しますが、私が期待するものとはまったく異なります。単純に右下 (右上?) のポイントを再配置するのではなく、何もない、完全に白い、次の 2 つの形状の間で反転します。

奇妙な形 1 奇妙な形 2

2 番目または 3 番目の頂点を置き換えると、これが発生します。最初の頂点を置き換えると、画面に何も表示されません。したがって、どの頂点が実際にウィンドウの中央に表示されているかについての私の仮定を確認するために、次のことを試しました。

static final String vertexShader = """
    #version 150
    in vec2 in_Position;
    in vec3 in_Color;

    smooth out vec3 ex_Color;
    void main(void) {
        gl_Position = vec4(in_Position,0.0,1.0);
        ex_Color = vec3(1.0, 1.0, 1.0);
        if (gl_VertexID==0) ex_Color = vec3(1.0, 0.0, 0.0);
        if (gl_VertexID==1) ex_Color = vec3(0.0, 1.0, 0.0);
        if (gl_VertexID==2) ex_Color = vec3(0.0, 0.0, 1.0);
        //ex_Color = in_Color;
    }

""";

static final String fragmentShader = """
    #version 150

    smooth in vec3 ex_Color;
    out vec4 fragColor;

    void main(void) {
        fragColor = vec4(ex_Color, 1.0);
        //fragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
""";

シンプルですね。中央の頂点はおそらく最初の「赤い」頂点であるはずです。これはオプションではない頂点であり、それなしでは画面に何も描画できないようです。実際にはそうではありません。ハーフスクリーン ブロックは常に予想どおり赤ですが、左向きの三角形の形状は常に、置き換える頂点の色になります。2 番目の頂点を置き換えると緑になり、3 番目の頂点を置き換えると青になります。「-0.8、-0.8」と「0.8、-0.8」の両方が画面からはみ出しているように見えるため、表示されている三角形のセクションは事実上無限に細い線になっています。しかし、これは変換によるものではないと思います。これは、配置の問題のように動作し、0.9 前後の任意のしきい値を使用して、座標をファーランドに送信します。

ドリルダウンを続けるために、ハードコードされたGLSLの量を増やして、バッファーを完全に無視しました-

static final String vertexShader = """
    #version 150
    in vec2 in_Position;
    in vec3 in_Color;

    smooth out vec3 ex_Color;
    void main(void) {
        gl_Position = vec4(in_Position,0.0,1.0);
        ex_Color = vec3(1.0, 1.0, 1.0);
        if (gl_VertexID==0) {
            ex_Color = vec3(1.0, 0.0, 0.0);
            gl_Position = vec4(0.0, 0.8, 0.0, 1.0);
        }
        if (gl_VertexID==1) {
            ex_Color = vec3(0.0, 1.0, 0.0);
            gl_Position = vec4(-0.8, -0.8, 0.0, 1.0);
        }
        if (gl_VertexID==2) {
            ex_Color = vec3(0.0, 0.0, 1.0);
            gl_Position = vec4(0.8, -0.8, 0.0, 1.0);
        }
        //ex_Color = in_Color;
    }

""";

これにより、各頂点に異なる色の素敵な大きな三角形が生成されます。明らかに、頂点バッファーからこの同じ三角形を取得したいのですが、それは本当に良いスタートです.2つの頂点を使用すると、少なくとも最終頂点がどの方向に発射されているかを知ることができます.最初の頂点の場合、それは間違いなくdown .

また、プロファイルでデバッグ モードを有効にする方法も見つけましたが、カラー バッファ エラーが発生しています。良い!それが始まりです。では、大量の VBO エラーが発生しないのはなぜでしょうか?

4

2 に答える 2

1

コードはコア プロファイルと互換性がありません。あなたreportErrors()は実際に発砲する必要があります。コア プロファイルでは、頂点のセットアップに頂点配列オブジェクト (VAO) を使用する必要があります。glGenVertexArrays()頂点の状態を設定する前に、VAO を で生成し、それを `glBindVertexArray() でバインドする必要があります。

フラグメント シェーダでの の使用gl_FragColorも非推奨です。outコア プロファイルで独自の変数を宣言する必要があります。次に例を示します。

out vec4 FragColor;
...
    FragColor = ...
于 2014-05-29T05:37:43.983 に答える
0

答えは最終的にhttp://lwjgl.org/forum/index.php?topic=5171.0からのひらめきから生まれました。

それはかなり間違っているので、最終的に何が正しかったかを説明しましょう。私の開発環境は、Intel チップ上の Java です。Java はすべてビッグエンディアンで動作します。フロートの指数が有効桁数で巻き上げられているように見えて戸惑いましたが、この投稿を見て、エンディアンが反転した場合に発生する最も簡単な方法です! FloatBuffer は引き続きビッグエンディアンになります。OpenGL がネイティブ バイト オーダー以外で実行される可能性はほとんどありません。私が調べた lwjgl リソースのいずれにも、この癖について言及されていなかったか、見逃していました。

このプログラムの ByteBuffers の正しい初期化子は次のとおりです。

protected static FloatBuffer vboBuffer = ByteBuffer.allocateDirect(6*4).order( ByteOrder.nativeOrder(  ) ).asFloatBuffer();
protected static FloatBuffer colorBuffer = ByteBuffer.allocateDirect(9*4).order( ByteOrder.nativeOrder(  ) ).asFloatBuffer();

重要な部分は、ByteOrder.nativeOrder()

于 2014-05-30T16:07:55.720 に答える