【问题标题】:LWJGL VAO/VBO not displayingLWJGL VAO/VBO 不显示
【发布时间】:2018-06-23 17:41:00
【问题描述】:

这是我的代码:

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

它显示一个具有正确宽度、高度和标题的白色窗口。 我认为问题出在我的 glVertexAttribPointer 调用上,而且我听说过可能需要用到的称为“缓冲区翻转”的东西。

编辑:

响应一些cmets,用这个顶点着色器:

#version 410 core

layout (location = 0) in vec3 inPos;

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

没有任何变化。

【问题讨论】:

  • 顶点着色器的输出不应该是gl_Position = vec4(inPos,1.0);吗?

标签: java opengl glsl lwjgl glfw


【解决方案1】:

你必须在顶点着色器中写信给gl_Position。写入gl_Position 的齐次坐标用于基元组装。您不能指定自己的“输出”变量,因为您可以在片段着色器中执行此操作。 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

变量gl_Position 用于写入齐次顶点位置。它可以在着色器执行期间的任何时间编写。该值将由图元组装、裁剪、剔除和其他固定功能操作(如果存在)使用,这些操作在发生顶点处理后对图元进行操作。如果顶点在顶点处理阶段之后它的值是未定义的 着色器可执行文件不写入gl_Position


在将数据传输到缓冲区后,您还必须flip() 缓冲区。另见:

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 时,将检索指向缓冲区当前位置的数据的指针。

【讨论】:

  • 非常感谢!你能解释一下为什么需要翻转缓冲区吗?在JOGL或C++/OpenGL中不需要翻转。
【解决方案2】:

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

gl_Position = vec4(inPos,1.0);

【讨论】:

    猜你喜欢
    • 2012-07-24
    • 1970-01-01
    • 2020-07-21
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-30
    • 1970-01-01
    相关资源
    最近更新 更多