4

我正在尝试实施这篇论文。我已经完成了大部分工作,但是关于将任意非几何数据发送到着色器以用于确定和显示几何边缘的部分给我带来了问题。我已经成功地使用我对 VBO 的了解成功地发送了我的大部分数据。但是,我需要发送大量数据,这就需要使用多个纹理坐标。

我已经实现了几种我认为设置多组纹理坐标的正确方法的变体,并遵循了许多论坛海报的说明。到目前为止,没有任何解决方案有效。

对于上下文,该程序为模型中的每个唯一边发送 4 个几乎相同的副本,其中包含一组 4 个顶点、2 个法向量、一个浮点数和一个整数(存储为浮点数)。我已经这样排列了数据:

v0 is stored in gl_Vertex (vec3)
v1 is stored in gl_Color (vec3)
v2 is stored in gl_MultiTexCoord0 (vec3)
v3 is stored in gl_MultiTexCoord1 (vec3)
n0 is stored in gl_Normal (vec3)
n1 is stored in gl_SecondaryColor (vec3)
r and i are stored in gl_MultiTexCoord2 (vec2)

4 个副本之间的唯一区别是 i 值,它有助于确定在找到可绘制边时如何组织顶点。

如您所见,我至少需要 3 个纹理坐标。我能够让第一个工作正常(gl_MultiTexCoord0),但是任何后续纹理坐标,虽然在显卡上,似乎有无法控制的行为,有时工作,但通常不是。

我的渲染函数曾经看起来像这样:

void Mesh::RenderLineEdgesGPU()
{
    // Enable client state
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    // Turn on edge shader
    edgeProgram.Activate();

    // Link buffers
    // v0
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
    glVertexPointer(3, GL_FLOAT, 0, 0);

    // v1
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
    glColorPointer(3, GL_FLOAT, 0, 0);

    // v2
    glClientActiveTextureARB(GL_TEXTURE0_ARB);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
    glTexCoordPointer(3, GL_FLOAT, 0, 0);

    // v3
    glClientActiveTextureARB(GL_TEXTURE1_ARB);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
    glTexCoordPointer(3, GL_FLOAT, 0, 0);

    // n0
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
    glNormalPointer(GL_FLOAT, 0, 0);

    // n1
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
    glSecondaryColorPointer(3, GL_FLOAT, 0, 0);

    // r and i
    glClientActiveTextureARB(GL_TEXTURE2_ARB);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
    glTexCoordPointer(2, GL_FLOAT, 0, 0);

    // Indicies
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);

    // Draw
    glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);

    // Turn off edge shader
    edgeProgram.Deactivate();

    // Disable client state
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

这是我原来的。它绝对适用于 v0、v1 和 v2。它似乎适用于“r 和 i”,但这可能是一种错觉。我还没有能力测试 n0 或 n1。v3 绝对行不通。如您所见,我将它们绘制为点,这告诉我它们是否存在(通过着色器)。v0、v1 和 v2 都在那里。尝试对 v3 执行相同操作会在原点处产生一个点,或者根本没有。

在网上查看建议后,这是我的新设置:

void Mesh::RenderLineEdgesGPU()
{
    // Enable client state
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_SECONDARY_COLOR_ARRAY);

    // Turn on edge shader
    edgeProgram.Activate();

    // Link buffers
    // v0
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
    glVertexPointer(3, GL_FLOAT, 0, 0);

    // v1
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
    glColorPointer(3, GL_FLOAT, 0, 0);

    // v2
    glClientActiveTextureARB(GL_TEXTURE0_ARB);

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glActiveTextureARB(GL_TEXTURE0_ARB);
    glEnable(GL_TEXTURE_2D);

    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
    glTexCoordPointer(3, GL_FLOAT, 0, 0);

    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    // v3
    glClientActiveTextureARB(GL_TEXTURE1_ARB);

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glActiveTextureARB(GL_TEXTURE1_ARB);
    glEnable(GL_TEXTURE_2D);

    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
    glTexCoordPointer(3, GL_FLOAT, 0, 0);

    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    // n0
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
    glNormalPointer(GL_FLOAT, 0, 0);

    // n1
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
    glSecondaryColorPointer(3, GL_FLOAT, 0, 0);

    // r and i
    glClientActiveTextureARB(GL_TEXTURE2_ARB);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
    glTexCoordPointer(2, GL_FLOAT, 0, 0);

    // Indicies
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);

    // Draw
    glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);

    // Turn off edge shader
    edgeProgram.Deactivate();

    // Disable client state
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
}

