【问题标题】:OpenGL Vertex Arrays and GL_TRIANGLE_STRIP drawing errorOpenGL 顶点数组和 GL_TRIANGLE_STRIP 绘图错误
【发布时间】:2012-02-02 15:33:58
【问题描述】:

我正在使用 GL_TRIANGLE_STRIPS 和 LWJGL OpenGL Java 绑定实现高度图。当我使用“GL_BEGIN/GL_END”绘制“直接”时,它工作得很好,但是当高度图很大时,它工作得很慢。

由于我想继续使用 VBO,我现在正在学习如何使用顶点数组。这是我有问题的地方,绘图是错误的。条带的最后一个三角形似乎回到了第一个三角形。或许图片更好:

好图:

错误的顶点数组绘制:

我的正常绘图代码如下:

public void renderDirect() {
    //adapt the camera to the map
    float scale = 5.0f / Math.max(w - 1, l - 1);
    GL11.glScalef(scale, scale, scale);
    GL11.glTranslatef(-(float) (w - 1) / 2, 0.0f, -(float) (l - 1) / 2);

    //choose map color
    GL11.glColor3f(0.3f, 0.9f, 0.0f);

    for (int z = 0; z < l - 1; z++) {
        //Makes OpenGL draw a triangle at every three consecutive vertices
        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
        for (int x = 0; x < w; x++) {
            Vector3f normal = getNormal(x, z);
            GL11.glNormal3f(normal.getX(), normal.getY(), normal.getZ());
            GL11.glVertex3f(x, getHeight(x, z), z);
            normal = getNormal(x, z + 1);
            GL11.glNormal3f(normal.getX(), normal.getY(), normal.getZ());
            GL11.glVertex3f(x, getHeight(x, z + 1), z + 1);
        }
        glEnd();
    }
}

我的顶点数组绘制代码如下:

private void loadArrays(){
    //calculate the length of the buffers
    bLength = (l-1) * w * 6;
    //create the normal and vertex buffer array's
    dataBuffer = BufferUtils.createFloatBuffer(bLength*2);
    cBuffer = BufferUtils.createFloatBuffer(bLength);

    for (int z = 0; z < l - 1; z++) {
        //Fill up the buffers
        for (int x = 0; x < w; x++) {
            Vector3f normal = getNormal(x, z);
            dataBuffer.put(x).put(getHeight(x,z)).put(z);
            dataBuffer.put(normal.getX()).put(normal.getY()).put(normal.getZ());
            normal = getNormal(x, z + 1);
            dataBuffer.put(x).put(getHeight(x,z+1)).put(z+1);
            dataBuffer.put(normal.getX()).put(normal.getY()).put(normal.getZ());              
        }
    } 
}

int stride = 6*4;
public void renderDirect() {
    //adapt the camera to the map
    float scale = 5.0f / Math.max(w - 1, l - 1);
    GL11.glScalef(scale, scale, scale);
    GL11.glTranslatef(-(float) (w - 1) / 2, 0.0f, -(float) (l - 1) / 2);

    //choose map color
    GL11.glColor3f(0.3f, 0.9f, 0.0f);

    //Draw the vertex arrays
    glEnableClientState(GL_VERTEX_ARRAY);      
    glEnableClientState(GL_NORMAL_ARRAY); 

    dataBuffer.position(0);
    glVertexPointer(3, stride, dataBuffer);
    dataBuffer.position(3);
    glNormalPointer(stride,dataBuffer);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, bLength/3);    

    glDisableClientState(GL_VERTEX_ARRAY);      
    glDisableClientState(GL_NORMAL_ARRAY);
}    

我做错了什么?

【问题讨论】:

    标签: java opengl lwjgl vertex


    【解决方案1】:

    像这样将三角形条背靠背连接起来不会像您期望的那样工作。

    在循环中调用glDrawArrays() 调整firstcount 参数以绘制原始的N 三角形条带,或者在每行的末尾添加degenerate triangles 以重置条带起始位置。

    或者只使用GL_TRIANGLES :)

    【讨论】:

    • @OP 想一想,您需要为之前代码的每个 glBegin/glEnd 块调用 glDrawArrays。在这种情况下,考虑索引基元(因此glDrawElements 而不是glDrawArrays)可能也是一个好主意,因为每个顶点基本上都是两个条带的一部分。
    【解决方案2】:

    如果条带中连续绘制的三角形数量足够多,则可以节省大量时间的另一种解决方案如下:

    渲染三角形带时,您向 OpenGL 提供顶点信息流,它会为每个新顶点渲染一个三角形(例如,序列 ABCDEF 为您提供三角形 ABC、BCD、CDE、DEF)。现在,这将永远是一个单条(这就是为什么它被称为 GL_TRIANGLE_STRIP 而不是常见的复数命名)。

    无论如何,如果你需要引入一个间隙,你可以对你的绘制函数使用多次调用(虽然这是你想要避免的,对吧),但你也可以使用无效的多边形。

    无效的多边形是没有表面的多边形。您可以通过提供相同的点(如 ABB 或 ABA)来创建无效的多边形。据我所知,这样的多边形将在管道的早期被拒绝,因此不会给您带来太多开销。现在到你的特定问题。假设您有一个像“ABC|DEF”这样的间隙(由竖线表示)。修改您的流,使其看起来像这样“ABCCEEDEF”。这个可憎的东西给你三角形ABC,BCC,CCE,CEE,EDE,DEF。如果您考虑到无效的早期拒绝,您会得到 ABC 和 DEF - 正是您想要的。

    因此,总共每个间隙都会将您的顶点流炸毁三个三角形,这反过来使您在复杂性方面达到平衡时很容易看到。

    无论如何,如果你需要建立一个差距,你可以通过提供一个无效的三角形来做到这一点

    【讨论】:

      猜你喜欢
      • 2021-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 1970-01-01
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多