Combining Two Shaders into One Shader

僤鯓⒐⒋嵵緔 提交于 2019-12-11 08:03:22

问题


Unity Project, Want to combine these two shaders into one shader to get both of their functionality. One shader is for lighting, the other shader is for rendering better. How do I combine?

Shader "Transparent/Cutout/Lit3dSprite" {
Properties{
    _MainCol("Main Tint", Color) = (1,1,1,1)
    _MainTex("Main Texture", 2D) = "white" {}
    _Cutoff("Alpha cutoff", Range(0,1)) = 0.5
}

SubShader{
    Tags {"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout" "PreviewType" = "Plane"}
    Cull Off
    LOD 200

    CGPROGRAM
    #pragma surface surf SimpleLambert alphatest:_Cutoff addshadow fullforwardshadows
    #pragma target 3.0

    sampler2D _MainTex;
    fixed4 _MainCol;

    half4 LightingSimpleLambert(SurfaceOutput s, half3 lightDir, half atten) 

{
            half4 c;
            c.rgb = s.Albedo * _MainCol.rgb * (atten)* _LightColor0.rgb;
            c.a = s.Alpha;
            return c;
        }

        struct Input {
            float2 uv_MainTex;
        };

        void surf(Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _MainCol;
            o.Albedo = lerp(c.rgb, c.rgb, c.a);
            o.Alpha = c.a;
        }
        ENDCG
    }

    Fallback "Transparent/Cutout/VertexLit"
}

Shader 2:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "RetroAA/Sprite"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,0,0,0)
    }
    SubShader
    {
        Tags {
            "Queue"="Transparent" 
            "IgnoreProjector"="True" 
            "RenderType"="Transparent" 
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
        LOD 100

        Cull Off
        Lighting Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog

            #include "RetroAA.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float4 color : COLOR;
                float2 uv : TEXCOORD0;
            };

            struct v2f {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                float2 uv : TEXCOORD0;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _MainTex_TexelSize;

            float4 _Color;

            v2f vert(appdata v){
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.color = v.color * _Color;

                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                fixed4 color = RetroAA(_MainTex, i.uv, _MainTex_TexelSize);
                return i.color*color*color.a;
            }
            ENDCG
        }
    }
}

回答1:


The second shader isn't too complicated, and can be merged into the first one by just using the second shader's code to change how the first shader's surf calculates fixed4 c.

You'll also need to include the definition for RetroAA and include the Texel Size of the main texture in the shader variables.

However, the first shader assumes that there is no partial transparency, and the second shader requires it, so you have to accomodate that. You'll need to use Alpha blending, change the RenderType and Queue to Transparent, and indicate ZWrite Off.

Here is what that might all look together:

Shader "Transparent/Cutout/Lit3dSprite" {
    Properties{
        _MainCol("Main Tint", Color) = (1,1,1,1)
        _MainTex("Main Texture", 2D) = "white" {}
        _Cutoff("Alpha cutoff", Range(0,1)) = 0.5
    }

        SubShader{
            // change RenderType and Queue to Transparent
            Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane"}
            Cull Off
            ZWrite Off // Add this
            LOD 200

            // Enable Alpha blending here
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM
            // Enable Alpha blending here also
            #pragma surface surf SimpleLambert alphatest:_Cutoff addshadow fullforwardshadows alpha:blend
            #pragma target 3.0

            sampler2D _MainTex;
            float4 _MainTex_TexelSize; // Add this
            fixed4 _MainCol;

            // include this
            fixed4 RetroAA(sampler2D tex, float2 uv, float4 texelSize)
            {
                float2 texelCoord = uv * texelSize.zw;
                float2 hfw = 0.5*fwidth(texelCoord);
                float2 fl = floor(texelCoord - 0.5) + 0.5;
                float2 uvaa = (fl + smoothstep(0.5 - hfw, 0.5 + hfw, texelCoord - fl))*texelSize.xy;
                return tex2D(tex, uvaa);
            }

            half4 LightingSimpleLambert(SurfaceOutput s, half3 lightDir, half atten)
            {
                half4 c;

                // Fix the lambert lighting implementation here 
                half NdotL = dot(s.Normal, lightDir);

                // We set the surface rgba in surf, so don't need to do it again here.
                c.rgb = s.Albedo * (NdotL * atten) * _LightColor0.rgb;
                c.a = s.Alpha;
                return c;
            }

            struct Input {
                float2 uv_MainTex;
                float4 color: Color; // Add this to use SpriteRenderer color
            };

            void surf(Input IN, inout SurfaceOutput o) {
                // replace this line: 
                // fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _MainCol;

                // with this
                fixed4 c = RetroAA(_MainTex, IN.uv_MainTex, _MainTex_TexelSize);

                // factor in MainCol and SpriteRenderer color/tints
                o.Albedo = c.rgb * _MainCol.rgb * IN.color.rgb;
                o.Alpha = c.a * _MainCol.a * IN.color.a;
            }
            ENDCG
        }

            Fallback "Transparent/Cutout/VertexLit"
}

You might need to turn down the Alpha cutoff to zero or some other low number in order to make the AA work nicely.



来源:https://stackoverflow.com/questions/53752402/combining-two-shaders-into-one-shader

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!