【问题标题】:Implementing toon effect with Metal shader and SceneKit使用 Metal shader 和 SceneKit 实现卡通效果
【发布时间】:2019-05-08 14:08:27
【问题描述】:

我想改进我最近的question 并在SceneKit 中使用金属(片段)着色器实现卡通效果like this

这是我的片段着色器,实现了简单的 phong 光照和卡通效果:

fragment float4 lightingFragment(VertexOut in [[stage_in]]) {

    float3 normal = normalize(in.normal);

    // For edges set color to yellow
    float3 V = normalize(in.eye - in.position.xyz);
    float edgeDetection = (abs(dot(V, normal)) > 0.1) ? 1 : 0;
    if ( edgeDetection != 1 ) {
        return float4(1, 1, 0, 1);
    }

    // Compute simple phong
    float3 lightDirection = normalize(light.position - in.position.xyz);
    float diffuseIntensity = saturate(dot(normal, lightDirection));
    float3 diffuseTerm = light.diffuseColor * material.diffuseColor * diffuseIntensity;

    // Ambient color
    float3 ambientTerm = light.ambientColor * material.ambientColor;

    return float4(ambientTerm + diffuseTerm, 1.0);
}

正如我所说,我受到this article 的启发,但我得到了非常不同的结果......

有什么想法吗?这是whole project

【问题讨论】:

标签: shader scenekit metal fragment-shader


【解决方案1】:

这种类型的单通道视图空间技术必然会产生比正常挤压技术更差的结果,但要使其完全发挥作用,您需要掌握坐标空间。

这里的目的是什么?好吧,我们想注意什么时候表面法线几乎垂直与视图方向,并绕过我们通常的光照计算,而是返回一个纯轮廓颜色。

确定垂直度通常意味着取点积,但在(a +Y up, right-handed)视图空间中,视图方向正好是(0, 0, -1),V 正好是(0, 0, 1),V 和视图空间法线之间的点积就是视图空间法线的z 分量。

有了这些知识,我们只需要确保正确地将视图空间正常传递给片段着色器。

首先,将我们从顶点着色器传出的法线名称更改为eyeNormal,这样我们就可以清楚我们正在操作的空间。然后计算为

out.eyeNormal = (scn_node.modelViewTransform * float4(in.normal, 0)).xyz;

(我们通常假设 MV 矩阵不包含任何非均匀缩放或剪切)。像往常一样在片段着色器中标准化:

float3 normal = normalize(in.eyeNormal);

摆脱那些三元垃圾;布尔表达式具有布尔类型,可以很好地强制转换为 float

float edgeFactor = normal.z <= 0.3;

请注意,因为我们在视图空间中操作,实际上我们不会看到任何具有normal.z &lt; 0 的片段,因此我们也删除了abs

最后,由于我们实际上不会通过提前退出来保存任何循环,因此我们可以在返回时使用mix 函数在亮色和边缘颜色之间进行选择:

return mix(float4(ambientTerm + diffuseTerm, 1.0), float4(1, 1, 0, 1), edgeFactor);

你有它,粗犷的剪影,价格的一半:

【讨论】:

  • 谢谢沃伦!对此,我真的非常感激。渲染只是我正在处理的副项目的一小部分,这就是我遇到这些基本问题的原因。我想我会在不久的将来发布更多。再次感谢!
  • 我创建了另一个问题,详细介绍了我的项目:stackoverflow.com/questions/53764324/…
猜你喜欢
  • 1970-01-01
  • 2019-01-19
  • 2016-02-28
  • 2019-01-27
  • 1970-01-01
  • 2016-04-24
  • 1970-01-01
  • 2018-10-26
  • 2020-12-21
相关资源
最近更新 更多