带着色器的顶点缓冲区对象/顶点数组对象

Posted

技术标签:

【中文标题】带着色器的顶点缓冲区对象/顶点数组对象【英文标题】:Vertex Buffer Objects/Vertex Array Objects with shaders 【发布时间】:2017-02-27 03:19:53 【问题描述】:

我无法将任何内容渲染到屏幕上。

private void initVBO() 
    vao = GL30.glGenVertexArrays();
    GL30.glBindVertexArray(vao);

    float[] vertices = 
            -0.5f, 0.5f, 0f,
            0.5f, 0.5f, 0f,
            0.5f, -0.5f, 0f,
            -0.5f, -0.5f, 0f
    ;
    FloatBuffer vertBuffer = BufferUtils.createFloatBuffer(vertices.length);
    vertBuffer.put(vertices);
    vertBuffer.flip();

    this.vboID = GL15.glGenBuffers();
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vboID);
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertBuffer, GL15.GL_STATIC_DRAW);
    positionAttribute = GL20.glGetAttribLocation(getMaterial().getShader()
            .getProgram(), "position");
    GL20.glEnableVertexAttribArray(positionAttribute);
    GL20.glVertexAttribPointer(positionAttribute, 3, GL11.GL_FLOAT, false, 0,
            0);

    Color c = getMaterial().getColor();
    float[] colors = 
        c.red, c.green, c.blue, c.alpha,
        c.red, c.green, c.blue, c.alpha,
        c.red, c.green, c.blue, c.alpha,
    ;
    FloatBuffer colorBuffer = BufferUtils.createFloatBuffer(colors.length);
    colorBuffer.put(colors);
    colorBuffer.flip();

    this.vbocID = GL15.glGenBuffers();
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vbocID);
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colorBuffer, GL15.GL_STATIC_DRAW);
    colorAttribute = GL20.glGetAttribLocation(getMaterial().getShader().getProgram
            (), "color");
    GL20.glEnableVertexAttribArray(colorAttribute);
    GL20.glVertexAttribPointer(colorAttribute, 4, GL11.GL_FLOAT, false, 0, 0);

    byte[] indices = 
            0, 1, 2,
            2, 3, 0
    ;
    ByteBuffer indicesBuffer = BufferUtils.createByteBuffer(indices.length);
    indicesBuffer.put(indices);
    indicesBuffer.flip();

    this.vboiID = GL15.glGenBuffers();
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, this.vboiID);
    GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer,
            GL15.GL_STATIC_DRAW);

    GL30.glBindVertexArray(0);

    GL20.glDisableVertexAttribArray(positionAttribute);
    GL20.glDisableVertexAttribArray(colorAttribute);

    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);


public void render() 
    GL20.glUseProgram(getMaterial().getShader().getProgram());

    GL30.glBindVertexArray(this.vao);
    GL20.glEnableVertexAttribArray(positionAttribute);
    GL20.glEnableVertexAttribArray(colorAttribute);

    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, this.vboiID);

    GL11.glDrawElements(GL11.GL_TRIANGLES, 6, GL11.GL_BYTE, 0);

    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
    GL20.glDisableVertexAttribArray(colorAttribute);
    GL20.glDisableVertexAttribArray(positionAttribute);
    GL30.glBindVertexArray(0);
    GL20.glUseProgram(0);

着色器正在正确编译,并且我绑定了位置和颜色的属性正确。我只是在使用 glOrtho 并且它设置正确,因为通过立即模式绘图工作得很好。我不确定问题是否可能来自创建索引,或者它是否是 glVertexAttribPointer 中的问题。我只是想在屏幕上绘制一个彩色矩形。

更新: 顶点着色器:

#version 150

in vec3 position;
in vec4 color;

out vec4 passColor;

void main(void) 
  gl_Position = vec4(position, 1.0);
  passColor = color;

片段着色器:

#version 150

in vec4 passColor;

