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

269 行
8.3 KiB

#ifndef WATER_COMMON_INCLUDED
#define WATER_COMMON_INCLUDED
#define _SHADOWS_SOFT
#define _SHADOWS_ENABLED
#include "WaterInput.hlsl"
#include "CommonUtilities.hlsl"
#include "GerstnerWaves.cginc"
#include "WaterLighting.hlsl"
///////////////////////////////////////////////////////////////////////////////
// Structs //
///////////////////////////////////////////////////////////////////////////////
struct WaterVertexInput // vert struct
{
float4 vertex : POSITION; // vertex positions
float2 texcoord : TEXCOORD0; // local UVs
float4 lightmapUV : TEXCOORD1; // lightmap UVs
float4 color : COLOR; // vertex colors
};
struct WaterVertexOutput // fragment struct
{
float4 uv : TEXCOORD0; // Geometric UVs stored in xy, and world(pre-waves) in zw
float4 lightmapUVOrVertexSH : TEXCOORD1; // holds either lightmapUV or vertex SH. depending on LIGHTMAP_ON - TODO
float3 posWS : TEXCOORD2; // world position of the vertices
half3 normal : NORMAL; // vert normals
float3 viewDir : TEXCOORD3; // view direction
float2 preWaveSP : TEXCOORD4; // screen position of the verticies before wave distortion
half4 fogFactorAndVertexLight : TEXCOORD5; // x: fogFactor, yzw: vertex light
half4 additionalData : TEXCOORD6; // x = distance to surface, y = distance to surface??
half4 vertColor : TEXCOORD7;
float4 clipPos : SV_POSITION;
};
///////////////////////////////////////////////////////////////////////////////
// Water shading functions //
///////////////////////////////////////////////////////////////////////////////
half3 Scattering(half depth)
{
return _AbsorptionScatteringRamp.Sample(sampler_AbsorptionScatteringRamp, float2(saturate(depth * 0.01), 0.75));
}
half3 Absorption(half depth)
{
return _AbsorptionScatteringRamp.Sample(sampler_AbsorptionScatteringRamp, float2(saturate(depth * 0.01), 0.25));
}
half2 WaterDepth(half3 posWS, half3 viewDir, half2 texcoords, half4 additionalData, half2 screenUVs)// x = seafloor depth, y = water depth
{
half2 outDepth = 0;
half d = _CameraDepthTexture.Sample(sampler_CameraDepthTexture, screenUVs).r;
outDepth.x = LinearEyeDepth(d, _ZBufferParams) * additionalData.x - additionalData.y;
half wd = 1-_WaterDepthMap.Sample(sampler_WaterDepthMap, texcoords).r;
outDepth.y = ((wd * _depthCamZParams.y) - 4 - _depthCamZParams.x) + posWS.y;
//outDepth.y += posWS.y;
return outDepth;
}
//temp
inline float3 ObjSpaceViewDir( in float4 v )
{
float3 objSpaceCameraPos = mul(GetWorldToObjectMatrix(), float4(GetCameraPositionWS(), 1)).xyz;
return objSpaceCameraPos - v.xyz;
}
///////////////////////////////////////////////////////////////////////////////
// Vertex and Fragment functions //
///////////////////////////////////////////////////////////////////////////////
// Vertex: Used for Standard non-tessellated water
WaterVertexOutput WaterVertex(WaterVertexInput v)
{
WaterVertexOutput o = (WaterVertexOutput)0;
o.uv.xy = v.texcoord; // geo uvs
// initializes o.normal
o.normal = float3(0, 1, 0);
o.posWS = TransformObjectToWorld(v.vertex.xyz);
o.uv.zw = o.posWS.xz;
o.clipPos = TransformWorldToHClip(o.posWS);
o.viewDir = SafeNormalize(_WorldSpaceCameraPos - o.posWS);
o.vertColor = v.color;
// We either sample GI from lightmap or SH. lightmap UV and vertex SH coefficients
// are packed in lightmapUVOrVertexSH to save interpolator.
// The following funcions initialize
OUTPUT_LIGHTMAP_UV(v.lightmapUV, unity_LightmapST, o.lightmapUVOrVertexSH);
OUTPUT_SH(o.normal, o.lightmapUVOrVertexSH);
o.fogFactorAndVertexLight = VertexLightingAndFog(o.normal, o.posWS, o.clipPos);
// Additional data
//o.additionalData.y = length(ObjSpaceViewDir(v.vertex));
return o;
}
// Fragment for water
half4 WaterFragment(WaterVertexOutput IN) : SV_Target
{
#if defined (_PERF_VERT) // PERF
half2 screenUV = ComputeNormalizedDeviceCoordinates(IN.clipPos);//screen UVs
screenUV /= half2(_ScreenParams.x * 0.5, -_ScreenParams.y * 0.5);// TODO - might be a SRP fix
half3 prePosWS = IN.posWS;
half4 waterFX = _WaterFXMap.Sample(sampler_WaterFXMap, float2(screenUV.x, screenUV.y));
#if _TESSELLATION
half3 normalWS = normalize(IN.normal);
#else
//Do the gerstner waves in the pixel shader
WaveStruct wave;
#if defined (_PERF_GERSTNER) // PERF
SampleWaves(IN.posWS, 1, wave);
//IN.posWS.xz -= wave.position.xz;
IN.uv.zw -= wave.position.xz;
SampleWaves(IN.posWS, 1, wave);
#else
wave.position = 0;
wave.normal = float3(0, 0, 1);
#endif
IN.additionalData.y = length(ObjSpaceViewDir(half4(IN.posWS + wave.position, 1)));
half3 normalWS = normalize(wave.normal.xzy);
//half thing = (length(wave.position.xz) * (wave.position.y + 0.25)) / _WaveCount;
//half thing = _PeakMap.Sample(sampler_PeakMap, float2(wave.position.y, 0));
IN.posWS.y += wave.position.y; //thing;
// Additional data(in vertex otherwise)
float3 viewPos = TransformWorldToView(IN.posWS);
IN.additionalData.x = length(viewPos / viewPos.z);// distance to surface
#endif
//Detail waves
half t = _Time.x;
half3 detailBump = UnpackNormal(_BumpMap.Sample(sampler_BumpMap, IN.uv.zw * 0.05 + (t * 0.25)));
detailBump += UnpackNormal(_BumpMap.Sample(sampler_BumpMap, (IN.uv.zw * 0.15) + (detailBump.xy * 0.01) - t));
normalWS += half3(detailBump.x, 0, detailBump.y) * _BumpScale;
// Depth
#if defined (_PERF_DEPTH) // PERF
half2 depth = WaterDepth(IN.posWS, IN.viewDir, IN.uv.xy, IN.additionalData, half2(screenUV.x, screenUV.y));
#else
half2 depth = 100;
#endif
// Fresnel
#if defined (_PERF_FRESNEL) // PERF
half fresnelTerm = CalculateFresnelTerm(lerp(normalWS, half3(0, 1, 0), 0.5), IN.viewDir.xyz);
#else
half fresnelTerm = 0;
#endif
// Shadows
//float4 shadowCoord = ComputeShadowCoord(prePosWS);
half shadow = RealtimeShadowAttenuation(prePosWS); //SampleShadowmap(shadowCoord);
// Do diffuse/fog?
half3 indirectDiffuse = SampleGI(IN.lightmapUVOrVertexSH, normalWS);
float fogFactor = IN.fogFactorAndVertexLight.x;
// Do specular
#if defined (_PERF_LIGHTING) // PERF
half3 spec = Highlights(IN.posWS, 0.01, normalWS, IN.viewDir) * shadow;
#else
half3 spec = 0;
#endif
// Do reflections
#if defined (_PERF_REF) // PERF
half3 reflection = SampleReflections(normalWS, IN.viewDir.xyz, screenUV, fresnelTerm, 0.0);
#else
half3 reflection = 0;
#endif
reflection = max(reflection, spec);
// Do Refractions
//half3 refraction = _CameraColorTexture.Sample(sampler_CameraColorTexture, screenUV);
// Do Foam
#if defined (_PERF_FOAM) // PERF
half3 foamMap = _FoamMap.Sample(sampler_FoamMap, (IN.uv.zw * 0.025) + (detailBump.xy * 0.0025)); //r=thick, g=medium, b=light
half shoreMask = saturate((1-depth.y + 1.25) * 0.35);//shore foam
half foamMask = IN.posWS.y - 0.5;
foamMask = saturate(foamMask + shoreMask + waterFX.r);
half foamA = lerp(0, foamMap.b, saturate(foamMask * 4 - 1));
half foamB = lerp(foamMap.g, foamMap.r, saturate(foamMask * 4 - 3));
half foam = lerp(foamA, foamB, saturate(foamMask * 4 - 2)) * (shadow + 0.5);
#else
half foam = 0;
#endif
// Do colouring
half3 color = 1;// TODO - get scene colour
#if defined (_PERF_COL) // PERF
color *= Absorption(depth.x);// TODO - absoption
color += Scattering(depth.x);// TODO - scattering
color *= saturate(min(shadow + 0.1, 1-fresnelTerm));
#else
color = 0.5;
#endif
// Do compositing
half3 comp = color + (foam * 0.75) + (reflection * (1-(foam)));
// Computes fog factor per-vertex
ApplyFog(comp, fogFactor);
//DebugViews
#if _DEBUG
if(_DebugPass == 1)
{
return half4(reflection, 1); // Reflection debug
}
else if(_DebugPass == 2) // Color debug
{
return half4(color, 1);
}
else if(_DebugPass == 3) // Depth debug
{
return half4(depth, 0, 1);
}
else if(_DebugPass == 4) // WaterFX pass debug
{
return waterFX;
}
else if(_DebugPass == 5) // Normals debug
{
return half4(normalWS, 1);
}
else if(_DebugPass == 6) // Fresnel debug
{
return half4(fresnelTerm, 0, 0, 1);
}
else if(_DebugPass == 7) // Specular debug
{
return half4(spec, 1);
}
else if(_DebugPass == 8) // Temp debug
{
return half4(frac(IN.uv.zw), 0, 1);
}
else // fallback to output
{
return half4(comp, 1);
}
#else
return half4(comp, 1);
#endif
#else // vert perf
return half4(0.5, 0.5, 0.5, 1);
#endif
}
#endif // WATER_COMMON_INCLUDED