[URP]交互水Shader(未完ing)

环境

下面代码的运行环境

  • Unity : 2022.3.3f1
  • Pipeline : URP

美术思路:获取屏幕中得一张RT图,传给Shader生成高度图,至于水的效果就按照正常流程去写,顶点起伏+水面反射(海水的话得加湍流)+ 泡沫 + 水边缘处理;目前水Shader还没写完后面有空再接着写;

代码如下,有注释(参考了很多文章,后面再优化效果和代码):

Shader "Ripples/Add" {
    Properties {
        
    }
    SubShader {
        Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalRenderPipeline" }

        HLSLINCLUDE
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        ENDHLSL

        Pass {
            Name "Add"
            Tags { "LightMode"="UniversalForward" }

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            struct a2v {
                float4 positionOS   : POSITION;
                float2 uv           : TEXCOORD0;
            };

            struct v2f {
                float4 positionCS  : SV_POSITION;
                float2 uv           : TEXCOORD0;
            };


			TEXTURE2D(_InteractiveTex);
			SAMPLER(sampler_InteractiveTex);

			TEXTURE2D(_CurrentRT);
            SAMPLER(sampler_CurrentRT);

			float _isRenderMousePointer;
			float4 _PositionPoint;

            v2f vert(a2v v) {
                v2f o;

                o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
                o.uv = v.uv;
                return o;
            }

            half4 frag(v2f i) : SV_Target {

				float c =  SAMPLE_TEXTURE2D(_InteractiveTex, sampler_InteractiveTex, i.uv).r + //交互相机RT
				SAMPLE_TEXTURE2D(_CurrentRT, sampler_CurrentRT,i.uv).r +  //上一帧RT
				max(_PositionPoint.z - length(i.uv - _PositionPoint.xy)/_PositionPoint.z,0) * _isRenderMousePointer; //鼠标交互
				//float c = SAMPLE_TEXTURE2D(_CurrentRT, sampler_CurrentRT,i.uv).r +  //上一帧RT
				//		  max(_PositionPoint.z - length(i.uv - _PositionPoint.xy)/_PositionPoint.z,0) * _isRenderMousePointer; //鼠标交互
				return c;
				
				//return length(i.uv - _PositionPoint.xy);
				//return max(_PositionPoint.z - length(i.uv - _PositionPoint.xy),0);

				//return max(_PositionPoint.z - length(i.uv - _PositionPoint.xy)/_PositionPoint.z,0);
				//return  SAMPLE_TEXTURE2D(_CurrentRT, sampler_CurrentRT,i.uv).r + max(_PositionPoint.z - length(i.uv - _PositionPoint.xy)/_PositionPoint.z,0);
            }
            ENDHLSL
        }

    }
}