out vec4 outColor;

void main(void) 
  outColor = vec4(1.0, 1.0, 1.0, 1.0);

我还更新了上面的初始化和渲染代码。这里还有着色器的加载代码:

private void load(File vertex, File fragment) 
        this.vertexID = FileUtility.loadShader(vertex, GL20.GL_VERTEX_SHADER);
        this.fragmentID = FileUtility.loadShader(fragment, GL20.GL_FRAGMENT_SHADER);

        programID = GL20.glCreateProgram();
        GL20.glAttachShader(programID, vertexID);
        GL20.glAttachShader(programID, fragmentID);

        GL20.glBindAttribLocation(programID, 0, "position");
        GL20.glBindAttribLocation(programID, 1, "color");

        GL30.glBindFragDataLocation(programID, 0, "outColor");

        GL20.glLinkProgram(programID);
        GL20.glValidateProgram(programID);

        int status = GL20.glGetProgrami(programID, GL20.GL_LINK_STATUS);
        if (status != GL11.GL_TRUE) 
            Log.print(LogLevel.Error, GL20.glGetProgramInfoLog(programID));
        
    

【问题讨论】:

您的投影矩阵是如何在顶点着色器中设置的? glOrtho 不会这样做,除非您使用 #version 110ftransformgl_ProjectionMatrix 等。 我正在通过GL11.glViewport(0, 0, Configuration.getInstance().getWindowWidth(), Configuration.getInstance().getWindowHeight()); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity();i GL11.glOrtho(-1, 1, 1, -1, 1, -1); GL11.glMatrixMode(GL11.GL_MODELVIEW); 创建正交矩阵我没有在着色器中设置投影矩阵;我只是设置顶点的颜色。 您打算如何在未扩展的#version 120 着色器中使用in/out 我试过使用#version 150,但它没有产生任何结果。我已经更新了代码 【参考方案1】:

这里有很多问题,主要是你的VBO实际上没有绑定。

您创建、绑定并立即解除绑定您的 VAO。所以删除对glBindVertexArray(0) 的调用或将其推到initVBO 的底部。也不要在解除绑定 VAO 之前解除绑定 VBO,否则您的 VAO 将不会绑定到 VBO。

您没有发布着色器,但您使用的是 VAO,这意味着您至少可以访问 GLSL 1.30。 glOrtho with shaders 仅得到短暂支持,在 GLSL 1.20 中被弃用并在核心配置文件中被删除。我强烈建议尽快远离固定功能矩阵堆栈。 LWJGL 有自己的矩阵类,切换应该很简单。

除非着色器中出现任何其他问题,否则首先应该让某些东西出现在屏幕上

【讨论】:

GL30.glBindVertexArray(0); GL20.glDisableVertexAttribArray(positionAttribute); GL20.glDisableVertexAttribArray(colorAttribute); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); 所以我将所有这些按顺序移到了底部,但它仍然没有绘制任何东西。 你能用你的着色器更新你的问题吗?如果还没有,也禁用背面剔除,只是为了检查你的脸没有被剔除 glOrtho 对您的着色器没有任何影响。您在顶点着色器中将顶点直接设置为 NDC,而无需接触固定功能矩阵堆栈或应用任何变换。您应该在视口的左下象限看到材质颜色的正方形。如果没有,请禁用背面剔除并将片段着色器中的颜色设置为恒定颜色,仅用于测试目的 剔除被禁用,并且在片段着色器中我使用的是恒定颜色,它不起作用。

以上是关于带着色器的顶点缓冲区对象/顶点数组对象的主要内容,如果未能解决你的问题,请参考以下文章

从顶点着色器中修改着色器存储缓冲区对象

openGL:带着色器的线条

顶点着色器的绘制操作

具有多个缓冲区的片段着色器颜色错误

顶点着色器 VAO 是不是需要 VBO?

片段着色器是不是处理来自顶点着色器的所有像素?