在 OpenGL 中,我可以通过正常绘制对象来勾勒对象,然后使用模板缓冲区再次将其绘制为线框,这样原始对象就不会被覆盖。但是,这会导致轮廓具有一种纯色。
在这张图片中,生物轮廓的像素似乎越远离它们所描绘的生物越透明。如何使用 OpenGL 实现类似的效果?
我迟到了答案,但我试图实现同样的目标,并认为我会分享我正在使用的解决方案。
使用不那么复杂的着色器可以在单个绘制操作中实现类似的效果。
在片段着色器中,您将根据闪电和纹理计算片段的颜色,为您提供未突出显示的颜色“colorA”。
您的第二种颜色是轮廓颜色“colorB”。
您应该将片段获取到相机矢量,对其进行归一化,然后获得该矢量与片段法线的点积。
片段到相机矢量只是片段在眼睛空间中的位置的倒数。
片段的颜色是:
float CameraFacingPercentage = dot(v_fragmentToCamera, v_Normal);
gl_FragColor = ColorA * CameraFacingPercentage + ColorB * (1 - FacingCameraPercentage);
这是基本想法,但您必须尝试使用或多或少的轮廓颜色。此外,模型的凹面部分也将突出显示,但问题中发布的图像也是如此。
他们没有为此使用线框。我猜它与着色器密切相关并且需要这个:
据我所见,屏幕上的效果很短,许多“边缘”效果不是纯边缘,就像漫画轮廓一样。大多数情况下,你有一个通道是你正常渲染对象,然后一个通道只有几何体(没有纹理)和一个 GLSL 着色器。在片段着色器中,法线被采用并且该法线垂直于您为对象着色的相机矢量。然后通过包括接近完美垂直的区域来平滑效果。
我将不得不查找确切的数学,但我认为如果您将相机矢量的点积与法线相乘,您会得到“垂直度”的量。然后,您可以通过 exp 之类的函数运行以偏向 1。
所以(不保证它是正确的):
exp(dot(vec3(0, 0, 1), normal));
(注意:一切都在屏幕空间中。)
使用 dotprod(view,normal) 检测 GLSL 着色器中的边缘
http://en.wikibooks.org/wiki/GLSL_Programming/Unity/Toon_Shading#Outlines