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