未绘制 OpenGL 顶点

OpenGL Vertices not drawn

我整天都在努力让 OpenGL 在 Java 中工作(使用 LWJGL 3/GLFW)。问题是除了清晰的颜色,我什么都看不到。

问题:

  1. 我的 OpenGL 函数调用顺序可以吗?
  2. 有没有错误 这会阻止绘制顶点?

除了初始化之外,这是OpenGL调用的顺序。完整的程序可以在这里找到 http://pastebin.com/JWJ7pqBs 并且从 LWJGL 3 "Getting Started"-Example 派生以跳过初始化部分。

编辑: 更正了 derhass 所述的一些错误。但是仍然没有可见的输出。 http://pastebin.com/FbkuusM3

EDIT2: 尝试在片段着色器中使用固定颜色,但没有绘制顶点。

变量:

int shader;
int vao;
int vbo;

创建着色器(一次):

    String dummyVertexShaderSrc =
                "#version 330 core"
                + "\n" + "layout(location = 0) in vec3 vs_position;"
                + "\n" + "layout(location = 1) in vec4 vs_color;"
                + "\n" + ""
                + "\n" + "out vec4 fs_color;"
                + "\n" + ""
                + "\n" + "void main() {"
                + "\n" + "    gl_Position = vec4(vs_position, 1.0);"
                + "\n" + "    fs_color = vs_color;"
                + "\n" + "}"
                ;

        String dummyFragmentShaderSrc = "#version 330 core"
                + "\n" + "in vec4 fs_color;"
                + "\n" + "void main() {"
                + "\n" + "    gl_FragColor = fs_color;"
                + "\n" + "}";

        System.out.println("Vertex-Shader: \n" + dummyVertexShaderSrc + "\n");
        System.out.println("Fragment-Shader: \n" + dummyFragmentShaderSrc + "\n");

        // 1# Read/Compile VertexShader
        int idVertexShader = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
        GL20.glShaderSource(idVertexShader, dummyVertexShaderSrc);
        GL20.glCompileShader(idVertexShader);

        if (GL20.glGetShaderi(idVertexShader, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
            System.err.println("Could not compile vertex shader: " + GL20.glGetShaderInfoLog(idVertexShader));
            System.exit(-1);
        }

        // 2# Read/Compile FragmentShader
        int idFragmentShader = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
        GL20.glShaderSource(idFragmentShader, dummyFragmentShaderSrc);
        GL20.glCompileShader(idFragmentShader);

        if (GL20.glGetShaderi(idFragmentShader, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
            System.err.println("Could not compile fragment shader: " + GL20.glGetShaderInfoLog(idFragmentShader));
            System.exit(-1);
        }

        // 3# Create Shader-Program
        shader = GL20.glCreateProgram();
        GL20.glAttachShader(shader, idVertexShader);
        GL20.glAttachShader(shader, idFragmentShader);

        GL20.glBindAttribLocation(shader, 0, "vs_position");
        GL20.glBindAttribLocation(shader, 1, "vs_color");

        GL20.glLinkProgram(shader);
        if (GL20.glGetProgrami(shader, GL20.GL_LINK_STATUS) == GL11.GL_FALSE) {
            System.out.println("Shader linking failed: " + GL20.glGetProgramInfoLog(shader));
            System.exit(-1);
        }

        GL20.glValidateProgram(shader);
        GL20.glDeleteShader(idVertexShader);
        GL20.glDeleteShader(idFragmentShader);

创建VAO/VBO(一次):

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

            vbo = GL15.glGenBuffers();
            GL15.glBindBuffer( GL15.GL_ARRAY_BUFFER, vbo);
            GL15.glBufferData( GL15.GL_ARRAY_BUFFER, 1024 * Vertex.ByteSize, null, GL15.GL_STREAM_DRAW );

            GL20.glEnableVertexAttribArray(0);
            GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);

            GL20.glEnableVertexAttribArray(1);
            GL20.glVertexAttribPointer(1, 4, GL11.GL_FLOAT, false, 0, 3);

            GL20.glDisableVertexAttribArray(0);
            GL20.glDisableVertexAttribArray(1);

            GL15.glBindBuffer( GL15.GL_ARRAY_BUFFER, 0);

        GL30.glBindVertexArray(0);  

用数据填充VAO/VBO(一次):

    Vertex[] vertices = new Vertex[] {
                new Vertex(new Vector3f(-1.0f, -1.0f, 0.0f), new Color4f(0.5f, 0.5f, 0.5f, 0.5f), Vector2f.Zero),
                new Vertex(new Vector3f( 1.0f, -1.0f, 0.0f), new Color4f(0.5f, 0.5f, 0.5f, 0.5f), Vector2f.Zero),
                new Vertex(new Vector3f( 0.0f,  1.0f, 0.0f), new Color4f(0.5f, 0.5f, 0.5f, 0.5f), Vector2f.Zero),
        };

        // 1# Create buffer
        FloatBuffer buffer = ByteBuffer.allocateDirect(3 * 7 * Float.BYTES).asFloatBuffer();
        buffer.position(0);
        for(Vertex vertex : vertices) {
            buffer.put(vertex.position.x);
            buffer.put(vertex.position.y);
            buffer.put(vertex.position.z);
            buffer.put(vertex.color.r);
            buffer.put(vertex.color.g);
            buffer.put(vertex.color.b);
            buffer.put(vertex.color.a);
        }

        // 2# Write data
        GL30.glBindVertexArray(vao);

            GL15.glBindBuffer( GL15.GL_ARRAY_BUFFER, vbo);
            GL15.glBufferSubData( GL15.GL_ARRAY_BUFFER, 3 * 7, buffer);
            GL15.glBindBuffer( GL15.GL_ARRAY_BUFFER, 0);

        GL30.glBindVertexArray(0);

最后在主循环中绘制顶点(多次):

        GL20.glUseProgram(shader);
        GL30.glBindVertexArray( vao );
        GL20.glEnableVertexAttribArray(0);
        GL20.glEnableVertexAttribArray(1);

        GL11.glDrawArrays( GL11.GL_TRIANGLES, 0, 3 );

        GL20.glDisableVertexAttribArray(1);
        GL20.glDisableVertexAttribArray(0);
        GL30.glBindVertexArray( 0 );
        GL20.glUseProgram(0);

在检查您的代码时,我发现了几个错误:

GL20.glVertexAttribPointer(1, 4, GL11.GL_FLOAT, false, 0, 3);

您可能正在使用交错属性,但是,offset of 3 bytes 这里肯定是错误的。您似乎想跳过属性 0 的 3 个浮点数,所以这很可能是 3 *sizeof(GLfloat).

此外,您的 stride 参数也是错误的:您是在告诉 GL 您的属性是紧密包装的 each。您可能希望 7*sizeof(GLfloat) 作为步幅:

以下不需要:

GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);

VAO 将跟踪启用位以及指针值。您不需要在此 VAO 中禁用它们,并在绘制时重新启用和禁用它们。保持启用状态,绘制时,绑定 VAO。

上传数据时: GL15.glBufferSubData( GL15.GL_ARRAY_BUFFER, 3 * 7, 缓冲区);

你忘记了这些大小和偏移量是以字节为单位的,所以你需要乘以浮点大小again.However,我不完全明白你在这里做什么。 glBufferSubData() 需要一个偏移量和一个大小。大小 pis 可能从 java API 中删除,因为它在缓冲区对象中是隐式已知的,那么为什么你在这里使用不同于 0 的偏移量?

问题是 ByteBuffer.allocateDirect 以大端格式分配缓冲区,无论代码在什么机器上运行。 ("All x86 and x86-64 machines [..] are little-endian")

解决方案是手动交换位或仅使用 LWJGL 的 BufferUtils class 以当前机器使用的格式创建 ByteBuffer