glDrawElement 的 OpenGL 渲染问题
Posted
技术标签:
【中文标题】glDrawElement 的 OpenGL 渲染问题【英文标题】:OpenGL Rendering Issue With glDrawElement 【发布时间】:2012-11-01 21:33:55 【问题描述】:当谈到我应该为我的 OpenGL 延迟渲染使用什么函数时,我有点困惑。
我有一个 VBO 列表(顶点缓冲区对象)
每一个都代表一种顶点,可能是(位置+颜色)
我也有一个用于低级的
当我想渲染不同的对象时,我的问题就出现了
我习惯使用 DirectX 方式 1)激活你的顶点缓冲区 2)激活你的索引缓冲区 3)然后你在你的draw call上指定你的原始类型 顶点缓冲区的起始顶点、最小顶点索引、顶点计数、起始索引和原始计数
由于我可以使用,所以我丢失了 openGL:
glDrawElements - 但它使用渲染模式、对象计数、索引字节类型和索引
这基本上告诉我它将在 VBO 的开头呈现,如果我在那里有多个对象,这对我没有任何帮助。
任何人都知道openGL有什么渲染功能,我可以指定VBO中从哪里开始渲染并指定我的起始顶点位置?我希望有人有任何想法=\
【问题讨论】:
【参考方案1】:glDrawElements 不是从 VBO 的开头开始,而是从您指定要开始的指针的任何位置开始。
如果你有一个 VBO,并且你想从它的后半部分开始渲染,那么你将字节偏移设置为从作为 glVertexAttribPointer 的最后一个属性开始。
【讨论】:
所以为了使用 glDrawElements 我必须在它之前使用 glVertexAttribPointer? 是的,您必须始终设置一个(或多个)指针以使用 glDrawElements(前提是您没有使用已弃用的“立即模式”(glBegin/End 等)。指针告诉 glDrawElements 在哪里从中获取数据。 嗯,好的,谢谢。我一直认为,当我使用 glVertexAttribPointer 时,它是告诉它如何拆分我的顶点而不是从我的 vbo 开始渲染的位置【参考方案2】:您有多种选择。
您可以通过在绘制该对象之前发出更多glVertexAttribPointer
调用来重新定位每个特定对象的顶点数据的起点。或者你可以使用glDrawElementsBaseVertex,在这里你可以指定一个顶点索引,所有被获取的索引都被添加到。
后者应该在任何仍受支持的非英特尔硬件上可用。
【讨论】:
是的,我正在使用 glDrawElementsBaseVertex 环顾四周。在我看来,它是最干净的,没有撕掉大量的渲染组件【参考方案3】:编辑:我刚刚意识到,如果您不使用着色器,这可能不适用,但由于我不熟悉旧版 OpenGL,我不确定我的帖子对您有什么好处。您正在使用/定位哪个版本?
我最近问了一个关于 glDrawElements here 的问题。希望我发布的内容能提供一些解释/示例。
我的理解方式:你的索引是由你决定的,所以如果你想从第二个顶点开始,你可以尝试(一个基本的骨架,没有 glVertexAttribPointer 调用等但是如果你愿意,我可以添加它们):
const float VBOdata =
//Some X and Y coordinates for triangle1 (in the first quadrant)
//(z = 0, w = 1 and are not strictly necessary here)
0.0f, 1.0f, 0.0f, 1.0f //index 0
0.0f, 0.0f, 0.0f, 1.0f //1
1.0f, 0.0f, 0.0f, 1.0f //2
//Some X and Y coordinates for triangle2 (in the second quadrant)
0.0f, -1.0f, 0.0f, 1.0f //3
0.0f, 0.0f, 0.0f, 1.0f //4
-1.0f, 0.0f, 0.0f, 1.0f //5
//Now some color data (all white)
1.0f, 1.0f, 1.0f, 1.0f, //0
1.0f, 1.0f, 1.0f, 1.0f, //1
1.0f, 1.0f, 1.0f, 1.0f, //2
1.0f, 1.0f, 1.0f, 1.0f, //3
1.0f, 1.0f, 1.0f, 1.0f, //4
1.0f, 1.0f, 1.0f, 1.0f, //5
;
const GLubyte indices[] =
3, 4, 5,
;
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, indices);
其中 GL_TRIANGLES 是基元的类型,3 是“索引”内的元素数量,GL_UNSIGNED_BYTE 是如何解释它们,“索引”只是数组的名称。
这应该只绘制第二个三角形。你也可以试试glDrawElementsBaseVertex,不过我自己没有亲自尝试过。我收集到的是,您将从 0 开始生成/显式编码索引,但给出一个偏移量,以便它实际上在 0+offset、1+offset 等处读取。
这有帮助吗?
【讨论】:
我明白你在说什么,但我试图控制的是索引将被加载,就好像说“模型 1,使用索引,1,2,3,4”但是然后加载“模型 2,使用加载为 1、2、3、4 的自己的索引”现在你有 2 个模型完全在同一个 vbo 中,当我尝试使用 glDrawElements 模型时,ibo 和 glDrawElements 最终会渲染模型 1 2. 啊,所以在不同的绘制调用之间保持相同的索引,但是为新模型替换 VBO 中的数据?说得通。那么蒂姆说的是正确的,您将使用 glVertexAttribPointer 并指向 VBO 中的新位置,同时让 GlDrawElements 调用相同。 (除非我又完全错过了你的意思,在这种情况下我很抱歉。) 是的,第二部分似乎是正确的。我要找到一种方法来使 glVertexAttribPointer 调用健壮,这应该可以解决这个问题以上是关于glDrawElement 的 OpenGL 渲染问题的主要内容,如果未能解决你的问题,请参考以下文章
OpenGL阴影映射,具有多个glDrawElements的帧缓冲区
我的OpenGL学习进阶之旅使用glDrawElements绘制的时候,不绘制任何图元,报错 1282 即 GL_INVALID_OPERATION
我的OpenGL学习进阶之旅使用glDrawElements绘制的时候,不绘制任何图元,报错 1282 即 GL_INVALID_OPERATION