升级水插件
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#ifndef CREST_UNDERWATER_MASK_SHARED_INCLUDED
|
||||
#define CREST_UNDERWATER_MASK_SHARED_INCLUDED
|
||||
#ifndef d_WaveHarmonic_Crest_Mask
|
||||
#define d_WaveHarmonic_Crest_Mask
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
|
||||
@@ -18,43 +18,45 @@
|
||||
#include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Library/Portals.hlsl"
|
||||
#endif
|
||||
|
||||
// Variable mask for when fog is applied before transparent pass and water tile might be culled.
|
||||
half _Crest_MaskBelowSurface;
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
// The old unity macros require this name and type.
|
||||
float4 vertex : POSITION;
|
||||
float4 positionCS : POSITION;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
#if d_LodInput
|
||||
float3 positionWS : TEXCOORD;
|
||||
#endif
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
Varyings Vertex(Attributes v)
|
||||
Varyings Vertex(const Attributes i_Input)
|
||||
{
|
||||
// This will work for all pipelines.
|
||||
Varyings output = (Varyings)0;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_SETUP_INSTANCE_ID(i_Input);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||
|
||||
const Cascade cascade0 = Cascade::Make(_Crest_LodIndex);
|
||||
const Cascade cascade1 = Cascade::Make(_Crest_LodIndex + 1);
|
||||
const uint slice0 = _Crest_LodIndex;
|
||||
const uint slice1 = _Crest_LodIndex + 1;
|
||||
|
||||
float3 worldPos = mul(UNITY_MATRIX_M, float4(v.vertex.xyz, 1.0)).xyz;
|
||||
const Cascade cascade0 = Cascade::Make(slice0);
|
||||
const Cascade cascade1 = Cascade::Make(slice1);
|
||||
|
||||
float3 positionWS = mul(UNITY_MATRIX_M, float4(i_Input.positionCS.xyz, 1.0)).xyz;
|
||||
|
||||
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
|
||||
worldPos.xz += _WorldSpaceCameraPos.xz;
|
||||
positionWS.xz += _WorldSpaceCameraPos.xz;
|
||||
#endif
|
||||
|
||||
// Vertex snapping and lod transition
|
||||
float lodAlpha;
|
||||
SnapAndTransitionVertLayout(_Crest_ChunkMeshScaleAlpha, cascade0, _Crest_ChunkGeometryGridWidth, worldPos, lodAlpha);
|
||||
float alpha;
|
||||
SnapAndTransitionVertLayout(_Crest_ChunkMeshScaleAlpha, cascade0, _Crest_ChunkGeometryGridWidth, positionWS, alpha);
|
||||
|
||||
{
|
||||
// Scale up by small "epsilon" to solve numerical issues. Expand slightly about tile center.
|
||||
@@ -64,83 +66,82 @@ Varyings Vertex(Attributes v)
|
||||
tileCenterXZ += _WorldSpaceCameraPos.xz;
|
||||
#endif
|
||||
const float2 cameraPositionXZ = abs(_WorldSpaceCameraPos.xz);
|
||||
// Scale "epsilon" by distance from zero. There is an issue where overlaps can cause SV_IsFrontFace
|
||||
// to be flipped (needs to be investigated). Gaps look bad from above surface, and overlaps look bad
|
||||
// from below surface. We want to close gaps without introducing overlaps. A fixed "epsilon" will
|
||||
// either not solve gaps at large distances or introduce too many overlaps at small distances. Even
|
||||
// with scaling, there are still unsolvable overlaps underwater (especially at large distances).
|
||||
// 100,000 (0.00001) is the maximum position before Unity warns the user of precision issues.
|
||||
worldPos.xz = lerp(tileCenterXZ, worldPos.xz, lerp(1.0, 1.01, max(cameraPositionXZ.x, cameraPositionXZ.y) * 0.00001));
|
||||
positionWS.xz = lerp(tileCenterXZ, positionWS.xz, lerp(1.0, 1.01, max(cameraPositionXZ.x, cameraPositionXZ.y) * 0.00001));
|
||||
}
|
||||
|
||||
// Calculate sample weights. params.z allows shape to be faded out (used on last lod to support pop-less scale transitions)
|
||||
const float wt_smallerLod = (1.0 - lodAlpha) * cascade0._Weight;
|
||||
const float wt_biggerLod = (1.0 - wt_smallerLod) * cascade1._Weight;
|
||||
// Sample displacement textures, add results to current world pos / normal / foam
|
||||
const float2 positionWS_XZ_before = worldPos.xz;
|
||||
const float weight0 = (1.0 - alpha) * cascade0._Weight;
|
||||
const float weight1 = (1.0 - weight0) * cascade1._Weight;
|
||||
|
||||
// Data that needs to be sampled at the undisplaced position
|
||||
if (wt_smallerLod > m_CrestSampleLodThreshold)
|
||||
const float2 positionXZ = positionWS.xz;
|
||||
|
||||
// Data that needs to be sampled at the undisplaced position.
|
||||
if (weight0 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
Cascade::MakeAnimatedWaves(_Crest_LodIndex).SampleDisplacement(positionWS_XZ_before, wt_smallerLod, worldPos);
|
||||
Cascade::MakeAnimatedWaves(slice0).SampleDisplacement(positionXZ, weight0, positionWS);
|
||||
}
|
||||
if (wt_biggerLod > m_CrestSampleLodThreshold)
|
||||
if (weight1 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
Cascade::MakeAnimatedWaves(_Crest_LodIndex + 1).SampleDisplacement(positionWS_XZ_before, wt_biggerLod, worldPos);
|
||||
Cascade::MakeAnimatedWaves(slice1).SampleDisplacement(positionXZ, weight1, positionWS);
|
||||
}
|
||||
|
||||
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
|
||||
worldPos.xz -= _WorldSpaceCameraPos.xz;
|
||||
positionWS.xz -= _WorldSpaceCameraPos.xz;
|
||||
#endif
|
||||
|
||||
output.positionCS = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0));
|
||||
output.positionCS = mul(UNITY_MATRIX_VP, float4(positionWS, 1.0));
|
||||
|
||||
#if d_LodInput
|
||||
output.positionWS = positionWS;
|
||||
#endif
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
half4 Fragment(const Varyings input, const bool i_isFrontFace)
|
||||
half4 Fragment(const Varyings i_Input, const bool i_FrontFace)
|
||||
{
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i_Input);
|
||||
|
||||
half4 result = 0.0;
|
||||
#if d_LodInput
|
||||
return half4(i_Input.positionWS.y - g_Crest_WaterCenter.y, 0, 0, 1);
|
||||
#endif
|
||||
|
||||
half result = 0.0;
|
||||
|
||||
#if (CREST_PORTALS != 0)
|
||||
#if !d_Tunnel
|
||||
bool masked = false;
|
||||
|
||||
if (m_CrestPortal)
|
||||
{
|
||||
masked = ApplyVolumeToWaterMask(input.positionCS);
|
||||
Portal::EvaluateMask(i_Input.positionCS);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (IsUnderwater(i_isFrontFace, g_Crest_ForceUnderwater))
|
||||
if (IsUnderWater(i_FrontFace, g_Crest_ForceUnderwater))
|
||||
{
|
||||
result = (half4)_Crest_MaskBelowSurface;
|
||||
result = CREST_MASK_BELOW_SURFACE;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (half4)CREST_MASK_ABOVE_SURFACE;
|
||||
result = CREST_MASK_ABOVE_SURFACE;
|
||||
}
|
||||
|
||||
#if (CREST_PORTALS != 0)
|
||||
#if d_Crest_NegativeVolumePass
|
||||
result = Portal::FixMaskForNegativeVolume(result, i_Input.positionCS.xy);
|
||||
#endif
|
||||
|
||||
#if d_Tunnel
|
||||
const float rawFrontFaceZ = LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeFrontFaceTexture, input.positionCS.xy);
|
||||
const float rawBackFaceZ = LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeBackFaceTexture, input.positionCS.xy);
|
||||
if (rawFrontFaceZ <= 0.0 && rawBackFaceZ > 0.0)
|
||||
const float2 positionSS = i_Input.positionCS.xy;
|
||||
const float ffz = LOAD_DEPTH_TEXTURE_X(_Crest_PortalFogBeforeTexture, positionSS);
|
||||
const float bfz = LOAD_DEPTH_TEXTURE_X(_Crest_PortalFogAfterTexture, positionSS);
|
||||
if (ffz <= 0.0 && bfz > 0.0)
|
||||
{
|
||||
result = (half4)CREST_MASK_ABOVE_SURFACE;
|
||||
}
|
||||
#else
|
||||
if (m_CrestPortal)
|
||||
{
|
||||
result *= masked ? 2 : 1;
|
||||
result = CREST_MASK_ABOVE_SURFACE;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return result;
|
||||
return (half4)result;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
@@ -148,4 +149,4 @@ m_CrestNameSpaceEnd
|
||||
m_CrestVertex
|
||||
m_CrestFragmentWithFrontFace(half4)
|
||||
|
||||
#endif // CREST_UNDERWATER_MASK_SHARED_INCLUDED
|
||||
#endif // d_WaveHarmonic_Crest_Mask
|
||||
|
||||
Reference in New Issue
Block a user