使用TBO的非平面多边形的OpenGL平面着色

我试图实现基于缓冲区纹理的非平面多边形的平面着色(使用每个多边形单个法向量),但我似乎无法弄清楚如何正确设置的东西。 方法如下 –

  • 我使用GL_TRIANGLE_FAN渲染n- GL_TRIANGLE_FAN 。 一切都基于索引存储,所以我使用glDrawElements() 。 要知道一个n-gon结束,下一个开始,我使用原始的重新启动方法。

  • 在片段着色器中,可以访问gl_PrimitiveID 。 在渲染过程中,每个n-gon被分成(n-2)三角形,每个三角形都有一个唯一的gl_PrimitiveID

  • 每个三角形可以按照如下方式链接回原来的n-gon。 我们来考虑一个由五边形,三角形和四边形组成的网格(按此顺序)。 存储在第一缓冲区纹理中的数据是0,0,0,1,2,2 。 五边形(索引0 )呈现为三个三角形,三角形(索引1 )当然呈现为单个三角形,四边形(索引2 )呈现为两个三角形。 使用gl_PrimitiveID ,可以获得n-gon索引。

  • 最后,还有第二个caching纹理 ,每个原始n-gon包含一个法向量。 其他缓冲区纹理中的索引(例如,本例中的02 )可用于获取每个三角形的右法向量。

好的,为了创建缓冲区纹理,我使用

 GLuint faceIndexBuffer, faceIndexTexture, faceNormalBuffer, faceNormalTexture; glGenBuffers(1, &faceIndexBuffer); glBindBuffer(GL_TEXTURE_BUFFER, faceIndexBuffer); glBufferData(GL_TEXTURE_BUFFER, sizeof(unsigned int)*FaceIDs.size(), FaceIDs.data(), GL_DYNAMIC_DRAW); glGenTextures(1, &faceIndexTexture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_BUFFER, faceIndexTexture); // Unsigned integers (uint) glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, faceIndexBuffer); glGenBuffers(1, &faceNormalBuffer); glBindBuffer(GL_TEXTURE_BUFFER, faceNormalBuffer); glBufferData(GL_TEXTURE_BUFFER, sizeof(QVector3D)*FaceNorms.size(), FaceNorms.data(), GL_DYNAMIC_DRAW); glGenTextures(1, &faceNormalTexture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_BUFFER, faceNormalTexture); // RGB floats (vec3) glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, faceNormalBuffer); 

哪里

 QVector<unsigned int> FaceIDs; QVector<QVector3D> FaceNorms; 

上面的代码运行时, FaceIDsFaceNorms都不包含任何数据。 要更新实际的数据,我使用

 glBindBuffer(GL_TEXTURE_BUFFER, faceIndexBuffer); glBufferData(GL_TEXTURE_BUFFER, sizeof(unsigned int)*FaceIDs.size(), FaceIDs.data(), GL_DYNAMIC_DRAW); glBindBuffer(GL_TEXTURE_BUFFER, faceNormalBuffer); glBufferData(GL_TEXTURE_BUFFER, sizeof(QVector3D)*FaceNorms.size(), FaceNorms.data(), GL_DYNAMIC_DRAW); 

其他数据(顶点信息,即坐标和法线和索引)被存储为包含在VAO中的VBO和IBO。

片段着色器的相关部分 –

 layout(binding = 0) uniform samplerBuffer primIdToFaceId; layout(binding = 1) uniform samplerBuffer faceNormals; int faceIndex = int(texelFetch(primIdToFaceId, gl_PrimitiveID).x); vec3 norm = texelFetch(faceNormals, faceIndex).xyz; 

请注意,我在着色器中使用绑定,所以我不应该使用例如

 uFaceIDs = glGetUniformLocation(ShaderProg->programId(), "primIdToFaceId"); glUniform1i(uFaceIDs, 0); uFaceNorms = glGetUniformLocation(ShaderProg->programId(), "faceNormals"); glUniform1i(uFaceNorms, 1); 

不幸的是,有些东西显然不是以正确的方式设置的,因为我没有得到正确的法线。 这是相关的日志信息(缓冲区4对应于第一个包含索引的TBO,缓冲区5到第二个,包含正常) –

 → Log: QOpenGLDebugMessage("APISource", 131185, "Buffer detailed info: Buffer object 4 (bound to GL_TEXTURE_BUFFER, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.", "NotificationSeverity", "OtherType") → Log: QOpenGLDebugMessage("APISource", 131185, "Buffer detailed info: Buffer object 5 (bound to GL_TEXTURE_BUFFER, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.", "NotificationSeverity", "OtherType") 

当创建/更新数据,和

 → Log: QOpenGLDebugMessage("APISource", 131185, "Buffer detailed info: Buffer object 4 (bound to NONE, usage hint is GL_DYNAMIC_DRAW) will use VIDEO memory as the source for buffer object operations.", "NotificationSeverity", "OtherType") 

渲染时。 这里的最后一行表明什么可能是错误的,第一个TBO不再受约束了? 我忽略了什么?

修复! 其中一个TBO填充了无符号整数,因此必须使用usamplerBuffer来代替samplerBuffer

 layout(binding = 0) uniform usamplerBuffer primIdToFaceId; layout(binding = 1) uniform samplerBuffer faceNormals; 

一些debugging和结果。 运用

 fColor = vec4(0.0, mod(gl_PrimitiveID,256)/255, 0.0, 1.0); 

在片段着色器结果中

在这里输入图像描述

请注意,在此设置中,原始n-gon中的每个三角形都有其自己的颜色 –

在这里输入图像描述

运用

 fColor = vec4(0.0, mod(faceIndex,256)/255, 0.0, 1.0); 

结果是

在这里输入图像描述

现在n-gon中的所有三角形都具有相同的颜色。 最后,使用原始文章中的代码,我们得到了预期的平面着色效果 –

在这里输入图像描述

[编辑]我仍然得到

 → Log: QOpenGLDebugMessage("APISource", 131185, "Buffer detailed info: Buffer object 4 (bound to NONE, usage hint is GL_DYNAMIC_DRAW) will use VIDEO memory as the source for buffer object operations.", "NotificationSeverity", "OtherType") 

消息,尽管它似乎是无害的。