rainyeve
  • 首页
  • 编程
  • 涂鸦
  • 其他
  • 关于
2021年8月30日
编程

【UNITY SHADER】简单模拟海面

【UNITY SHADER】简单模拟海面
2021年8月30日
编程
  • 网格顶点没有很密集,不涉及tessellation函数,对移动端友好。在网上找到的案例大多都是在standard surface shader或者pbr shader的基础上着色 (比如Harry Alisavakis的Water Shader),对移动端不友好,而且pbr有点黑盒子,想做自定义修改比较不方便。于是我用的是简单的高光公式来上色,主要是用来模拟液体的反光,似乎够用
  • 顶点动画 用了3个Gerstner波,参考自教程catlike coding Waves
  • 简单地根据顶点高度上色,模仿次表面散射
  • 根据视角和法线夹角做简单的高光计算
  • 用“湍流”噪声对法线扰动,使表面光斑更碎
Shader "Test/Ocean" {
Properties {
		[Header(Color)]
	        _SurfaceColor ("PeakColor", Color) = (1,1,1,1)
	        _WaterColor ("ValleyColor", Color) = (1,1,1,1)
		_AlphaSmooth ("AlphaSmooth", vector) = (0, 1, 1, 1)
		_HeightSmooth ("HeightSmooth", vector) = (-1, 1, 1, 0)

		[Header(Specular)]
		_Glossy ("Glossy", float) = 0.35
		_SpecPower("Specularity Power", Range(0,1)) = 1
		_SunColor ("SunColor", Color) = (1,1,0.901,1)
		_SunDir ("SunDirection", Vector) = (0, 0, 0, 0)

               [Header(Wave)]
               _WaveA ("Wave A (dir, steepness, wavelength)", Vector) = (1,0,0.5,10)
               _WaveB ("Wave B", Vector) = (0,1,0.25,20)
               _WaveC ("Wave C", Vector) = (1,1,0.15,10)
               _Speed("Speed", float) = 1

		[Header(Bump)]
		_Bump ("Bump (RGB)", 2D) = "bump" {}
		_BumpScale ("BumpScale", Range(0.01,8)) = 0.3
		_TurbulenceTex ("Turbulence Tex", 2D) = "white" {}
		_DistortPower  ("Distort Power", float) = 0
                _PowerX  ("Power X", range (0,1)) = 0
		_PowerY  ("Power Y", range (0,1)) = 0

}

SubShader {
	Tags { "RenderType" = "Opaque" "Queue"="Geometry"}
		
        Blend SrcAlpha OneMinusSrcAlpha
	ZWrite Off

    	Pass {
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
                #pragma multi_compile _ TRANSPARENT

		#include "UnityCG.cginc"

		struct v2f {
    			float4 pos : SV_POSITION;
    			float2  uv : TEXCOORD0;
    			float3  normal : TEXCOORD1;
			half4 grabPos : TEXCOORD2;
			float3 worldPos : TEXCOORD3;
			float height : TEXCOORD4;
			float2 uvnoise : TEXCOORD5;
		};

		half4 _SunDir;

                float4 _WaveA;
                float4 _WaveB;
                float4 _WaveC;
                float _Speed;

	        float4 _HeightSmooth;

		fixed _PowerX;
		fixed _PowerY;
		fixed _DistortPower;
		sampler2D _TurbulenceTex;
		half4 _TurbulenceTex_ST;

            float3 GerstnerWave (float4 wave, float3 p, inout float3 tangent, inout float3 binormal) {
                float steepness = wave.z;
                float wavelength = wave.w;
                float k = 2 * 3.141593653 / wavelength;
                float c = _Speed;
                float2 d = normalize(wave.xy);
                float f = k * (dot(d, p.xz) - c * _Time.y);
                float a = steepness / k;

                tangent += float3(
                    -d.x * d.x * (steepness * sin(f)),
                    d.x * (steepness * cos(f)),
                    -d.x * d.y * (steepness * sin(f))
                );
                binormal += float3(
                    -d.x * d.y * (steepness * sin(f)),
                    d.y * (steepness * cos(f)),
                    -d.y * d.y * (steepness * sin(f))
                );
                return float3(
                    d.x * (a * cos(f)),
                    a * sin(f),
                    d.y * (a * cos(f))
                );
            }

	    v2f vert (appdata_full v) {
    		v2f o;

                float3 gridPoint = v.vertex.xyz;
                float3 tangent = float3(1, 0, 0);
                float3 binormal = float3(0, 0, 1);

                float3 p = gridPoint;
                p += GerstnerWave(_WaveA, gridPoint, tangent, binormal);
                p += GerstnerWave(_WaveB, gridPoint, tangent, binormal);
                p += GerstnerWave(_WaveC, gridPoint, tangent, binormal);
		float3 normal = normalize(cross(binormal, tangent));

		o.height = p.y - v.vertex.y;

                v.vertex.xyz = p;

                o.pos = UnityObjectToClipPos(v.vertex);
		o.normal = UnityObjectToWorldNormal(normal);

		o.uv = v.texcoord.xy;
		o.uvnoise = TRANSFORM_TEX(v.texcoord.xy, _TurbulenceTex);

		o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

                return o;
		}

		sampler2D _Bump;
		half4 _SurfaceColor;
		half4 _WaterColor;
		half _BumpScale;
		half _SpecPower;
		half4 _SunColor;
		float _Glossy;

	    half4 frag (v2f i) : COLOR {	
		float3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
		float3 lightDir = normalize(_SunDir);
		float3 normal = i.normal;
		float2 originUV = i.uv;

		fixed4 offsetColor1 = tex2D(_TurbulenceTex, i.uvnoise + fmod(_Time.xz*_DistortPower,1));
		fixed4 offsetColor2 = tex2D(_TurbulenceTex, i.uvnoise + fmod(_Time.yx*_DistortPower,1));
		i.uv.x += ((offsetColor1.r + offsetColor2.r) - 1) * _PowerX;
		i.uv.y += ((offsetColor1.r + offsetColor2.r) - 1) * _PowerY;

		normal += tex2D(_Bump, i.uv) * _BumpScale;

		half4 col = lerp(_WaterColor, _SurfaceColor, smoothstep(_HeightSmooth.x, _HeightSmooth.y, i.height) * _HeightSmooth.z);

		float3 halfdir = normalize(lightDir + viewDir);

		float ndh = max(0, dot(normal, halfdir));

		col.rgb += _SunColor.rgb * pow(ndh, _SpecPower*128.0) * _Glossy; 

    	        return col;
	}

	ENDCG
	}
    }
		   
}

Post Views: 2,086

shader unity

上一篇【自定义Post Processing Volume】径向模糊(Radial Blur)下一篇 【Unity Animation Rigging】自定义Damp Transform模拟头发衣服晃动

发表评论 取消回复

邮箱地址不会被公开。 必填项已用*标注

分类目录

  • 其他 (2)
  • 旅行 (1)
  • 涂鸦 (6)
  • 编程 (28)
Email: wuch441692@163.com