从不同的缓冲区绘制多个对象(数组切换)
Posted
技术标签:
【中文标题】从不同的缓冲区绘制多个对象(数组切换)【英文标题】:Draw multiple objects from different buffers (arrays switching) 【发布时间】:2014-05-12 07:23:37 【问题描述】:目前我正在尝试使用缓冲区数量绘制多个对象。
我不确定我是否以正确的方式切换缓冲区以进行绘图,并且不知道该怎么做。
我有 2 个数组:
quad_strip2
的数量包含 34 个元素(要绘制的对象),每个元素的 QUAD_STRIP
使用 52 个顶点(总共 1767 个顶点)。
quad_strip3
包含 48 个元素,QUAD_STRIP
有 26 个顶点(总共 1247 个顶点)。
初始化代码
gl.GenBuffers(2, Buffers);
//SKIPED MATRICES AND SHADERS INITIALIZATION
float[] quad_strip2 = new float[]
// COUNT OF ELEMENTS: 34
// COUNT OF VERTICES: 52
-19.66171f, 8.161709f, 2f, //0
-19.66171f, 8.161709f, 4f, //1
........
-19.66171f, -6.838291f, 35f, //1767
;
float[] quad_strip3 = new float[]
// COUNT OF ELEMENTS: 48
// COUNT OF VERTICES: 26
-0.8537037f, 7.25f, 2f, //0
-0.8537037f, 7.25f, 4f, //1
........
-20f, -3.25f, 34.45f, //1247
;
//bind first buffer
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, Buffers[0]);
//fill buffer with vertices
unsafe
fixed (float* verts = quad_strip2)
var prt = new IntPtr(verts);
gl.BufferData(OpenGL.GL_ARRAY_BUFFER, quad_strip2.Length * sizeof(float), prt,
OpenGL.GL_STATIC_DRAW);
//bind second buffer
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, Buffers[1]);
//fill buffer
unsafe
fixed (float* verts = quad_strip3)
var prt = new IntPtr(verts);
gl.BufferData(OpenGL.GL_ARRAY_BUFFER, quad_strip3.Length * sizeof(float), prt,
OpenGL.GL_STATIC_DRAW);
gl.VertexAttribPointer((uint)Attrib_IDs.vPosition, 3, OpenGL.GL_FLOAT, false, 0, new IntPtr(0));
gl.EnableVertexAttribArray((uint)Attrib_IDs.vPosition);
绘图代码
//SKIPED FILLING VERTEX SHADER WITH MATRIXES
//DRAW ARRAYS
//binf first array and draw it
gl.BindVertexArray(Buffers[0]);
for (int i = 0; i < 34; i++)
gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 52, 52);
//binf second array and draw it
gl.BindVertexArray(Buffers[1]);
shaderProgram.SetUniform3(gl, "color", 0, 0.4f, 1);
for (int i = 0; i < 48; i++)
gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 26, 26);
//DRAW WIREFRAMES
shaderProgram.SetUniform3(gl, "color", 0, 0, 0);
gl.Enable(OpenGL.GL_POLYGON_OFFSET_FILL);
gl.PolygonOffset(1.0f, 1.0f);
gl.PolygonMode(FaceMode.FrontAndBack, PolygonMode.Lines);
gl.BindVertexArray(Buffers[0]);
for (int i = 0; i < 34; i++)
gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 52, 52);
gl.BindVertexArray(Buffers[1]);
for (int i = 0; i < 48; i++)
gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 26, 26);
gl.PolygonMode(FaceMode.FrontAndBack, PolygonMode.Filled);
结果我有这样的输出,这看起来不像我需要得到的。
【问题讨论】:
【参考方案1】:您需要在绘图代码中的每个BindBuffer
调用之后调用VertexAttribPointer
。 VertexAttribPointer
适用于当前绑定的缓冲区。您当前的代码在初始化代码中只有一个 VertexAttribPointer
调用,这是在调用 Buffers[1]
时发生的。因此,您的所有绘图调用都将使用该缓冲区中的顶点数据。
编辑:我还注意到您在绘制代码中使用了BindVertexArray
。顶点数组对象 (VAO) 是来自顶点缓冲区 (VBO) 的不同类型的对象,您不能只将 VBO 的 id 用于 BindVertexArray
调用。要让这一切暂时不使用 VAO,您可以从初始化代码中删除 VertexAttribPointer
调用。然后将两个VertexAttribPointer
调用添加到您的绘图代码中,并将BindVertexArray
替换为BindBuffer
,使其结构如下:
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, Buffers[0]);
gl.VertexAttribPointer((uint)Attrib_IDs.vPosition, 3, OpenGL.GL_FLOAT, false, 0, new IntPtr(0));
for (int i = 0; i < 34; i++)
gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 52, 52);
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, Buffers[1]);
gl.VertexAttribPointer((uint)Attrib_IDs.vPosition, 3, OpenGL.GL_FLOAT, false, 0, new IntPtr(0));
shaderProgram.SetUniform3(gl, "color", 0, 0.4f, 1);
for (int i = 0; i < 48; i++)
gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 26, 26);
另一种选择是您一直使用顶点数组对象 (VAO)。为此,您必须在初始化代码 (glGenVertexArrays
) 中创建这些对象,并在为每个缓冲区设置状态时绑定它们。它们允许您在设置期间设置所有状态,然后仅在准备绘制时进行一次绑定调用。您应该能够通过一些搜索找到相应的代码示例。
【讨论】:
能否提供小代码sn-p来解释你的答案? gl.VertexAttribPointer 中的什么参数应该指定我的缓冲区? 指定缓冲区的不是VertexAttribPointer
的参数。调用时当前绑定的缓冲区很重要。我会补充答案。以上是关于从不同的缓冲区绘制多个对象(数组切换)的主要内容,如果未能解决你的问题,请参考以下文章
WebGL入门(四十)-通过切换着色器实现一个页面同时展示多个立方体
OpenGL:尝试使用 VBO(顶点缓冲区对象)绘制线条,它不显示
我的OpenGL学习进阶之旅介绍顶点缓冲区对象VBO和元素数组缓冲区对象EBO,并对比使用VBO和不使用VBO绘制三角形的效果