我试图实现基于缓冲区纹理的非平面多边形的平面着色(使用每个多边形单个法向量),但我似乎无法弄清楚如何正确设置的东西。 方法如下 –
我使用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包含一个法向量。 其他缓冲区纹理中的索引(例如,本例中的0
和2
)可用于获取每个三角形的右法向量。
好的,为了创建缓冲区纹理,我使用
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;
上面的代码运行时, FaceIDs
和FaceNorms
都不包含任何数据。 要更新实际的数据,我使用
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")
消息,尽管它似乎是无害的。