【问题标题】:Rendering Multiple Materials on single Mesh在单个网格上渲染多个材质
【发布时间】:2020-01-20 23:36:38
【问题描述】:

在 Unity3D 中,我尝试渲染一个生物并在它被选中时显示其轮廓。

单独的生物被渲染得很好:

我下载了Outline Shader on Github 并将其作为第二个材质应用到我的网格中:

展开后的材质如下所示:

然而,结果却完全不像预期的那样:

在不太了解材质和着色器的情况下,我尝试摆弄,发现如果我将标准材质的渲染模式更改为透明,结果看起来很好:

但现在这个生物单独以一种奇怪的方式渲染,四肢与身体重叠:

实现我想要做的事情的正确方法是什么?你有我可以阅读更多的资源吗?

【问题讨论】:

  • 看起来您的其他材料也已设置为“透明”。
  • “其他材料”是什么意思?我将生物的材质(BluePBR)设置为透明。 (在图 3 中,您可以看到我更改的渲染模式被标记。
  • 如果生物设置为透明,您将获得上一张图片中显示的效果。 “透明”的整个想法是 Z 缓冲区不受影响,因此后续绘制会覆盖或与开始的任何内容混合。您需要多种材质(轮廓和 BluPBR),或者在着色器中弄脏您的手。
  • 您是否尝试过使用轮廓材质,而不是将 MainColor 设置为完全透明并保持主要材质不变?我不知道着色器,但您的 PBR 需要基于顶点的深度测试才能正常工作。然而,一般来说:你不应该为了让它与其他东西一起工作而使任何材料透明......它会影响渲染性能!
  • @3Dave 我有两种不同的材料,但是当我同时应用它们时。只有其中一个显示。

标签: unity3d shader


【解决方案1】:

您的设置的问题是渲染队列。透明对象在不透明对象之后渲染,因此您的轮廓只是在生物顶部绘制。如果您想更改渲染顺序,您必须将带有轮廓的对象视为“特殊”不透明对象(例如,绘制普通对象、绘制轮廓、绘制生物)。

这里有几个选择:

  1. 使用Cull Front - 这个着色器基本上是在原始对象的顶部绘制一个更大的对象副本,就像一个外壳。 Cull Front 使得它绘制对象后面的外壳的背面,而不是正面。
  2. 使用模板缓冲区标记绘制原始对象的区域,并在绘制轮廓时跳过它。

以下是您的着色器的修改版本(删除了第二个颜色通道和表面着色器通道,因为您不使用它们)。这是模板缓冲区选项。如果您想尝试另一个,请删除第一遍,第二遍中的模板块并将Cull Back替换为Cull Front。

Shader "Outlined/UltimateOutline"
{
    Properties
    {
        _Color("Main Color", Color) = (0.5,0.5,0.5,1)       

        _FirstOutlineColor("Outline color", Color) = (1,0,0,0.5)
        _FirstOutlineWidth("Outlines width", Range(0.0, 2.0)) = 0.15        

        _Angle("Switch shader on angle", Range(0.0, 180.0)) = 89
    }
    CGINCLUDE
    #include "UnityCG.cginc"

    struct appdata {
        float4 vertex : POSITION;
        float4 normal : NORMAL;
    };

    uniform float4 _FirstOutlineColor;
    uniform float _FirstOutlineWidth;

    uniform float4 _Color;
    uniform float _Angle;

    ENDCG

    SubShader{              
        Pass {
            Tags{ "Queue" = "Transparent-1" "IgnoreProjector" = "True" }
            ZWrite Off
            Stencil {
                Ref 1
                Comp always
                Pass replace
            }
            ColorMask 0
        }

        //First outline
        Pass{
            Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
            Stencil {
                Ref 1
                Comp NotEqual
            }

            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite Off
            Cull Back      //Replace this with Cull Front for option 1
            CGPROGRAM

            struct v2f {
                float4 pos : SV_POSITION;
            };

            #pragma vertex vert
            #pragma fragment frag

            v2f vert(appdata v) {
                appdata original = v;

                float3 scaleDir = normalize(v.vertex.xyz - float4(0,0,0,1));
                //This shader consists of 2 ways of generating outline that are dynamically switched based on demiliter angle
                //If vertex normal is pointed away from object origin then custom outline generation is used (based on scaling along the origin-vertex vector)
                //Otherwise the old-school normal vector scaling is used
                //This way prevents weird artifacts from being created when using either of the methods
                if (degrees(acos(dot(scaleDir.xyz, v.normal.xyz))) > _Angle) {
                    v.vertex.xyz += normalize(v.normal.xyz) * _FirstOutlineWidth;
                }
                else {
                   v.vertex.xyz += scaleDir * _FirstOutlineWidth;
                }

                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;
            }

            half4 frag(v2f i) : COLOR{
                return _FirstOutlineColor;
            }
        ENDCG
        }
    }
    Fallback "Diffuse"
}

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 2021-03-23
    • 2021-10-29
    • 1970-01-01
    • 2019-11-09
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    相关资源
    最近更新 更多