合并2个着色器

时间:2018-01-10 03:21:18

标签: unity3d shader

我目前正在使用2017.3.0f.3。我有两个CG着色器,我想合并到一个着色器中。一个用于处理精灵的失真(如波浪/风),另一个用于使其面向摄像机(广告牌)。他们独立工作,但我需要他们一起工作。

着色器1:

Shader "Cg  shader for billboards" {
   Properties {
      _MainTex ("Texture Image", 2D) = "white" {}
      _ScaleX ("Scale X", Float) = 1.0
      _ScaleY ("Scale Y", Float) = 1.0
   }
   SubShader {
      Pass {   
         CGPROGRAM

         #pragma vertex vert  
         #pragma fragment frag

         // User-specified uniforms            
         uniform sampler2D _MainTex;        
         uniform float _ScaleX;
         uniform float _ScaleY;

         struct vertexInput {
            float4 vertex : POSITION;
            float4 tex : TEXCOORD0;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float4 tex : TEXCOORD0;
         };

         vertexOutput vert(vertexInput input) 
         {
            vertexOutput output;

            output.pos = mul(UNITY_MATRIX_P, 
              mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
              + float4(input.vertex.x, input.vertex.y, 0.0, 0.0)
              * float4(_ScaleX, _ScaleY, 1.0, 1.0));

            output.tex = input.tex;

            return output;
         }

         float4 frag(vertexOutput input) : COLOR
         {
            return tex2D(_MainTex, float2(input.tex.xy));   
         }

         ENDCG
      }
   }
}

着色器2:

Shader "Transparent/Cutout/Diffuse Shake" {

    Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
        _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
        _ShakeDisplacement ("Displacement", Range (0, 1.0)) = 1.0
        _ShakeTime ("Shake Time", Range (0, 1.0)) = 1.0
        _ShakeWindspeed ("Shake Windspeed", Range (0, 1.0)) = 1.0
        _ShakeBending ("Shake Bending", Range (0, 1.0)) = 1.0
    }

    SubShader {
        Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
        LOD 200

    CGPROGRAM
    #pragma target 3.0
    #pragma surface surf Lambert alphatest:_Cutoff vertex:vert addshadow

    sampler2D _MainTex;
    fixed4 _Color;
    float _ShakeDisplacement;
    float _ShakeTime;
    float _ShakeWindspeed;
    float _ShakeBending;

    struct Input {
        float2 uv_MainTex;
    };

    void FastSinCos (float4 val, out float4 s, out float4 c) {
        val = val * 6.408849 - 3.1415927;
        float4 r5 = val * val;
        float4 r6 = r5 * r5;
        float4 r7 = r6 * r5;
        float4 r8 = r6 * r5;
        float4 r1 = r5 * val;
        float4 r2 = r1 * r5;
        float4 r3 = r2 * r5;
        float4 sin7 = {1, -0.16161616, 0.0083333, -0.00019841} ;
        float4 cos8  = {-0.5, 0.041666666, -0.0013888889, 0.000024801587} ;
        s =  val + r1 * sin7.y + r2 * sin7.z + r3 * sin7.w;
        c = 1 + r5 * cos8.x + r6 * cos8.y + r7 * cos8.z + r8 * cos8.w;
    }


    void vert (inout appdata_full v) {

        float factor = (1 - _ShakeDisplacement -  v.color.r) * 0.5;

        const float _WindSpeed  = (_ShakeWindspeed  +  v.color.g );    
        const float _WaveScale = _ShakeDisplacement;

        const float4 _waveXSize = float4(0.048, 0.06, 0.24, 0.096);
        const float4 _waveZSize = float4 (0.024, .08, 0.08, 0.2);
        const float4 waveSpeed = float4 (1.2, 2, 1.6, 4.8);

        float4 _waveXmove = float4(0.024, 0.04, -0.12, 0.096);
        float4 _waveZmove = float4 (0.006, .02, -0.02, 0.1);

        float4 waves;
        waves = v.vertex.x * _waveXSize;
        waves += v.vertex.z * _waveZSize;

        waves += _Time.x * (1 - _ShakeTime * 2 - v.color.b ) * waveSpeed *_WindSpeed;

        float4 s, c;
        waves = frac (waves);
        FastSinCos (waves, s,c);

        float waveAmount = v.texcoord.y * (v.color.a + _ShakeBending);
        s *= waveAmount;

        s *= normalize (waveSpeed);

        s = s * s;
        float fade = dot (s, 1.3);
        s = s * s;
        float3 waveMove = float3 (0,0,0);
        waveMove.x = dot (s, _waveXmove);
        waveMove.z = dot (s, _waveZmove);
        v.vertex.xz -= mul ((float3x3)_World2Object, waveMove).xz;

    }

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

    Fallback "Transparent/Cutout/VertexLit"
}

我已经尝试了多次失败。有可能吗?

1 个答案:

答案 0 :(得分:0)

这是可能的,并且有多种方法可以去:

最简单的方法是根本不使用广告牌着色器,只需使用c#脚本定向变换以查看相机。如果您不关注效率,这是最好的解决方案。

另一种解决方案是将波函数合并到广告牌1的顶点着色器中。您只需要在广告牌转换之前应用波形失真:

input.vertex.xz -= mul ((float3x3)_World2Object, waveMove).xz;
output.pos = mul(UNITY_MATRIX_P, 
          mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
          + float4(input.vertex.x, input.vertex.y, 0.0, 0.0)
          * float4(_ScaleX, _ScaleY, 1.0, 1.0));

(你需要移动与waveMove相关的所有内容:))

如果您需要照明工作(使用表面着色器的好处),那么它会变得更加棘手。在执行主顶点着色器方法后,曲面着色器将转换为场景后面的剪辑/屏幕空间。由于广告牌转换需要分解转换事情变得混乱:您需要将顶点转换为最终的剪辑空间位置,然后将其转换回对象空间,以便可以在场景后面再次将其重新转换为所需位置。