21

在 OpenGL 中,我可以通过正常绘制对象来勾勒对象,然后使用模板缓冲区再次将其绘制为线框,这样原始对象就不会被覆盖。但是,这会导致轮廓具有一种纯色。

在此处输入图像描述

在这张图片中,生物轮廓的像素似乎越远离它们所描绘的生物越透明。如何使用 OpenGL 实现类似的效果?

4

4 回答 4

8

我迟到了答案,但我试图实现同样的目标,并认为我会分享我正在使用的解决方案。

使用不那么复杂的着色器可以在单个绘制操作中实现类似的效果。

在片段着色器中,您将根据闪电和纹理计算片段的颜色,为您提供未突出显示的颜色“colorA”。

您的第二种颜色是轮廓颜色“colorB”。

您应该将片段获取到相机矢量,对其进行归一化,然后获得该矢量与片段法线的点积。

片段到相机矢量只是片段在眼睛空间中的位置的倒数。

片段的颜色是:

float CameraFacingPercentage = dot(v_fragmentToCamera, v_Normal);
gl_FragColor = ColorA * CameraFacingPercentage + ColorB * (1 - FacingCameraPercentage);

这是基本想法,但您必须尝试使用​​或多或少的轮廓颜色。此外,模型的凹面部分也将突出显示,但问题中发布的图像也是如此。

于 2016-05-16T18:36:21.097 回答
7

他们没有为此使用线框。我猜它与着色器密切相关并且需要这个:

  1. 将对象渲染到模板缓冲区
  2. 在应用模糊时使用选择的颜色渲染模板缓冲区
  3. 在它上面渲染模型
于 2012-10-16T22:13:55.007 回答
2

据我所见,屏幕上的效果很短,许多“边缘”效果不是纯边缘,就像漫画轮廓一样。大多数情况下,你有一个通道是你正常渲染对象,然后一个通道只有几何体(没有纹理)和一个 GLSL 着色器。在片段着色器中,法线被采用并且该法线垂直于您为对象着色的相机矢量。然后通过包括接近完美垂直的区域来平滑效果。

我将不得不查找确切的数学,但我认为如果您将相机矢量的点积与法线相乘,您会得到“垂直度”的量。然后,您可以通过 exp 之类的函数运行以偏向 1。

所以(不保证它是正确的):

exp(dot(vec3(0, 0, 1), normal));

(注意:一切都在屏幕空间中。)

于 2012-10-17T12:44:25.317 回答
2

使用 dotprod(view,normal) 检测 GLSL 着色器中的边缘

http://en.wikibooks.org/wiki/GLSL_Programming/Unity/Toon_Shading#Outlines

于 2012-10-17T11:50:23.597 回答