Shader "Ripples/RippleShader"
{
     Properties {
		_Attenuation("Attenuation" , Range(0,1)) = 0.99
    }
    SubShader {
        Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalRenderPipeline" }

        HLSLINCLUDE
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

  //      CBUFFER_START(UnityPerMaterial)
		//float _Attenuation;
  //      CBUFFER_END
        ENDHLSL

        Pass {
            Name "Ripple"
            Tags { "LightMode"="UniversalForward" }

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            struct a2v {
                float4 positionOS   : POSITION;
                float2 uv           : TEXCOORD0;
            };

            struct v2f {
                float4 positionCS  : SV_POSITION;
                float2 uv           : TEXCOORD0;
            };

			TEXTURE2D(_PrevRT);
            SAMPLER(sampler_PrevRT);

			TEXTURE2D(_CurrentRT);
            SAMPLER(sampler_CurrentRT);

			float4 _CurrentRT_TexelSize;
			float _Attenuation;

            v2f vert(a2v v) {
                v2f o;
                o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
                o.uv = v.uv;
                return o;
            }

            half4 frag(v2f i) : SV_Target {

				//最小偏移单位
				float3 e = float3(_CurrentRT_TexelSize.xy,0);
				float2 uv =i.uv;
				//获取上下左右四个值
				float p10 = SAMPLE_TEXTURE2D(_CurrentRT, sampler_CurrentRT, uv - e.zy).x;//下
				float p01 = SAMPLE_TEXTURE2D(_CurrentRT, sampler_CurrentRT, uv - e.xz).x;//左
				float p21 = SAMPLE_TEXTURE2D(_CurrentRT, sampler_CurrentRT, uv + e.xz).x;//右
				float p12 = SAMPLE_TEXTURE2D(_CurrentRT, sampler_CurrentRT, uv + e.zy).x;//上
				//中心值
				float p11 =  SAMPLE_TEXTURE2D(_PrevRT, sampler_PrevRT, uv).x;
				//计算结果
				float d = (p10 + p01 + p21 + p12) / 2 - p11;
				//衰减
				d *= _Attenuation;

				return d;
            }
            ENDHLSL
        }
    }
}
Shader "water0829"
{
    Properties
    {   
        _SourceTexture("涟漪高度图", 2D) = "white" {}
        _sampleDelta("高度偏移",range(0,1)) = 0.5
        _FresnelPower("水面菲涅尔", Range(0.1,50)) = 5
        _Amount("折射强度",float)=100 

        [Header(Turbulence)]
        [Normal]_NormalMap("水面法线扰动",2D) = "bump"{}
        _NormalIntensity("扰动强度",Range(0,5)) = 1
        _NormalScale("扰动纹理缩放",Range(0,5)) = 1
        _Offset("扰动纹理偏移",Range(-1,1)) = 0
        _WaveXSpeed("扰动速度(X轴)",Range(0,1)) = 0.5
        _WaveYSpeed("扰动速度(Y轴)",Range(0,1)) = 0.5
        _NormalRefract("扰动折射",Range(0,1)) = 0.5

        [NoScaleOffset]_CubeMap ("环境", CUBE) = "white" {}
        [Header(WaterCol)]
        [KeywordEnum(Col,RampTex)] DepthCol("水颜色模式(2选1)",Float) = 1
        _DepthMaxDistance("水深度", Float) = 1
        [Header(DepthCol)]
        _DepthGradientShallow("浅水颜色", Color) = (0.325, 0.807, 0.971, 0.725)
        _DepthGradientDeep("深水颜色", Color) = (0.086, 0.407, 1, 0.749)
        [Header(DepthRampTex)]
        _rampTex("水着色图",2D) = "white" {}

        [Header(WavShape)]
        _WavSpeed("波浪速率",Range(0,1))=1
        _WavwA("波浪 A: directionX, directionZ, _Steepness, _Wavelength", Vector) = (1, 1, 0.8, 3.0)
        _WavwB("波浪 B: directionX, directionZ, _Steepness, _Wavelength", Vector) = (1, 1, 0.8, 3.0)
        _WavwC("波浪 C: directionX, directionZ, _Steepness, _Wavelength", Vector) = (1, 1, 0.8, 3.0)

        _ShadowMainColor("阴影颜色", color) = (0,0,0,1)

    }
 
    SubShader
    {
        Tags { "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True" "RenderPipeline" = "UniversalPipeline" }
        LOD 100
        Blend SrcAlpha OneMinusSrcAlpha
        Pass
        {   Tags{ "LightMode"="UniversalForward" }
            Name "Unlit"
            HLSLPROGRAM
            // Required to compile gles 2.0 with standard srp library
            #pragma prefer_hlslcc gles
            #pragma exclude_renderers d3d11_9x
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            //自定义
            #pragma multi_compile DEPTHCOL_COL DEPTHCOL_RAMPTEX
            // URP 软阴影
            #pragma multi_compile_fragment _ _SHADOWS_SOFT
            // URP 主光阴影、联机阴影、屏幕空间阴影//
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN

            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl"

            #include "WaterMath.hlsl"
            
 
            struct Attributes
            {
                float4 positionOS       : POSITION;
                float2 uv               : TEXCOORD0;
                float4 tangentOS        : TANGENT;
                float3 normalOS         : NORMAL;
            };
 
            struct Varyings
            {
                float4 positionHCS      : SV_POSITION;
                float2 uv               : TEXCOORD0;
                float  fogCoord         : TEXCOORD1;
                float4 screenPosition   : TEXCOORD2;
                float3 positionWS       : TEXCOORD3;
                float3 normalWS         : TEXCOORD4;
                float4 tangentWS        : TANGENT;
            };
 
            CBUFFER_START(UnityPerMaterial)
            float4 _SourceTexture_TexelSize; float _sampleDelta;
            float _WavSpeed,_NormalIntensity,_NormalScale,_Offset,_WaveXSpeed,_WaveYSpeed,_NormalRefract;
            float4 _WavwA,_WavwB,_WavwC;

            float4 _DepthGradientShallow,_DepthGradientDeep,_ShadowMainColor;            float _DepthMaxDistance,_FresnelPower,_CubemapMip;
            float  _Amount;
            CBUFFER_END
            TEXTURE2D (_rampTex);           SAMPLER(sampler_rampTex);
            TEXTURE2D (_SourceTexture);     SAMPLER(sampler_SourceTexture);
            TEXTURECUBE(_CubeMap);          SAMPLER(sampler_CubeMap);
            TEXTURE2D(_NormalMap);          SAMPLER(sampler_NormalMap);
            SAMPLER(_CameraColorTexture);   float4 _CameraColorTexture_TexelSize;       //该向量是非本shader独有,不能放在常量缓冲区
            
 
            Varyings vert(Attributes v)
            {
                Varyings o = (Varyings)0;
                //多波叠加
                float3 tangent = float3(0.0, 0.0, 0.0);
                float3 bitangent = float3(0.0, 0.0, 0.0);
                v.positionOS.xyz += gerstner(_WavwA, v.positionOS, tangent, bitangent, _WavSpeed);             //_WavwB,_WavwC
                v.positionOS.xyz += gerstner(_WavwB, v.positionOS, tangent, bitangent, _WavSpeed); 
                v.positionOS.xyz += gerstner(_WavwC, v.positionOS, tangent, bitangent, _WavSpeed);
                o.normalWS = normalize(cross(bitangent, tangent)); 

                VertexPositionInputs positionInputs = GetVertexPositionInputs(v.positionOS.xyz); 
                o.positionWS = positionInputs.positionWS; 
                o.positionHCS = positionInputs.positionCS; 
                o.screenPosition = ComputeScreenPos(o.positionHCS);

                VertexNormalInputs normalInputs = GetVertexNormalInputs(v.normalOS, v.tangentOS);    //计算世界空间中的法线和切线
                o.tangentWS = half4(normalInputs.tangentWS, v.tangentOS.w * GetOddNegativeScale());      //世界空间的切线

                o.uv = v.uv;
                o.fogCoord = ComputeFogFactor(o.positionHCS.z);
 
                return o;
            }
 
            half4 frag(Varyings i) : SV_Target
            {
                //阴影
				float4 SHADOW_COORDS = TransformWorldToShadowCoord(i.positionWS.xyz);
                Light  lightDirectional     = GetMainLight(SHADOW_COORDS);
                half   shadow        = lightDirectional.shadowAttenuation;

                //高度图
                float2 Hdelta = float2(_SourceTexture_TexelSize.x*0.5, 0);
                float  u1     = SAMPLE_TEXTURE2D(_SourceTexture, sampler_SourceTexture, i.uv - Hdelta).r;
                float  u2     = SAMPLE_TEXTURE2D(_SourceTexture, sampler_SourceTexture, i.uv + Hdelta).r;
                float3 du     = float3(_sampleDelta, (u2 - u1), 0);

                float2 Vdelta = float2(0, _SourceTexture_TexelSize.y * 0.5);
                float  v1     = SAMPLE_TEXTURE2D(_SourceTexture, sampler_SourceTexture, i.uv - Vdelta).r;
                float  v2     = SAMPLE_TEXTURE2D(_SourceTexture, sampler_SourceTexture, i.uv + Vdelta).r;
                float3 dv     = float3(0, (v2 - v1), _sampleDelta);
                float3 waterNormal = cross(dv, du);

                //向量准备
                half3 L = normalize(lightDirectional.direction);
                half3 V = normalize(_WorldSpaceCameraPos.xyz - i.positionWS.xyz);
                half3 N01 = waterNormal;  
                half3 N02 = i.normalWS;
                half3 blendedNormal = lerp(N01, N02, 0.5);

                //---------//uv偏移
                        float4 offsetColor = (SAMPLE_TEXTURE2D(_NormalMap,sampler_NormalMap, i.uv
                                                    + float2(_WaveXSpeed * _Time.x, 0))
                                                    + SAMPLE_TEXTURE2D(_NormalMap,sampler_NormalMap, float2(i.uv.y, i.uv.x)
                                                    + float2(_WaveYSpeed * _Time.x, 0))) / 2;
                        half2 offset = UnpackNormal(offsetColor).xy * _NormalRefract; //法线偏移程度可控之后offset被用于这里

                        //切线转世界
                        half3 normalTS1 = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap,sampler_NormalMap,i.uv*_NormalScale+offset));    //对法线纹理采样(切线)
                        half3 normalTS2 = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap,sampler_NormalMap,i.uv*_NormalScale-offset));    //对法线纹理采样(切线)
                        half3 normalTS3 = normalize(normalTS1+normalTS2);
                        normalTS3.xy *= _NormalIntensity;
                        normalTS3.z = sqrt(1 - saturate(dot(normalTS3.xy, normalTS3.xy)));
                        half3 binormalWS = cross(blendedNormal, normalTS3.xyz) * i.tangentWS.w;                          //世界空间下的副切线 
                        half3 NormalWS = normalize(mul(normalTS3,half3x3(i.tangentWS.xyz,binormalWS,blendedNormal)));       //将切线空间中的法线转换到世界空间中
                
                //blendedNormal = lerp(blendedNormal, NormalWS, 0.5);
                half3 vrDirWS = reflect(-V, NormalWS);       // 反射

                //折射
                float2 SS_texcoord = i.positionHCS.xy/_ScreenParams.xy;//获取屏幕UV
                float2 SS_bias=normalTS3.xy*_Amount*_CameraColorTexture_TexelSize;//如果取的是切线空间的法线则执行它计算偏移,但是切线空间的法线不随着模型的旋转而变换;
                half3 refract = tex2D(_CameraColorTexture, SS_texcoord+SS_bias).rgb;
                

                //计算结果
                half  NdotL   = max(dot(blendedNormal, L),1e-5);
                half3 SampleCubeMap = SAMPLE_TEXTURECUBE_LOD(_CubeMap, sampler_CubeMap, vrDirWS,_CubemapMip).rgb;
                half  fresnel =  pow((1- (dot(blendedNormal,V))),_FresnelPower);
                half3 ref = lerp(refract,SampleCubeMap, fresnel)+pow(fresnel,100);

                //水的颜色
                float2 screenPos= i.screenPosition.xy / i.screenPosition .w;
                float depth = LinearEyeDepth(SampleSceneDepth(screenPos), _ZBufferParams);
                float depthDifference = depth - i.screenPosition.w;
                depthDifference = saturate(depthDifference / _DepthMaxDistance);
                //两个方法
                #if DEPTHCOL_COL
                float4 waterColor = lerp(_DepthGradientShallow, _DepthGradientDeep, depthDifference);
                //waterColor.a*= depthDifference;
                #elif DEPTHCOL_RAMPTEX
                depthDifference = clamp(0,0.99,depthDifference);
                float3 DepthColor = SAMPLE_TEXTURE2D(_rampTex,sampler_rampTex,(depthDifference + 0.2)*4/5);
                float  alpha = (0,1,depthDifference);
                float4 waterColor = float4(DepthColor,alpha);
                waterColor  = float4(waterColor.rgb,alpha);
                #endif


                shadow = shadow*depthDifference;                     //阴影矫正边缘过硬
                waterColor.rgb = MixFog(waterColor.rgb, i.fogCoord);
                waterColor.rgb = lerp(_ShadowMainColor.rgb * waterColor.rgb, waterColor.rgb, shadow);
                waterColor.rgb += ref;

                half4 Debug = float4(vrDirWS,1);

                return waterColor;
            }
            ENDHLSL
        }
    }
}

水还没写完,后面有空再写,后面有空再写~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃斋的和尚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值