OpenGL/JOGL:顶点数组中的多个三角形扇形
我正在努力用顶点数组制作一些相当简单的形状,并且取得了一些良好的进展,但现在我想绘制 2 个(或更多)三角形扇形对象。有没有办法只对 gl.glDrawArrays(GL.GL_TRIANGLE_FAN,...
进行一次调用,或者我是否需要为每个风扇进行单独的调用?
维基百科的 三角带文章描述了一种称为原始重启的东西,但是OpenGL的顶点规范让我觉得这不适用于顶点数组。
绘制多个三角形扇形的正确方法是什么?这是我当前的绘制方法:
public void draw(GL gl){
if(vertices.length == 0)
return;
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL.GL_COLOR_ARRAY);
gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertBuff);
gl.glColorPointer(3, GL.GL_FLOAT, 0, colorBuff);
gl.glNormalPointer(GL.GL_FLOAT,0, normalBuff);
// drawArrays count is num of points, not indices.
gl.glDrawArrays(GL.GL_TRIANGLES, 0, triangleCount);
gl.glDrawArrays(GL.GL_QUADS, triangleCount, quadCount);
gl.glDrawArrays(GL.GL_TRIANGLE_FAN, triangleCount+quadCount, fanCount);
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL.GL_COLOR_ARRAY);
gl.glDisableClientState(GL.GL_NORMAL_ARRAY);
}
编辑
我更新了相关像这样绘制的部分:
for(int i = 0; i < fanLength.length; i++){
gl.glDrawArrays(GL.GL_TRIANGLE_FAN,
triangleCount+quadCount+fanDist[i], fanLength[i]);
}
其中 fanDist 是该扇形开始的偏移量(从扇形的起点开始),而 fanLength 是该扇形的长度
这似乎确实有效,这很好,但仍然是这样 。有更好的方法吗?
I'm working on making some moderately simple shapes with vertex arrays, and I'm making some good headway, but now I want to draw 2 (or more) triangle fan objects. Is there any way to only make one call to gl.glDrawArrays(GL.GL_TRIANGLE_FAN,...
or do I need to make a separate call for each fan?
Wikipedia's Triangle strip article describes something called primitive restart, but OpenGL's Vertex Specification makes me think this doesn't work with vertex arrays.
What is the correct way to draw multiple triangle fans? Here is my current draw method:
public void draw(GL gl){
if(vertices.length == 0)
return;
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL.GL_COLOR_ARRAY);
gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertBuff);
gl.glColorPointer(3, GL.GL_FLOAT, 0, colorBuff);
gl.glNormalPointer(GL.GL_FLOAT,0, normalBuff);
// drawArrays count is num of points, not indices.
gl.glDrawArrays(GL.GL_TRIANGLES, 0, triangleCount);
gl.glDrawArrays(GL.GL_QUADS, triangleCount, quadCount);
gl.glDrawArrays(GL.GL_TRIANGLE_FAN, triangleCount+quadCount, fanCount);
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL.GL_COLOR_ARRAY);
gl.glDisableClientState(GL.GL_NORMAL_ARRAY);
}
Edit
I updated the relevant section of draw like so:
for(int i = 0; i < fanLength.length; i++){
gl.glDrawArrays(GL.GL_TRIANGLE_FAN,
triangleCount+quadCount+fanDist[i], fanLength[i]);
}
Where fanDist is the offset (from the start of the fans) of the start of this fan, and fanLength is the length of this fan.
This does seem to work, which is nice, but still, is this the right way to do this? Is there a better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
原始重启确实适用于顶点数组和顶点缓冲区 - 如果不适用,它就不会真正有用。
但是,确实它与
glDrawArrays
结合使用时没有用处。让我们看一下两种技术:
原始重启
让我向您介绍一下
glDrawElements
: 像这样的调用类似于
So,而不是指定要从数组中绘制的元素的范围 ,您指定这些元素的精确索引。
然后你可以通过使用这样的数组来引入图元重新启动:
这将从前4个顶点绘制一个扇形,然后遇到“符号”以重新启动图元,然后它将在最后4个顶点绘制另一个扇形。
传递给 DrawElements 的索引不必是连续的范围!它们可以采用任何顺序,并且可以根据需要重复 - 这是该函数最好的部分。事实上,最好尽可能频繁地重用一个索引,因为如果结果被缓存,它只会被顶点着色器处理一次。因此,您可以自由地创建缓冲区,例如:
MultiDrawElements
在您的情况下,您可能需要使用
glMultiDrawElements
来代替。例如,如果您有 20 个顶点,并且您想从第一个顶点开始绘制一个 8 个顶点的扇形,并从第 10 个顶点开始绘制一个 10 个顶点的扇形,您可以执行以下操作:
因此您要做的工作会少一些。
选择您认为更有用的技术。我将让您在 Java/JOGL 中重写它,原理是相同的,但我猜您必须使用
Buffer
类来实现所有这些。Primitive restart does work with vertex arrays and vertex buffers - it wouldn't be really useful if it didn't.
However, it's true that it's not useful in conjunction with
glDrawArrays
.Let's have a look on two techniques:
Primitive Restart
Let me introduce
glDrawElements
to you: A call likeis analogous to
So instead of specifying a range of elements to draw from an array, you specify exact indices of those elements.
And then you can introduce primitive restarting by using such array:
This will draw a fan from the first 4 vertices, then will encounter the "sign" to restart the primitive, and then it will draw another fan of the last 4 vertices.
The indices passed to DrawElements don't have to be a consecutive range! They can be in any order and can be repeated as you desire - that's the whole best part of this function. In fact, it's best to reuse one index as often as possible, as it will get processed by vertex shader only once if the result's cached. So you're free to make buffers like:
MultiDrawElements
In your case, you might want to use
glMultiDrawElements
instead.If you have, say, 20 vertices and you want to draw one fan of 8 vertices starting from the first and one fan of 10 vertices starting from the 10th, you can do something like this:
Thus you have a bit less work to do.
Pick the technique you find more useful. I'll leave it to you to rewrite that in Java/JOGL, the principle is the same but you'll have to use the
Buffer
class for all those, I guess.