请注意我是如何围绕每个纹理坐标列表的实际“加载”完成glEnableClientState/调用的。glDisableClientState我也使用glActiveTextureARBglEnable(GL_TEXTURE_2D)。虽然我想我可能明白为什么glActiveTextureARB需要这里,但另一个让我感到困惑。根据GLSL 常见错误页面glEnable(GL_TEXTURE_2D),当您制作自己的着色器时不应该使用,因为无论如何使用着色器都会忽略此调用。

就是这样了。我已经走了这么远,但找不到任何专门解决如何在纹理坐标中发送非纹理坐标数据的教程。也许如果有人知道这方面的教程,我的问题就会得到缓解。谢谢你的时间!

4

1 回答 1

8

glClientActiveTextureARB更改调用后的特定纹理坐标单元glEnableClientState(GL_TEX_COORD_ARRAY)glTexCoordPointer并将更改。

glActiveTextureARB影响glEnable(GL_TEXTURE_2D),正如您所提到的,您不需要着色器。

如果您仔细查看您的代码,只选择这 5 个调用(以及它们等效的禁用),您将拥有以下内容:

    glClientActiveTextureARB(GL_TEXTURE0_ARB);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glActiveTextureARB(GL_TEXTURE0_ARB);
    glEnable(GL_TEXTURE_2D);
    glTexCoordPointer(3, GL_FLOAT, 0, 0);
    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glClientActiveTextureARB(GL_TEXTURE1_ARB);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glActiveTextureARB(GL_TEXTURE1_ARB);
    glEnable(GL_TEXTURE_2D);
    glTexCoordPointer(3, GL_FLOAT, 0, 0);
    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glClientActiveTextureARB(GL_TEXTURE2_ARB);
    glTexCoordPointer(2, GL_FLOAT, 0, 0);
    glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);

好的,我们已经说过 glActiveTextureARB 和 glEnable 没有用(顺便说一句,您启用/禁用GL_TEXTURE_2D之间没有任何绘制,这是没有用的),所以删除它们:

    glClientActiveTextureARB(GL_TEXTURE0_ARB);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(3, GL_FLOAT, 0, 0);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glClientActiveTextureARB(GL_TEXTURE1_ARB);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(3, GL_FLOAT, 0, 0);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glClientActiveTextureARB(GL_TEXTURE2_ARB);
    glTexCoordPointer(2, GL_FLOAT, 0, 0);

    glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);

现在突出的是什么?2个问题:

  • 您在执行 Draw 之前禁用您的客户端状态
  • 您没有为 TEXTURE2 设置启用位

你应该写什么?沿着这些思路:(请注意,您需要将 BindBuffer 调用添加回每个 Pointer 调用):

    // texture coord 0
    glClientActiveTextureARB(GL_TEXTURE0_ARB); // program texcoord unit 0
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); // enable array data to shader
    glTexCoordPointer(3, GL_FLOAT, 0, 0); // say what data

    // texture coord 1
    glClientActiveTextureARB(GL_TEXTURE1_ARB);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(3, GL_FLOAT, 0, 0);

    // texture coord 2
    glClientActiveTextureARB(GL_TEXTURE2_ARB);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, 0, 0);

    glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);

    // done with those texcoord units, turn them off
    glClientActiveTextureARB(GL_TEXTURE0_ARB);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glClientActiveTextureARB(GL_TEXTURE1_ARB);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glClientActiveTextureARB(GL_TEXTURE2_ARB);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

关于 BindBuffer: 的更多评论glBindBufferARB(GL_ARRAY_BUFFER_ARB,...)不受影响,但影响下一次调用。本质上,将and视为为.glClientActiveTextureARBglTexCoordPointerglClientActiveTextureARBglBindBufferARBglTexCoordPointer

最后一件事,您可能希望将其中一些 VBO 分组到更少的缓冲区中。也许还有另一个问题?(提示,2 个参数glTexCoordPointer不必为 0)

于 2009-11-05T08:22:49.337 回答