【问题标题】:How to colour vertices as a grid (like wireframe mode) using shaders?如何使用着色器将顶点着色为网格(如线框模式)?
【发布时间】:2019-06-21 23:19:39
【问题描述】:
我创建了一个平面,每个正方形有六个顶点,形成一个地形。
我使用像素着色器中的地形高度值为每个顶点着色。
我正在寻找一种将顶点之间的像素着色为黑色的方法,同时保持其他所有内容相同以创建网格效果。与线框模式相同的效果,除了对角线,透明部分应该是正常颜色。
我的地形,以及它在线框模式下的样子:
如何在像素着色器或其他方式中执行此操作?
【问题讨论】:
标签:
c++
shader
directx-11
hlsl
【解决方案1】:
请参阅“Solid Wireframe” - 几年前的 NVIDIA 论文。
这个想法基本上是这样的:包括一个几何着色器,它为每个顶点生成重心坐标作为变量。在您的片段/像素着色器中,检查重元素的值。如果它们低于某个阈值,您可以为像素着色,但是您希望您的线框被着色。否则,照常点亮它。
给定一个具有顶点 A、B、C 的面,您将生成以下重心值:
答:1,0,0
B:0,1,0
C: 0,0,1
在您的片段着色器中,查看该片段的 bary 的任何分量是否小于 0.1。如果是这样,则意味着它靠近脸部的边缘之一。 (如果您想花哨的话,哪个组件低于阈值也会告诉您哪个边缘。)
我看看能不能找到链接,过几天再更新一下。
请注意,这篇论文也有大约 10 年的历史。这些天在某些情况下,有一些方法可以在没有几何着色器的情况下获得重坐标,我相信还有其他解决方法。 (几何着色器有自己的位置,但不是性能的最佳朋友。)
此外,虽然 geom 着色器带有 perf hit,但它们比第二遍绘制线框要快得多。在 GL(或 DX)中以线框模式绘制会带来显着的性能损失,因为您要求光栅化器模拟 Bresenham 的线算法。这不是光栅化器的工作方式,而且速度非常慢。
此方法还可以解决您在两次通过时可能遇到的任何 z-fighting 问题。
如果您的网格是单个三角形,您可以跳过几何着色器并将所需的值打包到顶点缓冲区中。但是,由于顶点在除单个三角形之外的任何模型中的面之间共享,因此事情变得有点复杂。
或者,为了好玩:将此作为后期处理步骤。在片段着色器中查找高 ddx()/ddy()(或 dFdx()/dFdy(),取决于您的 API)值。这也可以让您制作一些有趣的效果。
【解决方案2】:
假设您有一个包含网格所有顶点的顶点缓冲区,请创建一个使用顶点缓冲区的索引缓冲区,但不要将 3 组用于三角形,而将 2 组用于线段。这将是一个行列表,应该包含构成网格正方形的所有对。您可以在程序中自动生成此列表。
渲染的粗略算法:
- 正常渲染地形
- 将原始拓扑切换到线路列表
- 分配新的索引缓冲区
- 禁用深度剔除(或为顶点着色器中的每个点添加一个小的高度值,以便网格出现在地形上方)
- 渲染行列表
这应该会产生您正在寻找的地形效果,在地形上绘制和着色并在其顶部使用方形网格。您需要在像素着色器中放置一个开关(通过一个常量缓冲区),告诉它何时渲染网格,以便它可以将网格绘制为黑色,而不是使用高度值。