首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >OpenGL/JOGL:顶点数组中的多个三角形扇形

OpenGL/JOGL:顶点数组中的多个三角形扇形
EN

Stack Overflow用户
提问于 2010-12-08 11:24:40
回答 1查看 7.3K关注 0票数 12

我正在使用顶点数组制作一些中等简单的形状,并且取得了一些不错的进展,但现在我想绘制2个(或更多)三角形扇形对象。有没有办法只给gl.glDrawArrays(GL.GL_TRIANGLE_FAN,...打一次电话,或者我需要为每个风扇单独打一个电话?

维基百科的Triangle strip文章描述了一种叫做原语重启的东西,但是OpenGL的Vertex Specification让我认为这不适用于顶点数组。

绘制多个三角形扇子的正确方法是什么?下面是我当前的绘制方法:

代码语言:javascript
运行
AI代码解释
复制
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);
}

编辑

我像这样更新了draw的相关部分:

代码语言:javascript
运行
AI代码解释
复制
    for(int i = 0; i < fanLength.length; i++){
        gl.glDrawArrays(GL.GL_TRIANGLE_FAN, 
            triangleCount+quadCount+fanDist[i], fanLength[i]);
    }

其中,fanDist是该风扇起点的偏移量(相对于风扇起点),fanLength是该风扇的长度。

这看起来确实有效,这很好,但是这是正确的方法吗?有没有更好的方法?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-12-08 12:19:34

基元重启确实适用于顶点数组和顶点缓冲区-如果不这样做,它将不会真正有用。

但是,它在与glDrawArrays结合使用时确实没有用处。

让我们来看看两种技术:

原语重启

让我向您介绍glDrawElements:一个像这样的调用

代码语言:javascript
运行
AI代码解释
复制
glDrawArrays(mode, 0, 5);

类似于

代码语言:javascript
运行
AI代码解释
复制
GLuint idxs[] = {0, 1, 2, 3, 4}; // C code, but idea's the same in Java
glDrawElements(mode, 5, GL_UNSIGNED_INT, idxs);

因此,不是指定要从数组中提取的元素的精确索引,而是指定这些元素的。

然后你可以通过使用这样的数组来引入原语重启:

代码语言:javascript
运行
AI代码解释
复制
GLuint PRIMITIVE_RESTART = 12345; // magic value

glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(PRIMITIVE_RESTART);
GLuint idxs[] = {0, 1, 2, 3, PRIMITIVE_RESTART, 4, 5, 6, 7};
glDrawElements(mode, 9, GL_UNSIGNED_INT, idxs);

这将从前4个顶点绘制一个扇形,然后将遇到重新启动基本体的“符号”,然后它将绘制最后4个顶点的另一个扇形。

传递给DrawElements的索引不必是连续的范围!它们可以是任何顺序,并且可以按你想要的方式重复--这就是这个函数最好的部分。事实上,最好是尽可能频繁地重用一个索引,因为如果结果被缓存,顶点着色器只会处理一次。所以你可以像这样自由地制作缓冲区:

代码语言:javascript
运行
AI代码解释
复制
GLuint idxs[] = {0, 6, 3, 4, 6, 2, PRIMITIVE_RESTART, 2, 6, 3, 3, 5, 2}; // etc.

MultiDrawElements

在您的示例中,您可能希望改用glMultiDrawElements

如果你有20个顶点,你想从第一个顶点开始画一个8个顶点的扇形,从第10个顶点开始画一个10个顶点的扇形,你可以这样做:

代码语言:javascript
运行
AI代码解释
复制
// assuming glVertexPointer is already set
GLuint startingElements[] = {0, 9};
GLuint counts[] = {8, 10};
glMultiDrawArrays(GL_TRIANGLE_FAN, startingElements, counts, 2); // 2 fans

因此,您需要做的工作就少了一点。

选择你认为更有用的技术。我将留给您用Java/JOGL重写它,原理是相同的,但我想您必须使用Buffer类来完成所有这些工作。

票数 18
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4386861

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档