将深度缓冲区与 GL_LINES 结合使用
我想绘制删除了隐藏边缘的对象的边缘。我想要应用的想法是首先将对象的面渲染到深度缓冲区,然后在第二遍中在启用深度测试的情况下绘制边缘。
由于并非所有三角形边缘都应该可见,因此边缘是单独存储的(简单的示例:在立方体中,对角线边缘不应该可见,尽管它们存在,因为四边形被渲染为两个三角形)。因此,面是使用 GL_TRIANGLES
绘制的,边是使用 GL_LINES
和单独的顶点缓冲区绘制的。
问题在于,此设置会部分显示隐藏边缘,而部分隐藏可见边缘。如何才能获得正确的结果?
没有深度测试:
有深度测试:
渲染到深度缓冲区的面:
我使用带有附加颜色和深度缓冲区的帧缓冲区来绘制对象。
// Color buffer setup.
glBindTexture(GL_TEXTURE_2D, objectEdges);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 360, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
// Depth buffer setup.
glBindRenderbuffer(GL_RENDERBUFFER, objectFaces);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 640, 360);
// Framebuffer setup.
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, objectEdges, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, objectFaces);
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
assert(glGetError() == GL_NO_ERROR);
此设置工作没有任何问题。我按如下方式绘制对象:
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_TRUE);
glBindVertexArrayOES(vertexArray_faces);
glDrawArrays(GL_TRIANGLES, 0, vertexCount_faces);
glBindVertexArrayOES(0);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
glBindVertexArrayOES(vertexArray_edges);
glDrawArrays(GL_LINES, 0, vertexCount_edges);
glBindVertexArrayOES(0);
glDisable(GL_DEPTH_TEST);
使用的着色器只是一个标准的模型视图投影顶点着色器,以及一个为所有片段输出白色的片段着色器。
GLKMatrix4 projectionMatrix =
GLKMatrix4MakePerspective(
GLKMathDegreesToRadians(65.0f), 640.0 / 360.0f, 0.01f, 10.0f);
GLKMatrix4 modelViewMatrix =
GLKMatrix4MakeLookAt(0.2f, 0.4f, 0.2f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
I want to draw edges of an object with hidden edges removed. The idea I want to apply is to render the object's faces first to the depth buffer, then in a second pass drawing the edges with depth testing enabled.
Since not all triangle edges should be visible, the edges are stored separately (simple example: in a cube, the diagonal edges should not be visible, although they are there since a quad is rendered as two triangles). The faces are therefore drawn using GL_TRIANGLES
, the edges are drawn uing GL_LINES
with a separate vertex buffer.
The problem is that hidden edges are partly shown with this setup, and that visible edges are partly hidden. How can I achieve a proper result?
without depth testing:
with depth testing:
faces which are rendered to depth buffer:
I use a framebuffer with an attached color and depth buffer to draw my object.
// Color buffer setup.
glBindTexture(GL_TEXTURE_2D, objectEdges);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 360, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
// Depth buffer setup.
glBindRenderbuffer(GL_RENDERBUFFER, objectFaces);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 640, 360);
// Framebuffer setup.
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, objectEdges, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, objectFaces);
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
assert(glGetError() == GL_NO_ERROR);
This setup works without any problems. I draw my object as following:
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_TRUE);
glBindVertexArrayOES(vertexArray_faces);
glDrawArrays(GL_TRIANGLES, 0, vertexCount_faces);
glBindVertexArrayOES(0);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
glBindVertexArrayOES(vertexArray_edges);
glDrawArrays(GL_LINES, 0, vertexCount_edges);
glBindVertexArrayOES(0);
glDisable(GL_DEPTH_TEST);
The used shader is just a standard model-view-projection vertex shader, and a fragment shader which outputs white for all fragments.
GLKMatrix4 projectionMatrix =
GLKMatrix4MakePerspective(
GLKMathDegreesToRadians(65.0f), 640.0 / 360.0f, 0.01f, 10.0f);
GLKMatrix4 modelViewMatrix =
GLKMatrix4MakeLookAt(0.2f, 0.4f, 0.2f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您遇到的问题是,线条的深度值计算方式与填充图元的计算方式略有不同。您尝试做的事情正是所谓的“多边形offest”存在的原因之一。整个事情在附录中的官方编程指南中进行了描述: "Hidden-Line Removal"
You're running into the issue that depth values are calculated for lines slightly differently than for filled primitives. The very thing you try to do is one of the reasons for the existance of the so called "polygon offest". The whole thing is described in the official programming guide in the appendix: "Hidden-Line Removal"