Unity Shader 用纹理变形模拟流动的水面

时间:2023-02-27   阅读次数:

根据案例教学过了一遍,把源码贴上来。

大致分:UV动画、无缝循环、动画调整、纹理化等4个步骤。

纹理模拟波动水面最终效果图

最终效果的源码如下:

Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        [NoScaleOffset] _FlowMap("Flow (RG,A noise)",2D)="black"{}
        // [NoScaleOffset] _NormalMap("Normals",2D)="bump"{}
        [NoScaleOffset] _DerivHeightMap("Deriv (AG) Height (B)",2D)="black"{}
        _UJump("U jump per phase",Range(-0.25,0.25))=0.25
        _VJump("V jump per phase",Range(-0.25,0.25))=0.25
        _Tiling("Tiling",float)=1
        _Speed("Speed",float)=1
        _FlowStrength("Flow Strength",float)=1
        _FlowOffset("Flow Offset",float)=0
        _HeightScale ("Height Scale, Constant", Float) = 0.25
		_HeightScaleModulated ("Height Scale, Modulated", Float) = 0.75
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0

        sampler2D _MainTex,_FlowMap,_DerivHeightMap;
        float _UJump,_VJump,_Tiling,_Speed,_FlowStrength,_FlowOffset;
        float _HeightScale,_HeightScaleModulated;
        // #if !defined(FLOW INCLUDED)
        #define FLOW_INCLUDED
        float3 UnpackDerivativeHeight(float4 textureData){
            float3 dh=textureData.agb;
            dh.xy=dh.xy*2 -1;
            return dh;
        }
        float3 FlowUVW(float2 uv,float2 flowVector,float2 jump,
            float flowOffset,float tiling,float _Speed, float time,bool flowB){
            float phaseOffset=flowB ? 0.5 :0;
            float progress=frac(time+phaseOffset);
            float3 uvw;
            // uvw.xy=uv- flowVector*progress+phaseOffset;
            uvw.xy=uv-flowVector*(progress+flowOffset);
            uvw.xy*=tiling;
            uvw.xy+=phaseOffset;
            uvw.xy+=(time-progress)*jump;
            uvw.z=1-abs(1-2*progress);
            return uvw;
        }
        // #endif
        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            //波动
            // float2 flowVector=tex2D(_FlowMap,IN.uv_MainTex).rg*2 -1;
            // flowVector*=_FlowStrength;
            //替换上面两行流量加速度
            float3 flow=tex2D(_FlowMap,IN.uv_MainTex).rgb;
            flow.xy=flow.xy*2 -1;
            flow *=_FlowStrength;

            float noise=tex2D(_FlowMap,IN.uv_MainTex).a;
            float time=_Time.y*_Speed+noise;
            float2 jump=float2(_UJump,_VJump);
            float3 uvwA=FlowUVW(IN.uv_MainTex,flow.xy,jump,_FlowOffset,_Tiling,_Speed,time,true);
            float3 uvwB=FlowUVW(IN.uv_MainTex,flow.xy,jump,_FlowOffset,_Tiling,_Speed,time,false);
            //法线
            // float3 normalA=UnpackNormal(tex2D(_NormalMap,uvwA.xy))*uvwA.z;
            // float3 normalB=UnpackNormal(tex2D(_NormalMap,uvwB.xy))*uvwB.z;
            // o.Normal=normalize(normalA+normalB);
            //上面三行修改为使用导数贴图代替法线贴图
            //生成的表面法线看起来与使用法线贴图时几乎相同,只是计算成本更低
            float finalHeightScale =length(flow.xy) * _HeightScaleModulated + _HeightScale;
            float3 dhA=UnpackDerivativeHeight(tex2D(_DerivHeightMap,uvwA.xy))*(uvwA.z*finalHeightScale);
            float3 dhB=UnpackDerivativeHeight(tex2D(_DerivHeightMap,uvwB.xy))*(uvwB.z*finalHeightScale);
            o.Normal=normalize(float3(-(dhA.xy+dhB.xy),1));

            fixed4 texA = tex2D (_MainTex, uvwA.xy)*uvwA.z;
            fixed4 texB = tex2D (_MainTex, uvwB.xy)*uvwB.z;
            float4 c=(texA+texB)*_Color;
            o.Albedo = c.rgb;
            o.Albedo=pow(dhA.z+dhB.z,3);    //可注释掉,显示为自定义颜色
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
其它文章