glDrawElements使用相同的顶点数组对象和相同的着色器程序在第二次调用时不会绘制

时间:2015-03-08 05:02:24

标签: c# opengl opentk

我对opengl很陌生,而且我发现这种意外行为。

我实现了一个基本的场景图,并尝试添加重用着色器和网格数据的功能。

我有一个GeometryData对象,它包含对顶点数组对象,顶点缓冲区和索引缓冲区的引用。它有一个使用glDrawElements绘制模型的render方法。

GeometryData具有对Shader对象的引用,该对象具有对程序着色器句柄的引用。

问题在于,如果我渲染具有相同着色器实例的连续对象,则只渲染第一个,而其他对象不是出于某种原因,没有错误。如果我在连续对象绘制之间交替着色器分配,则所有这些都是正常绘制的。

我的GeometryData的Render方法如下:

    public override void Render()
    {
        GL.BindVertexArray(vertexArray);

        if (UseShader != null)
            UseShader.Use();

        var err = GL.GetError();

        GL.DrawElements(PrimitiveType.Triangles, numIndices, DrawElementsType.UnsignedInt, IntPtr.Zero);

        err = GL.GetError();
        GL.BindVertexArray(0);
    }

UseShader.Use()方法就是这个

    public void Use()
    {
        int current = GL.GetInteger(GetPName.CurrentProgram);

        if (current != ProgramHandle) 
            GL.UseProgram(ProgramHandle);

        // Use a uniform block for the project and modelview matrices
        var index = GL.GetUniformBlockIndex(ProgramHandle, "Matrices");
        GL.UniformBlockBinding(ProgramHandle, index, World.BINDING_POINT);

        // assume interleaved vertex data
        GL.VertexAttribPointer(positionLoc, 3, VertexAttribPointerType.Float, false, 2 * Vector3.SizeInBytes, Vector3.SizeInBytes);
        GL.EnableVertexAttribArray(positionLoc);

        GL.VertexAttribPointer(colorLoc, 3, VertexAttribPointerType.Float, false, 2 * Vector3.SizeInBytes, 0);
        GL.EnableVertexAttribArray(colorLoc);
    }

以下是一些截图。使用此循环创建框:

 for (int i = -3; i <= 3; i+=3)
 {
     Transform child = new Transform();
     child.Translation = new Vector3(i, 0, 0);

     // this causes the second red box to not render
     Geometry geom = new Geometry(i > 0 ? coloredShader : redShader, box); 


     // this causes all boxes to render normally
     // Geometry geom = new Geometry(i == 0 ? coloredShader : redShader, box);

     child.addChild(geom);

     root.addChild(child);
 }

带有交替着色器的图片(红色,彩色,红色) Picture with alternating shaders (red, colored, red)

使用相同着色器(红色,红色,彩色)连续两个对象的图片。未绘制第二个红色对象。我对场景所做的唯一更改是着色器分配。

Picture with two consecutive object using the same shader (red, red, colored)

更新

经过进一步的检查和调试,似乎问题的根源是统一块。我使用统一块将投影和模型视图矩阵发送到着色器。我怀疑第二次调用glBufferSubData来更新模型视图矩阵不会更新制服,或者着色器没有从制服中读取该值而不先切换到另一个着色器。

我尝试从统一块中取出模型视图矩阵并将其分别发送到每个着色器。这使得所有对象都能正确呈现,但我仍然希望使用统一块来避免冗余上传。

1 个答案:

答案 0 :(得分:0)

解决! 这真是太傻了。我需要在使用glBufferSubData更新统一块值后调用glFlush()。

    public static void setModelView(ref Matrix4 modelView)
    {
        GL.BindBuffer(BufferTarget.UniformBuffer, uniformBuffer);
        GL.BufferSubData(BufferTarget.UniformBuffer, (IntPtr)(16 * sizeof(float)), (IntPtr)(16 * sizeof(float)), ref modelView);
        GL.Flush(); // I just added this line
        GL.BindBuffer(BufferTarget.UniformBuffer, 0);
    }