LWJGL VAO/VBO 不显示

LWJGL VAO/VBO not displaying

这是我的代码:

import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.io.File;
import java.nio.*;
import java.util.Scanner;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL14.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL21.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.opengl.GL31.*;
import static org.lwjgl.opengl.GL32.*;
import static org.lwjgl.opengl.GL33.*;
import static org.lwjgl.opengl.GL40.*;
import static org.lwjgl.opengl.GL41.*;
import static org.lwjgl.opengl.GL42.*;
import static org.lwjgl.opengl.GL43.*;
import static org.lwjgl.opengl.GL44.*;
import static org.lwjgl.opengl.GL45.*;
import static org.lwjgl.opengl.GL46.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

public class Test {

  public static void main(String[] args) {

    if (!glfwInit()) {
      System.out.println("GLFW not init.");
      return;
    }

    glfwDefaultWindowHints();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    long window = glfwCreateWindow(500, 500, "Window", NULL, NULL);
    if (window == NULL) {
      System.out.println("Window not create.");
      return;
    }

    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);
    glfwShowWindow(window);

    GL.createCapabilities();

    Utilities.printGLInfo();

    int vert=glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vert, Utilities.loadStrFromFile("Shaders/shader.vert"));
    glCompileShader(vert);
    if(glGetShaderi(vert, GL_COMPILE_STATUS)==GL_FALSE) {
      System.out.println("Vertex shader compilation error:\n"+glGetShaderInfoLog(vert));
    }
    int frag=glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(frag, Utilities.loadStrFromFile("Shaders/shader.frag"));
    glCompileShader(frag);
    if(glGetShaderi(frag, GL_COMPILE_STATUS)==GL_FALSE) {
      System.out.println("Fragment shader compilation error:\n"+glGetShaderInfoLog(frag));
    }

    int prog=glCreateProgram();
    glAttachShader(prog, vert);
    glAttachShader(prog, frag);
    glLinkProgram(prog);

    float[]vboData=new float[] {
        0,0,0,
        1,0,0,
        0,1,0
    };

    int vao=glGenVertexArrays();
    int vbo=glGenBuffers();


    glBindVertexArray(vao);

    glBindBuffer(GL_ARRAY_BUFFER,vbo);
    glBufferData(GL_ARRAY_BUFFER, FloatBuffer.wrap(vboData), GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 3*Float.BYTES, 0);

    glBindVertexArray(0);


    System.out.println("prog="+prog+",vert="+vert+",frag="+frag);
    System.out.println("vao="+vao+",vbo="+vbo);

    while (!glfwWindowShouldClose(window)) {
      glClearColor(1, 1, 1, 1);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      glUseProgram(prog);

      glBindVertexArray(vao);
//      glDrawElements(GL_TRIANGLES, indices);
      glDrawArrays(GL_TRIANGLES, 0, 3);
      glBindVertexArray(0);

      glUseProgram(0);

      glfwSwapBuffers(window);
      glfwPollEvents();
    }

    glfwDestroyWindow(window);
    glfwTerminate();

  }

}

这是它打印的内容:

Version       : 4.1 ATI-1.66.31
Vendor        : ATI Technologies Inc.
Renderer      : AMD Radeon Pro 560 OpenGL Engine
GLSL version  : 4.10
Major version : 4
Minor version : 1
prog=3,vert=1,frag=2
vao=1,vbo=1

因此它生成了着色器并且 vao/vbos 正确。

顶点着色器:

#version 410 core

layout (location = 0) in vec3 inPos;

out vec4 outPos;

void main(){
    outPos=vec4(inPos,1.0);
}

片段着色器:

#version 410 core

out vec4 fragColor;

void main(){
    fragColor=vec4(0.0,0.0,0.0,1.0);
}

我使用的是 macOS High Sierra 版本 10.13.4。

图形:

Radeon Pro 560 4096 MB
Intel HD Graphics 630 1536 MB

它显示白色 window,宽度、高度和标题正确。 我认为问题出在我的 glVertexAttribPointer 调用上,我听说过一些叫做 "buffer flipping" 的东西,可能是 nescarry。

编辑:

回应一些评论,使用这个顶点着色器:

#version 410 core

layout (location = 0) in vec3 inPos;

void main(){
    gl_Position=vec4(inPos,1.0);
}

没有任何变化。

顶点的位置,作为顶点着色器的输出,存储在gl_Position向量中,所以尝试

gl_Position = vec4(inPos,1.0);

您必须在顶点着色器中写入 gl_Position。写入gl_Position的齐次坐标用于图元组装。您不能指定自己的 "output" 变量,因为您可以在片段着色器中这样做。 Vertex Shader中的输出变量是可变变量,传递给管道的下一段。

#version 410 core

layout (location = 0) in vec3 inPos;

void main()
{
    gl_Position = vec4(inPos, 1.0);
}

GLSL - The OpenGL Shading Language 4.6; 7.1.1. Vertex Shader Special Variables; page 131

The variable gl_Position is intended for writing the homogeneous vertex position. It can be written at any time during shader execution. This value will be used by primitive assembly, clipping, culling, and other fixed functionality operations, if present, that operate on primitives after vertex processing has occurred. Its value is undefined after the vertex processing stage if the vertex shader executable does not write gl_Position.


另外你还得flip()把数据传送到缓冲区后的缓冲区。参见:

  • Converting C++ OpenGl to Java(LWJGL), glBufferData()
  • LWJGL3: Overloaded glBufferData methods

float[]vboData=new float[] { 0,0,0,  1,0,0,  0,1,0 };

FloatBuffer buf = BufferUtils.createFloatBuffer(vboData.length);
buf.put(vboData).flip();

glBufferData(GL_ARRAY_BUFFER, buf, GL_STATIC_DRAW);

解释:

put(vboData) 将数据传输到缓冲区,从当前位置开始(在本例中是缓冲区的开头)。缓冲区位置按数据大小递增。所以新的缓冲区位置在新数据的末尾。

flip() 将缓冲区的限制(长度)设置为当前位置,然后将位置设置为零。

当您将缓冲区数据传递给 glBufferData 时,将检索指向缓冲区当前位置的数据的指针。