【问题标题】:threejs - creating "cel-shading" for objects that are close bythreejs - 为附近的对象创建“cel-shading”
【发布时间】:2017-08-01 23:55:22
【问题描述】:

所以我正在尝试“勾勒”3D 对象。标准问题,答案是复制网格,将其着色为轮廓颜色,按比例放大,然后将其设置为仅渲染“指向错误方向”的面 - 对我们而言,这意味着设置side:THREE.BackSide 在材质中。例如这里https://stemkoski.github.io/Three.js/Outline.html

但是看看我会发生什么

这是我想做的

我有一堆靠得很近的物体——它们“进入”彼此的轮廓。

对我应该做什么有什么建议吗?我想看到的是渲染框架上的任何地方,这些形状与背景或彼此接触,那里有轮廓。

【问题讨论】:

标签: graphics 3d three.js webgl outline


【解决方案1】:

你想发生什么?是您示例中的一个网格还是一堆相交的网格。如果是一堆相交的网格,你希望它们有一个轮廓吗?其他网格呢?我的观点是,如果您使用多个网格,您需要一些方法来定义哪些“组”网格得到一个轮廓。

对于多个网格和一个轮廓,常见的解决方案是将单个组中的所有网格绘制到渲染目标以生成轮廓,然后对轮廓进行后期处理以扩展它。最后将剪影应用到场景中。我不知道three.js 的例子,但the concept is explained herethere's also many references here

另一种可能有效的解决方案应该可以将轮廓外壳移回 Z 中,这样就不会相交。一直返回(剪辑空间中的 Z = 1)或返回一些可设置的量。与组一起绘制,以便前面的对象集合具有阻挡后面的组的轮廓会更难。

例如,如果 I take this sample 那个囚犯 849 链接到

并将OutlineEffect.js 中的vertexShaderChunk 更改为此

  var vertexShaderChunk = `

    #include <fog_pars_vertex>

    uniform float outlineThickness;

    vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {

      float thickness = outlineThickness;
      const float ratio = 1.0; // TODO: support outline thickness ratio for each vertex
      vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + objectNormal, 1.0 );
    // NOTE: subtract pos2 from pos because BackSide objectNormal is negative
      vec4 norm = normalize( pos - pos2 );

   // ----[ added ] ----

      // compute a clipspace value
      vec4 pos3 = pos + norm * thickness * pos.w * ratio;

      // do the perspective divide in the shader
      pos3.xyz /= pos3.w;

      // just return screen 2d values at the back of the clips space
      return vec4(pos3.xy, 1, 1);

    }

  `;

如果您删除所有对reflectionCube 的引用并将清除颜色设置为白色renderer.setClearColor( 0xFFFFFF );,则更容易查看

原文:

之后:

【讨论】:

  • 谢谢你!但我不敢说这些是多个网格 - 我正在寻找多个轮廓。着色器需要一个聪明的“边缘检测器”,它可以检测颜色接触到不是它自己颜色的其他东西的任何地方。这样的事情存在吗?如果是这样,我可以看到它比我所看到的解决方案要先进得多......但是......我肯定不是第一个想要接触两个粗略的东西的人吗?
  • 也许你应该添加一个你想要实现的手工创建的图像
  • 现在添加:o 在某种意义上我只是想摆脱“故障”
  • 我能想到的唯一事情是(a)在图像上运行边缘检测后期处理,然后在结果上运行另一个着色器以扩展边缘,然后将其用作蒙版来绘制轮廓. (b) 一次绘制一个对象,然后绘制其轮廓,然后绘制下一个对象,然后是轮廓,而不是先绘制所有对象,然后再绘制所有轮廓(不确定这是否真的有效)
  • 还是谢谢你。第二个是行不通的,因为想象一个物体挂在另一个物体上!我要做的就是作弊:我正在缩小碎片的大小,它们的轮廓将占据它们实际尺寸当前占用的空间。这解决了我的问题,在这种情况下!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 2017-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多