1

配列バッファを使用して 3 つのポイントをレンダリングしようとしていますが、何もレンダリングできません。
これは私のコードです:

import java.nio.*;
import javax.media.opengl.*;

public class SimpleScene implements GLEventListener 
{
        private GL3 gl;
        int myIdentityShader;

        @Override
        public void display(GLAutoDrawable drawable) {
            gl.glClear(GL3.GL_COLOR_BUFFER_BIT);

            gl.glUseProgram(myIdentityShader);
            gl.glDrawArrays(GL3.GL_POINTS, 0, 3);
        }
        @Override
        public void dispose(GLAutoDrawable drawable) {
            gl.glDeleteProgram(myIdentityShader);
            gl.glDeleteVertexArrays(1, vertexArrayObject, 0);
        }

        @Override
        public void init(GLAutoDrawable drawable) {
            gl = drawable.getGL().getGL3();

            try {
                myIdentityShader = createShaderProgram();
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }

            gl.glPointSize(30);
            gl.glClearColor(0.7f, 0, 0, 1);

            float[] floatData = {
                    0.25f, -0.25f, 0.5f, 1.0f,
                    -0.25f, -0.25f, 0.5f, 1.0f,
                    0.25f, 0.25f, 0.5f, 1.0f
                    };

            FloatBuffer data = FloatBuffer.allocate(3 * 4); 
            for (int i=0;i<12;i++)
                data.put(floatData[i]);

            gl.glGenVertexArrays(1, vertexArrayObject, 0);
            gl.glBindVertexArray(vertexArrayObject[0]);

            int[] buffers = new int[1];
            gl.glGenBuffers(1, buffers, 0);
            gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, buffers[0]);
            gl.glBufferData(GL3.GL_ARRAY_BUFFER, data.capacity(), data, GL3.GL_STATIC_DRAW);

            gl.glVertexAttribPointer(2, 4, GL3.GL_FLOAT, false, 0, 0);
            gl.glEnableVertexAttribArray(2);
        }

        @Override
        public void reshape(GLAutoDrawable drawable, int arg1, int arg2, int arg3,
                int arg4) {
            // TODO Add reshape code

        }

        private String vertexShader = "#version 130                                                         \n" +
                                        "in vec4 position;                                                  \n" +
                                        "void main(void)                                                    \n" + 
                                        "{                                                                  \n" + 
                                        "    gl_Position = position;                                        \n" +
                                        "}                                                                  \n";

        private String fragmentShader = "#version 130                                                       \n" +
                                        "out vec4 vFragColor;                                               \n" +
                                        "void main(void)                                                    \n" + 
                                        "{                                                                  \n" + 
                                        "    vFragColor = vec4(0.0, 0.8, 1.0, 1.0);                         \n" +
                                        "}                                                                  \n";
        private int[] vertexArrayObject = new int[1];


        private int createShaderProgram() throws Exception
        {
            int hVertexShader, hFragmentShader, hShaderProgram;
            int[] successTest = new int[] {1};

            hVertexShader = gl.glCreateShader(GL3.GL_VERTEX_SHADER);
            hFragmentShader = gl.glCreateShader(GL3.GL_FRAGMENT_SHADER);

            gl.glShaderSource(hVertexShader, 1, new String[] {vertexShader}, null);
            gl.glShaderSource(hFragmentShader, 1, new String[] {fragmentShader}, null);

            gl.glCompileShader(hVertexShader);
            gl.glCompileShader(hFragmentShader);

            gl.glGetShaderiv(hVertexShader, GL3.GL_COMPILE_STATUS, successTest, 0);
            if (successTest[0] == 0)
            {
                byte[] infoLog = new byte[1024];
                gl.glGetShaderInfoLog(hVertexShader, 1024, null, 0, infoLog, 0);
                gl.glDeleteShader(hVertexShader);
                gl.glDeleteShader(hFragmentShader);
                throw new Exception("Vertex shader compilation failed with: " + new String(infoLog));
            }
            gl.glGetShaderiv(hFragmentShader, GL3.GL_COMPILE_STATUS, successTest, 0);
            if (successTest[0] == 0)
            {
                byte[] infoLog = new byte[1024];
                gl.glGetShaderInfoLog(hFragmentShader, 1024, null, 0, infoLog, 0);
                gl.glDeleteShader(hVertexShader);
                gl.glDeleteShader(hFragmentShader);
                throw new Exception("Fragment shader compilation failed with: " + new String(infoLog));
            }

            hShaderProgram = gl.glCreateProgram();
            gl.glAttachShader(hShaderProgram, hVertexShader);
            gl.glAttachShader(hShaderProgram, hFragmentShader);

            gl.glBindAttribLocation(hShaderProgram, 2, "position");

            gl.glLinkProgram(hShaderProgram);

            gl.glGetProgramiv(hShaderProgram, GL3.GL_LINK_STATUS, successTest, 0);
            if (successTest[0] == 0)
            {
                byte[] infoLog = new byte[1024];
                gl.glGetProgramInfoLog(hShaderProgram, 1024, null, 0, infoLog, 0);
                gl.glDeleteProgram(hShaderProgram);
                throw new Exception("Shader linking failed with: " + new String(infoLog);
            }

            gl.glDeleteShader(hVertexShader);
            gl.glDeleteShader(hFragmentShader);

            return hShaderProgram;

        }
    }

