Boat Attack使用了Universal RP的许多新图形功能,可以用于探索 Universal RP 的使用方式和技巧。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

357 行
15 KiB

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "Water_Old"
{
Properties
{
_TessellationEdgeLength ("Tessellation Edge Length", Range(5, 100)) = 50
_Color ("SeaCol", Color) = (1, 1, 1, 1)
_Color2 ("SeaCol2", Color) = (1, 1, 1, 1)
//[NoScaleOffset]
//_ColorRamp("Color Ramp", 2D) = "grey" {}
[NoScaleOffset]
_BumpMap("Detail Wave Normal", 2D) = "bump" {}
_BumpValue("Detail Wave Amount", Range(0, 1)) = 0.2//fine detail multiplier
[NoScaleOffset]
_FoamMap("Foam Texture", 2D) = "black" {}
}
SubShader
{
//normal pass
Tags {"Queue"="Transparent" "RenderPipeline" = "LightweightPipeline"}
Pass
{
LOD 100
ZWrite Off
CGPROGRAM
//tesselation stuff
#pragma hull hull
#pragma domain domain
//normal stuff
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#pragma shader_feature GERSTNER_WAVES
#pragma target 4.0
#pragma require tessellation tessHW
////////////////////INCLUDES//////////////////////
#include "UnityCG.cginc"
//Import the Gerstner Waves function
#include "GerstnerWaves.cginc"
////////////////////STRUCTS///////////////////////
//vert struct
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;//TODO - May not need later
float4 uv2 : TEXCOORD1;//lightmap
};
//passing struct
struct midStruct
{
float4 vertex : POS;
float2 uv :TEXCOORD0;
float4 uv2 : TEXCOORD1;//lightmap
};
//tess CP
struct tessCP
{
float4 vertex : INTERNALTESSPOS;
float2 uv : TEXCOORD0;
float4 uv2 : TEXCOORD1;//lightmap
};
//frag struct
struct v2f
{
float4 uvs : TEXCOORD0;//Geometric UVs stored in xy, and world(pre-waves) in zw
float2 uv2 : TEXCOORD1;//lightmapUVs
float4 worldPos : TEXCOORD4;//world position of the vertices
float4 screenPos : TEXCOORD2;//screen position of the verticies after wave distortion
float2 screenPosPreVert : TEXCOORD3;//screen position of the verticies before wave distortion
half4 normal : NORMAL;//vert normals(not used right now)
fixed4 diff : COLOR0; // diffuse lighting color
fixed3 spec : TEXCOORD5;//for spec data
UNITY_FOG_COORDS(6)
float4 vertex : SV_POSITION;
};
//Hull Constant struct
struct HS_ConstantOutput
{
float TessFactor[3] : SV_TessFactor;
float InsideTessFactor : SV_InsideTessFactor;
};
//////////////////New variables final//////////////////
//Gerstner Wave variables
//uniform int _WaveCount;//how many waves, set via the water component
//uniform float4 _WaveData[10];//the data for the waves, x=amplitude, y=direction, z=wavelength, w=omniDir set via the water component
//uniform float4 _WaveData2[10];//more data, x=omnidirX, y=omnidirZ
//Screen-based textures/samplers
Texture2D _WaterDisplacementTexture;//screen-based displacement pass
Texture2D _PlanarReflectionTexture;//screen-based planar reflection
SamplerState sampler_PlanarReflectionTexture_repeat_bilinear;//screen-based sampler, clamped for no repetition/edge issues
//Tiling textures/samplers
Texture2D _BumpMap;//Detailed normalmap for high frequence details
sampler2D _FoamMap;//Foam map for crest whitecaps, etc..
sampler2D _WaterDepthMap;//The captured depth map under the water
sampler2D _CameraDepthTexture;//depth texture
sampler2D _AbsorptionScatteringRamp;
SamplerState sampler_BumpMap;//Tiling sampler, has repeat wrap mode
//Color lookups - TODO - should be a gradient lut
float4 _Color;
float4 _Color2;
float _MaxDepth;
float _MaxWaveHeight;
half _BumpValue;
/////////////////Utility Functions////////////////// - TODO - Moved to separate CGinc file
float Remap(half value, half4 remap)//remaps a value based on a in:min/max and out:min/max
{
return remap.z + (value - remap.x) * (remap.w - remap.z) / (remap.y - remap.x);
}
float3 HeightToNormal(Texture2D _tex, SamplerState _sampler, float2 uv, half intensity)//converts height to normal
{
float3 bumpSamples;
bumpSamples.x = _tex.Sample(_sampler, uv).x; // Sample center
bumpSamples.y = _tex.Sample(_sampler, float2(uv.x + intensity / _ScreenParams.x, uv.y)).x; // Sample U
bumpSamples.z = _tex.Sample(_sampler, float2(uv.x, uv.y + intensity / _ScreenParams.y)).x; // Sample V
half dHdU = bumpSamples.z - bumpSamples.x;//bump U offset
half dHdV = bumpSamples.y - bumpSamples.x;//bump V offset
return float3(-dHdU, dHdV, 0.5);//return tangent normal
}
////////////////////////Tesselation shader///////////////////////////
half _TessellationEdgeLength;
float TessellationEdgeFactor (float3 p0, float3 p1)
{
float edgeLength = distance(p0, p1);
float3 edgeCenter = (p0 + p1) * 0.5;
float viewDistance = distance(edgeCenter, _WorldSpaceCameraPos);
return edgeLength * _ScreenParams.y / (_TessellationEdgeLength * viewDistance);
}
tessCP vert( appdata Input )
{
tessCP Output;
Output.vertex = Input.vertex;
Output.uv = Input.uv;
Output.uv2 = Input.uv2;
return Output;
}
HS_ConstantOutput HSConstant( InputPatch<tessCP, 3> Input )
{
float3 p0 = mul(unity_ObjectToWorld, Input[0].vertex).xyz;
float3 p1 = mul(unity_ObjectToWorld, Input[1].vertex).xyz;
float3 p2 = mul(unity_ObjectToWorld, Input[2].vertex).xyz;
HS_ConstantOutput Output = (HS_ConstantOutput)0;
Output.TessFactor[0] = TessellationEdgeFactor(p1, p2);
Output.TessFactor[1] = TessellationEdgeFactor(p2, p0);
Output.TessFactor[2] = TessellationEdgeFactor(p0, p1);
Output.InsideTessFactor = (TessellationEdgeFactor(p1, p2) +
TessellationEdgeFactor(p2, p0) +
TessellationEdgeFactor(p0, p1)) * (1 / 3.0);
return Output;
}
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[patchconstantfunc("HSConstant")]
[outputcontrolpoints(3)]
tessCP hull( InputPatch<tessCP, 3> Input, uint uCPID : SV_OutputControlPointID )
{
tessCP Output = (tessCP)0;
Output.vertex = Input[uCPID].vertex;
Output.uv = Input[uCPID].uv;
Output.uv2 = Input[uCPID].uv2;
return Output;
}
////////////////////////////VERT SHADER////////////////////////////
[domain("tri")]
v2f domain( HS_ConstantOutput HSConstantData,
const OutputPatch<tessCP, 3> Input,
float3 BarycentricCoords : SV_DomainLocation)
{
v2f Output = (v2f)0;//initialize OUT
/////////////////////Tessellation////////////////////////
//DS_Output Output = (DS_Output)0;
float fU = BarycentricCoords.x;
float fV = BarycentricCoords.y;
float fW = BarycentricCoords.z;
float4 vertex = Input[0].vertex * fU + Input[1].vertex * fV + Input[2].vertex * fW;
float2 uv = Input[0].uv * fU + Input[1].uv * fV + Input[2].uv * fW;
float4 uv2 = Input[0].uv2 * fU + Input[1].uv2 * fV + Input[2].uv2 * fW;
///////////////////////Pre-waves/////////////////////////
Output.worldPos.xyz = mul(unity_ObjectToWorld, vertex).xyz;
float4 screenPosRaw = ComputeScreenPos(UnityObjectToClipPos(vertex));
Output.screenPosPreVert.xy = screenPosRaw.xy / screenPosRaw.w;//screen uvs pre-waves
Output.uvs.xy = uv;//geometry UVs
Output.uvs.zw = Output.worldPos.xz * 0.1;//worldspace UVs
Output.uv2 = uv2.xy * unity_LightmapST.xy + unity_LightmapST.zw;;
Output.normal = float4(0, 0, 1, 0);//intialize tangent normals
///////////////////////Gerstner Waves/////////////////////
WaveStruct wave;
SampleWaves(vertex.xyz, 1, wave);
half waterDepth = tex2Dlod(_WaterDepthMap, half4(Output.uvs.xy, 0, 0)).r;
half val = 1-clamp(waterDepth, 0, 1);
vertex.xyz = wave.position.xyz;// * half3(1, val, 1);
Output.normal.xyz = wave.normal.xyz * half3(val, 1, val);//normalize the normal :D
Output.normal.w = vertex.y;//encide wave height into w component of normal
//////////////////////Post-waves//////////////////////////
//vertex.y += _WaterDisplacementTexture.SampleLevel(sampler_PlanarReflectionTexture_repeat_bilinear, float4(Output.screenPosPreVert.xy, 0, 0), 0);//added displacement pass
Output.vertex = UnityObjectToClipPos(vertex);//calculate the vertices for rendering
Output.screenPos = ComputeScreenPos(Output.vertex);//create screenUVs that ignore wave disp
Output.worldPos.xyz = mul(unity_ObjectToWorld, vertex).xyz;//recalculate the world pos
Output.worldPos.w = length(ObjSpaceViewDir(vertex));
float3 viewPos = UnityObjectToViewPos(vertex);
Output.screenPos.z = length(viewPos / viewPos.z);
////////////////////Lighting info/////////////////////////
half3 lightDirectionWS;
//LightInput mainLight;
//INITIALIZE_MAIN_LIGHT(mainLight);
//half realtimeMainLightAtten = GetMainLightDirectionAndRealtimeAttenuation(mainLight, Output.normal.xzy, Output.worldPos, lightDirectionWS);
//half NdotL = saturate(dot(Output.normal.xzy, lightDirectionWS));
Output.diff.x = 0.5;// mainLight.color * NdotL;
half3 viewDir = normalize(_WorldSpaceCameraPos.xyz - Output.worldPos);
Output.spec = 0; //normalize(lightDirectionWS + viewDir);
//float nh = max(0, dot(Output.normal.xzy, h));
//Output.diff.y = pow(nh, 128.0) * 128;
UNITY_TRANSFER_FOG(Output, Output.vertex);//Do fog
return Output;
}
////////////////////////////FRAG SHADER///////////////////////////
fixed4 frag (v2f IN) : SV_Target
{
half3 waveNormals = IN.normal.xyz; //0;
half waveHeight = IN.normal.w;
float2 reflectionUV = IN.screenPos.xy / IN.screenPos.w;//screen UVs
reflectionUV = float2(reflectionUV.x, 1-reflectionUV.y);
///////////////////////Gerstner Waves/////////////////////
// #ifdef GERSTNER_WAVES
// WaveStructOut waves[10];
// for(int i = 0; i < _WaveCount; i++)
// {
// waves[i] = GerstnerWave(IN.worldPos, _WaveCount, _WaveData[i].x, _WaveData[i].y, _WaveData[i].z);//calculate the wave
// waveNormals += waves[i].normal;//add to the normal
// waveHeight += waves[i].pos.y;
// }
// waveNormals = normalize(waveNormals);
// #endif
///////////////////////////Normals////////////////////////
//Tangent normals
half roughness = saturate(_BumpValue);
half3 bump1 = UnpackNormal(_BumpMap.Sample(sampler_BumpMap, ((IN.uvs.zw * 0.5) + frac(_Time.y * 0.01)))) * roughness;//detail01
half3 bump2 = UnpackNormal(_BumpMap.Sample(sampler_BumpMap, ((IN.uvs.zw * 2) + frac(_Time.yy * -0.05)))) * roughness;//detail02
half3 dispNormal = HeightToNormal(_WaterDisplacementTexture, sampler_PlanarReflectionTexture_repeat_bilinear, IN.screenPosPreVert.xy, 2) * 0.4;//convert displacement pass to normal
half3 normal = bump1 + bump2 + waveNormals;//combine all the normals
//World normals
half3 worldNormal = normal.xzy;//we can cheat here since the water is always facing up, we can convert tangent to world with a swizzle
///////////////////////Fresnel////////////////////////////
half3 worldViewDir = normalize(UnityWorldSpaceViewDir(IN.worldPos));
half fresnel = 0.02 + 0.97 * pow(1.0 - saturate(dot (normalize(worldViewDir), worldNormal)), 5);//fresnel
/////////////////////Lighting////////////////////////////
half3 lighting = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, IN.uv2));
half spec = pow(max(0, dot(normal.xzy, IN.spec)), 128) * 12;
half translucency = (-IN.diff.w * 0.5 + waveHeight) * IN.diff.x;
translucency *= fresnel;
//////////////////////Planar refelction///////////////////
//create a flattened view dir
float3 viewDir = UNITY_MATRIX_IT_MV[2].xyz;
viewDir.y = 0;
viewDir = normalize(viewDir);
//create view normal
half3 viewNormal = mul( UNITY_MATRIX_V, float4(worldNormal,0) ).xyz;
//calculate screen-spaced UV offset for planar reflections
half2 refOffset = 0;
refOffset.x = viewNormal.x * 0.02;
refOffset.y = dot(viewDir, worldNormal) * 0.15;
half rimFade = (1-(fresnel * 1)) + 0.25;//value to smooth out reflection distortion on glancing/distant angles
refOffset *= rimFade;
fixed4 reflection = _PlanarReflectionTexture.Sample(sampler_PlanarReflectionTexture_repeat_bilinear, reflectionUV + refOffset);//planar reflection
///////////////////////Depth/Refraction////////////////////
float d = tex2D(_CameraDepthTexture, half2(reflectionUV.x, 1-reflectionUV.y)).r;
float depth = LinearEyeDepth(d) * IN.screenPos.z - IN.worldPos.w;
half waterDepth = (tex2D(_WaterDepthMap, IN.uvs.xy).r * _MaxDepth);
//waterDepth += IN.worldPos.y;
////////////////////////////Edgeing///////////////////////
half edging = 0;
//////////////////////////Colouring///////////////////////
half4 disp = _WaterDisplacementTexture.Sample(sampler_PlanarReflectionTexture_repeat_bilinear, IN.screenPosPreVert.xy);//sample displacement pass
fixed3 col = tex2D(_AbsorptionScatteringRamp, float2(saturate(depth * 0.01), 0));
//col += saturate(translucency) * half3(0, 0.75, 0.5);
//col *= lighting * (1.2-fresnel);
reflection *= length(1-col.rgb) * clamp(fresnel, 0, 0.5);
//fixed3 col = lerp(_Color2.rgb, _Color.rgb, 1-saturate(pow(waterDepth * 0.05, 0.25)));// - pow(fresnel, 5) - (IN.worldPos.y * -0.5)));// saturate((-IN.worldPos.y * 0.5) + pow(fresnel, 0.5)));
float3 blend = col + reflection.xyz;
//half foam = _FoamMap.Sample(sampler_BumpMap, IN.uvs.zw + frac(_Time.y * 0.05)).r;
half foam = tex2D(_FoamMap, (IN.uvs.zw * 0.25) + frac(_Time.y * 0.01)).r;
foam += waveHeight / _MaxWaveHeight + disp.y;
foam = saturate(Remap(foam, half4(0.8, 1.5, 0, 1)));// * lighting;
//foam = clamp(Remap(foam + waveHeight + (disp.y * 2), float4(0.75, 1, 0, 1)), 0, 2); //lerp(0, foam, saturate((i.worldPos.y * 2 - 1) + (disp * 2)));
UNITY_APPLY_FOG(IN.fogCoord, blend);
///////////////////////DEBUG OUTPUTS//////////////////////
//return float4(frac(depth * 0.01), frac(IN.worldPos.w * 0.01), 0, 1);
//return float4(reflection.rgb, 1);
//return float4(waterDepth, 0, 0, 1);
//return float4(waveHeight, 0, 0, 1);
return float4(saturate(blend + foam), 1);
}
ENDCG
}
//meta pass
Pass
{
Name "META"
Tags {"LightMode"="Meta"}
Cull Off
CGPROGRAM
#include "UnityStandardMeta.cginc"
float4 frag_meta2 (v2f_meta i): SV_Target
{
// We're interested in diffuse & specular colors
// and surface roughness to produce final albedo.
//FragmentCommonData data = UNITY_SETUP_BRDF_INPUT (i.uv);
UnityMetaInput o;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o);
fixed4 c = fixed4(0, 0.2, 0.4, 0.5);
o.Albedo = c.rgb;
o.Emission = c.rgb;
return UnityMetaFragment(o);
}
#pragma vertex vert_meta
#pragma fragment frag_meta2
#pragma shader_feature _EMISSION
#pragma shader_feature _METALLICGLOSSMAP
ENDCG
}
}
//Fallback "LightweightPipeline/Standard (Physically Based)"
}