シェーダーと createShaderProgram メソッドが正しいと確信しています。glVertexAttrib4fv を使用すると、3 つのポイントすべてが (予想どおり) 同じ場所にレンダリングされますが、glVertexAttribPointer を使用すると、何もレンダリングされず、エラーも発生しません (glGetError は 0 を返します)。
アトリビュート インデックスが 0 の場合、glVertexAttrib4fv は座標を送信しないため、すべてのポイントが画面の中央にレンダリングされることがわかりました。これは glVertexAttribPointer では発生しないため、座標が送信されます。

4

1 に答える 1

1

頂点配列オブジェクトを非効率的に使用しています。VAO を使用するポイントは、頂点属性を設定する必要がないようにすることです。ポインターを使用して、何かを描画するたびにポインターを有効/無効にします。VAO を初期化するときにポインターを設定すると、この状態が追跡されるため、何かを描画するたびにバインドされた VAO を変更するだけで済みます。

ただし、実際の問題はposition、頂点シェーダーの頂点属性を汎用属性位置 2 にバインドしていないことです。ほとんどの GLSL 実装では、その頂点属性位置 0 が自動的に割り当てられますが、これは必須の動作ではありません (依存しないでください)。 . プログラムをリンクした後で、この属性の場所を名前で照会するか ( glGetAttribLocation)、属性の場所を自分でバインドすることができます ( glBindAttribLocation)。いずれの場合も、ポインターの属性の場所をシェーダーの属性に一致させる必要があります。

glVertexAttrib4fv を使用すると、3 つのポイントすべてが同じ場所にレンダリングされますが、glVertexAttribPointer を使用すると何もレンダリングされず、エラーも発生しません (glGetError は 0 を返します)。

これは予想されることでありglVertexAttrib4fv (...)、その場所からデータをプルするすべての頂点シェーダー呼び出しに使用する定数値を設定します。(C 言語バインディングで) ポインターを使用することは事実ですが、そのポインターは配列を渡す OpenGL の方法にすぎません。呼び出しの完了後に指すデータの値を変更しても、何も起こりません。これが文字通り、頂点配列ポインタを設定する別のクラスの関数がある理由です。

アップデート:

この質問の更新されたコードを見た後、実際の問題が発生しました。Java では、 を使用するFloatBuffer.put (...)と、(JOGL が を呼び出したときに使用するglVertexAttribPointer (...)) バッファのベース アドレスがインクリメントされます。を呼び出してバッファをフリップする必要がありますFloatBuffer.flip (...)。これにより、バッファが効果的に巻き戻され、JOGL がバッファ内の最初の要素から読み取るようになります。

于 2014-01-05T23:33:11.303 に答える