升级6.4.升级水,升级天气
This commit is contained in:
@@ -16,7 +16,7 @@ float ClipSurface(const float2 i_PositionWSXZ)
|
||||
{
|
||||
// Do not include transition slice to avoid blending as we do a black border instead.
|
||||
uint slice0; uint slice1; float alpha;
|
||||
PosToSliceIndices(i_PositionWSXZ, 0.0, g_Crest_LodCount - 1.0, g_Crest_WaterScale, slice0, slice1, alpha);
|
||||
PositionToSliceIndices(i_PositionWSXZ, 0, g_Crest_LodCount - 1, g_Crest_WaterScale, slice0, slice1, alpha);
|
||||
|
||||
const Cascade cascade0 = Cascade::Make(slice0);
|
||||
const Cascade cascade1 = Cascade::Make(slice1);
|
||||
@@ -34,7 +34,7 @@ float ClipSurface(const float2 i_PositionWSXZ)
|
||||
Cascade::MakeClip(slice1).SampleClip(i_PositionWSXZ, weight1, value);
|
||||
}
|
||||
|
||||
return lerp(g_Crest_ClipByDefault, value, weight0 + weight1);
|
||||
return value;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
@@ -77,6 +77,7 @@ half3 Caustics
|
||||
);
|
||||
}
|
||||
|
||||
#if d_Crest_CausticsForceDistortion
|
||||
if (i_Underwater)
|
||||
{
|
||||
float2 surfacePosXZ = i_ScenePositionWS.xz;
|
||||
@@ -93,6 +94,7 @@ half3 Caustics
|
||||
cuv1.xy += 1.30 * causticN;
|
||||
cuv2.xy += 1.77 * causticN;
|
||||
}
|
||||
#endif
|
||||
|
||||
half causticsStrength = i_Strength;
|
||||
|
||||
|
||||
@@ -12,28 +12,43 @@ TEXTURE2D_FLOAT(_Crest_WaterLine);
|
||||
float _Crest_WaterLineTexel;
|
||||
float2 _Crest_WaterLineResolution;
|
||||
float2 _Crest_WaterLineSnappedPosition;
|
||||
bool _Crest_WaterLineFlatWater;
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
float SampleWaterLineHeight(const float2 i_PositionWS)
|
||||
{
|
||||
const float2 uv = (i_PositionWS - _Crest_WaterLineSnappedPosition) / (_Crest_WaterLineTexel * _Crest_WaterLineResolution) + 0.5;
|
||||
return _Crest_WaterLine.SampleLevel(_Crest_linear_clamp_sampler, uv, 0).r + g_Crest_WaterCenter.y;
|
||||
if (_Crest_WaterLineFlatWater)
|
||||
{
|
||||
return g_Crest_WaterCenter.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float2 uv = (i_PositionWS - _Crest_WaterLineSnappedPosition) / (_Crest_WaterLineTexel * _Crest_WaterLineResolution) + 0.5;
|
||||
return _Crest_WaterLine.SampleLevel(LODData_linear_clamp_sampler, uv, 0).r + g_Crest_WaterCenter.y;
|
||||
}
|
||||
}
|
||||
|
||||
half3 SampleWaterLineNormal(const float2 i_PositionWS, const float i_Height)
|
||||
{
|
||||
const float2 uv = (i_PositionWS - _Crest_WaterLineSnappedPosition) / (_Crest_WaterLineTexel * _Crest_WaterLineResolution) + 0.5;
|
||||
const float3 dd = float3(1.0 / _Crest_WaterLineResolution.xy, 0.0);
|
||||
const float xOffset = _Crest_WaterLine.SampleLevel(_Crest_linear_clamp_sampler, uv + dd.xz, 0).r;
|
||||
const float zOffset = _Crest_WaterLine.SampleLevel(_Crest_linear_clamp_sampler, uv + dd.zy, 0).r;
|
||||
if (_Crest_WaterLineFlatWater)
|
||||
{
|
||||
return half3(0, 1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float2 uv = (i_PositionWS - _Crest_WaterLineSnappedPosition) / (_Crest_WaterLineTexel * _Crest_WaterLineResolution) + 0.5;
|
||||
const float3 dd = float3(1.0 / _Crest_WaterLineResolution.xy, 0.0);
|
||||
const float xOffset = _Crest_WaterLine.SampleLevel(LODData_linear_clamp_sampler, uv + dd.xz, 0).r;
|
||||
const float zOffset = _Crest_WaterLine.SampleLevel(LODData_linear_clamp_sampler, uv + dd.zy, 0).r;
|
||||
|
||||
return normalize(half3
|
||||
(
|
||||
(xOffset - i_Height) / _Crest_WaterLineTexel,
|
||||
1.0,
|
||||
(zOffset - i_Height) / _Crest_WaterLineTexel
|
||||
));
|
||||
return normalize(half3
|
||||
(
|
||||
(xOffset - i_Height) / _Crest_WaterLineTexel,
|
||||
1.0,
|
||||
(zOffset - i_Height) / _Crest_WaterLineTexel
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#ifndef d_WaveHarmonic_Crest_Surface_Emission
|
||||
#define d_WaveHarmonic_Crest_Surface_Emission
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
half3 FoamBioluminescence
|
||||
(
|
||||
const half i_FoamData,
|
||||
const half i_FoamMap,
|
||||
const half3 i_BioluminescenceColor,
|
||||
const half i_BioluminescenceIntensity,
|
||||
const half i_BioluminescenceGlowCoverage,
|
||||
const half i_BioluminescenceGlowIntensity,
|
||||
const bool i_BioluminescenceSparklesEnabled,
|
||||
const half i_BioluminescenceSparklesMap,
|
||||
const half i_BioluminescenceSparklesCoverage,
|
||||
const half i_BioluminescenceSparklesIntensity,
|
||||
const half i_BioluminescenceMaximumDepth,
|
||||
const half i_WaterDepth
|
||||
)
|
||||
{
|
||||
half3 emission = 0.0;
|
||||
|
||||
const half weight = 1.0 - saturate(i_WaterDepth / i_BioluminescenceMaximumDepth);
|
||||
|
||||
if (weight <= 0.0)
|
||||
{
|
||||
return emission;
|
||||
}
|
||||
|
||||
emission +=
|
||||
(i_BioluminescenceColor * i_FoamMap * i_BioluminescenceIntensity) +
|
||||
(i_BioluminescenceColor * saturate(i_FoamData - (1.0 - i_BioluminescenceGlowCoverage)) * i_BioluminescenceGlowIntensity);
|
||||
|
||||
if (i_BioluminescenceSparklesEnabled)
|
||||
{
|
||||
emission += (i_BioluminescenceColor * i_BioluminescenceSparklesMap * saturate(i_FoamData - (1.0 - i_BioluminescenceSparklesCoverage)) * i_BioluminescenceSparklesIntensity);
|
||||
}
|
||||
|
||||
emission *= weight;
|
||||
|
||||
return emission;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
#endif // d_WaveHarmonic_Crest_Surface_Emission
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4707eb239a4b242d4ac074ac67b5544e
|
||||
ShaderIncludeImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -14,9 +14,15 @@
|
||||
#include "Packages/com.waveharmonic.crest.shifting-origin/Runtime/Shaders/ShiftingOrigin.hlsl"
|
||||
#endif
|
||||
|
||||
#if d_Crest_FoamStochastic
|
||||
#define m_SampleFoam SampleStochastic
|
||||
#else
|
||||
#define m_SampleFoam Sample
|
||||
#endif
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
half WhiteFoamTexture
|
||||
half2 WhiteFoamTexture
|
||||
(
|
||||
const TiledTexture i_Texture,
|
||||
const half i_Foam,
|
||||
@@ -25,27 +31,52 @@ half WhiteFoamTexture
|
||||
const float2 i_WorldXZ1,
|
||||
const float2 i_TexelOffset,
|
||||
const half i_LodAlpha,
|
||||
const Cascade i_CascadeData0
|
||||
const Cascade i_CascadeData0,
|
||||
const bool i_Sample2ndChannel = false
|
||||
)
|
||||
{
|
||||
const float2 uvOffset = i_TexelOffset + g_Crest_Time * i_Texture._speed / 32.0;
|
||||
// Scale with lods to get multiscale detail. 10 is magic number that gets the
|
||||
// material 'scale' slider into an intuitive range.
|
||||
const float scale = i_Texture._scale * i_CascadeData0._Scale / 10.0;
|
||||
float scale = i_Texture._scale * 0.5;
|
||||
|
||||
half ft = lerp
|
||||
(
|
||||
i_Texture.Sample((i_WorldXZ0 + uvOffset) / scale).r,
|
||||
i_Texture.Sample((i_WorldXZ1 + uvOffset) / (2.0 * scale)).r,
|
||||
i_LodAlpha
|
||||
);
|
||||
#if d_Crest_FoamMultiScale
|
||||
// 0.5 * 0.2 == / 10. We only need the full amount for multi-scale to account for
|
||||
// the default lower scale of 4. * 0.5 alone above will not match multi-scaled, but
|
||||
// overall better matches visually.
|
||||
scale *= i_CascadeData0._Scale * 0.2;
|
||||
#endif
|
||||
|
||||
half2 f0 = i_Texture.m_SampleFoam((i_WorldXZ0 + uvOffset) / scale).rg;
|
||||
|
||||
#if d_Crest_FoamMultiScale
|
||||
const half2 f1 = i_Texture.m_SampleFoam((i_WorldXZ1 + uvOffset) / (2.0 * scale)).rg;
|
||||
#endif
|
||||
|
||||
// Black point fade.
|
||||
half result = saturate(1.0 - i_Foam);
|
||||
return smoothstep(result, result + i_Feather, ft);
|
||||
const half result = saturate(1.0 - i_Foam);
|
||||
|
||||
#if d_Crest_FoamBioluminescence
|
||||
if (i_Sample2ndChannel)
|
||||
{
|
||||
#if d_Crest_FoamMultiScale
|
||||
f0 = lerp(f0, f1, i_LodAlpha);
|
||||
#endif
|
||||
|
||||
return smoothstep(result, result + i_Feather, f0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if d_Crest_FoamMultiScale
|
||||
f0.r = lerp(f0.r, f1.r, i_LodAlpha);
|
||||
#endif
|
||||
|
||||
return half2(smoothstep(result, result + i_Feather, f0.r), 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
half MultiScaleFoamAlbedo
|
||||
half2 MultiScaleFoamAlbedo
|
||||
(
|
||||
const TiledTexture i_Texture,
|
||||
const half i_Feather,
|
||||
@@ -53,7 +84,8 @@ half MultiScaleFoamAlbedo
|
||||
const Cascade i_CascadeData0,
|
||||
const Cascade i_CascadeData1,
|
||||
const half i_LodAlpha,
|
||||
const float2 i_UndisplacedXZ
|
||||
const float2 i_UndisplacedXZ,
|
||||
const bool i_Sample2ndChannel
|
||||
)
|
||||
{
|
||||
float2 worldXZ0 = i_UndisplacedXZ;
|
||||
@@ -67,20 +99,20 @@ half MultiScaleFoamAlbedo
|
||||
worldXZ1 -= ShiftingOriginOffset(i_Texture, i_CascadeData1);
|
||||
#endif // CREST_SHIFTING_ORIGIN
|
||||
|
||||
return WhiteFoamTexture(i_Texture, i_FoamData, i_Feather, worldXZ0, worldXZ1, (float2)0.0, i_LodAlpha, i_CascadeData0);
|
||||
return WhiteFoamTexture(i_Texture, i_FoamData, i_Feather, worldXZ0, worldXZ1, (float2)0.0, i_LodAlpha, i_CascadeData0, i_Sample2ndChannel);
|
||||
}
|
||||
|
||||
half2 MultiScaleFoamNormal
|
||||
(
|
||||
const TiledTexture i_Texture,
|
||||
const half i_Feather,
|
||||
const half i_NormalStrength,
|
||||
const half i_FoamData,
|
||||
const half i_FoamAlbedo,
|
||||
const Cascade i_CascadeData0,
|
||||
const Cascade i_CascadeData1,
|
||||
const half i_LodAlpha,
|
||||
const float2 i_UndisplacedXZ,
|
||||
const half i_NormalStrength,
|
||||
const half i_FoamAlbedo,
|
||||
const float i_PixelZ
|
||||
)
|
||||
{
|
||||
@@ -97,8 +129,8 @@ half2 MultiScaleFoamNormal
|
||||
|
||||
// 0.25 is magic number found through tweaking.
|
||||
const float2 dd = float2(0.25 * i_PixelZ * i_Texture._texel, 0.0);
|
||||
const half whiteFoam_x = WhiteFoamTexture(i_Texture, i_FoamData, i_Feather, worldXZ0, worldXZ1, dd.xy, i_LodAlpha, i_CascadeData0);
|
||||
const half whiteFoam_z = WhiteFoamTexture(i_Texture, i_FoamData, i_Feather, worldXZ0, worldXZ1, dd.yx, i_LodAlpha, i_CascadeData0);
|
||||
const half whiteFoam_x = WhiteFoamTexture(i_Texture, i_FoamData, i_Feather, worldXZ0, worldXZ1, dd.xy, i_LodAlpha, i_CascadeData0).r;
|
||||
const half whiteFoam_z = WhiteFoamTexture(i_Texture, i_FoamData, i_Feather, worldXZ0, worldXZ1, dd.yx, i_LodAlpha, i_CascadeData0).r;
|
||||
|
||||
// Compute a foam normal - manually push in derivatives. If I used blend
|
||||
// smooths all the normals towards straight up when there is no foam.
|
||||
@@ -107,7 +139,7 @@ half2 MultiScaleFoamNormal
|
||||
return magicStrengthFactor * i_NormalStrength * half2(whiteFoam_x - i_FoamAlbedo, whiteFoam_z - i_FoamAlbedo) / dd.x;
|
||||
}
|
||||
|
||||
half MultiScaleFoamAlbedo
|
||||
half2 MultiScaleFoamAlbedo
|
||||
(
|
||||
const Flow i_Flow,
|
||||
const TiledTexture i_Texture,
|
||||
@@ -116,7 +148,8 @@ half MultiScaleFoamAlbedo
|
||||
const Cascade i_CascadeData0,
|
||||
const Cascade i_CascadeData1,
|
||||
const half i_LodAlpha,
|
||||
const float2 i_UndisplacedXZ
|
||||
const float2 i_UndisplacedXZ,
|
||||
const bool i_Sample2ndChannel
|
||||
)
|
||||
{
|
||||
return MultiScaleFoamAlbedo
|
||||
@@ -127,7 +160,8 @@ half MultiScaleFoamAlbedo
|
||||
i_CascadeData0,
|
||||
i_CascadeData1,
|
||||
i_LodAlpha,
|
||||
i_UndisplacedXZ - i_Flow._Flow * i_Flow._Offset0
|
||||
i_UndisplacedXZ - i_Flow._Flow * i_Flow._Offset0,
|
||||
i_Sample2ndChannel
|
||||
) * i_Flow._Weight0 + MultiScaleFoamAlbedo
|
||||
(
|
||||
i_Texture,
|
||||
@@ -136,7 +170,8 @@ half MultiScaleFoamAlbedo
|
||||
i_CascadeData0,
|
||||
i_CascadeData1,
|
||||
i_LodAlpha,
|
||||
i_UndisplacedXZ - i_Flow._Flow * i_Flow._Offset1
|
||||
i_UndisplacedXZ - i_Flow._Flow * i_Flow._Offset1,
|
||||
i_Sample2ndChannel
|
||||
) * i_Flow._Weight1;
|
||||
}
|
||||
|
||||
@@ -145,13 +180,13 @@ half2 MultiScaleFoamNormal
|
||||
const Flow i_Flow,
|
||||
const TiledTexture i_Texture,
|
||||
const half i_Feather,
|
||||
const half i_NormalStrength,
|
||||
const half i_FoamData,
|
||||
const half i_FoamAlbedo,
|
||||
const Cascade i_CascadeData0,
|
||||
const Cascade i_CascadeData1,
|
||||
const half i_LodAlpha,
|
||||
const float2 i_UndisplacedXZ,
|
||||
const half i_NormalStrength,
|
||||
const half i_FoamAlbedo,
|
||||
const float i_PixelZ
|
||||
)
|
||||
{
|
||||
@@ -159,25 +194,25 @@ half2 MultiScaleFoamNormal
|
||||
(
|
||||
i_Texture,
|
||||
i_Feather,
|
||||
i_NormalStrength,
|
||||
i_FoamData,
|
||||
i_FoamAlbedo,
|
||||
i_CascadeData0,
|
||||
i_CascadeData1,
|
||||
i_LodAlpha,
|
||||
i_UndisplacedXZ - i_Flow._Flow * i_Flow._Offset0,
|
||||
i_NormalStrength,
|
||||
i_FoamAlbedo,
|
||||
i_PixelZ
|
||||
) * i_Flow._Weight0 + MultiScaleFoamNormal
|
||||
(
|
||||
i_Texture,
|
||||
i_Feather,
|
||||
i_NormalStrength,
|
||||
i_FoamData,
|
||||
i_FoamAlbedo,
|
||||
i_CascadeData0,
|
||||
i_CascadeData1,
|
||||
i_LodAlpha,
|
||||
i_UndisplacedXZ - i_Flow._Flow * i_Flow._Offset1,
|
||||
i_NormalStrength,
|
||||
i_FoamAlbedo,
|
||||
i_PixelZ
|
||||
) * i_Flow._Weight1;
|
||||
}
|
||||
@@ -214,8 +249,10 @@ void ApplyFoamToSurface
|
||||
// as if it had transmission.
|
||||
// There is still ugliness around the edges. There will either be black or
|
||||
// incorrect reflections depending on the magic value.
|
||||
io_NormalWS.y *= i_Foam > 0.15 ? -1.0 : 1.0;
|
||||
io_NormalWS = i_Foam > 0.0 ? half3(0.0, 1.0, 0.0) : io_NormalWS;
|
||||
#if _SPECULAR_SETUP
|
||||
io_Specular = lerp(io_Specular, i_Specular, i_Foam);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,13 +23,31 @@ void SetUpFog(bool i_Underwater, float3 i_PositionWS, float i_Multiplier, float
|
||||
{
|
||||
s_IsUnderWater = i_Underwater;
|
||||
|
||||
// XR does not like early returns in URP.
|
||||
#if !defined(STEREO_INSTANCING_ON) && !defined(STEREO_MULTIVIEW_ON)
|
||||
if (!s_IsUnderWater)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CREST_LEGACY_UNDERWATER != 1)
|
||||
s_PositionSS = i_PositionSS;
|
||||
s_PositionWS = i_PositionWS;
|
||||
s_ViewWS = i_ViewWS;
|
||||
s_FogDistance = i_FogDistance;
|
||||
s_DepthRaw = 0;
|
||||
s_FogMultiplier = i_Multiplier;
|
||||
ApplyUnderwaterEffect
|
||||
(
|
||||
0, // Not used (color)
|
||||
0, // TIR only
|
||||
0, // Caustics only
|
||||
i_FogDistance,
|
||||
i_ViewWS,
|
||||
i_PositionSS,
|
||||
i_PositionWS,
|
||||
false, // No caustics
|
||||
true, // TODO: implement
|
||||
false, // Do not apply lighting
|
||||
1.0, // TODO: implement
|
||||
s_VolumeOpacity,
|
||||
s_VolumeLighting
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
// Guard against missing uniforms.
|
||||
#ifdef SHADERPASS
|
||||
|
||||
#define m_Properties \
|
||||
#define m_Properties(iomod) \
|
||||
const float2 i_UndisplacedXZ, \
|
||||
const float i_LodAlpha, \
|
||||
float i_LodAlpha, \
|
||||
const half i_WaterLevelOffset, \
|
||||
const float2 i_WaterLevelDerivatives, \
|
||||
const half2 i_Flow, \
|
||||
const half3 i_ViewDirectionWS, \
|
||||
const bool i_Facing, \
|
||||
@@ -18,14 +17,38 @@
|
||||
const float4 i_ScreenPositionRaw, \
|
||||
const float3 i_PositionWS, \
|
||||
const float3 i_PositionVS, \
|
||||
const half3 i_NormalWS, \
|
||||
const float2 i_StaticLightMapUV, \
|
||||
out half3 o_Albedo, \
|
||||
out half3 o_NormalWS, \
|
||||
out half3 o_Specular, \
|
||||
out half3 o_Emission, \
|
||||
out half o_Smoothness, \
|
||||
out half o_Occlusion, \
|
||||
out half o_Alpha
|
||||
iomod half3 o_Albedo, \
|
||||
iomod half3 o_NormalWS, \
|
||||
iomod half3 o_Specular, \
|
||||
iomod half3 o_Emission, \
|
||||
iomod half o_Smoothness, \
|
||||
iomod half o_Occlusion, \
|
||||
iomod half o_Alpha
|
||||
|
||||
#define m_Parameters \
|
||||
i_UndisplacedXZ, \
|
||||
i_LodAlpha, \
|
||||
i_WaterLevelOffset, \
|
||||
i_Flow, \
|
||||
i_ViewDirectionWS, \
|
||||
i_Facing, \
|
||||
i_SceneColor, \
|
||||
i_SceneDepthRaw, \
|
||||
i_ScreenPosition, \
|
||||
i_ScreenPositionRaw, \
|
||||
i_PositionWS, \
|
||||
i_PositionVS, \
|
||||
i_NormalWS, \
|
||||
i_StaticLightMapUV, \
|
||||
o_Albedo, \
|
||||
o_NormalWS, \
|
||||
o_Specular, \
|
||||
o_Emission, \
|
||||
o_Smoothness, \
|
||||
o_Occlusion, \
|
||||
o_Alpha
|
||||
|
||||
// Guard against Shader Graph preview.
|
||||
#ifndef SHADERGRAPH_PREVIEW
|
||||
@@ -33,13 +56,13 @@
|
||||
#define d_Crest_WaterSurface 1
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Shim.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Keywords.hlsl"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Geometry.hlsl"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl"
|
||||
|
||||
@@ -54,6 +77,7 @@
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Refraction.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Caustics.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/VolumeLighting.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Emission.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fresnel.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Foam.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Alpha.hlsl"
|
||||
@@ -79,17 +103,18 @@ static const TiledTexture _Crest_CausticsTiledTexture =
|
||||
static const TiledTexture _Crest_CausticsDistortionTiledTexture =
|
||||
TiledTexture::Make(_Crest_CausticsDistortionTexture, sampler_Crest_CausticsDistortionTexture, _Crest_CausticsDistortionTexture_TexelSize, _Crest_CausticsDistortionScale, 1.0);
|
||||
|
||||
void Fragment(m_Properties)
|
||||
void Fragment
|
||||
(
|
||||
m_Properties(inout),
|
||||
const uint i_LodIndex0,
|
||||
const uint i_LodIndex1,
|
||||
const float2 i_PositionSS,
|
||||
const bool i_Underwater,
|
||||
const float i_SceneZRaw,
|
||||
const float i_NegativeFog
|
||||
)
|
||||
{
|
||||
o_Albedo = 0.0;
|
||||
o_NormalWS = half3(0.0, 1.0, 0.0);
|
||||
o_Specular = 0.0;
|
||||
o_Emission = 0.0;
|
||||
o_Smoothness = 0.7;
|
||||
o_Occlusion = 1.0;
|
||||
o_Alpha = 1.0;
|
||||
|
||||
const float2 positionSS = i_ScreenPosition.xy * _ScreenSize.xy;
|
||||
float2 scenePositionSS = i_PositionSS;
|
||||
|
||||
// Editor only. There is no defined editor symbol.
|
||||
if (_Crest_DrawBoundaryXZ)
|
||||
@@ -105,85 +130,99 @@ void Fragment(m_Properties)
|
||||
}
|
||||
}
|
||||
|
||||
bool underwater = IsUnderWater(i_Facing, g_Crest_ForceUnderwater, positionSS);
|
||||
|
||||
// TODO: Should we use PosToSIs or check for overflow?
|
||||
float slice0 = _Crest_LodIndex;
|
||||
float slice1 = _Crest_LodIndex + 1;
|
||||
|
||||
#ifdef CREST_FLOW_ON
|
||||
const Flow flow = Flow::Make(i_Flow, g_Crest_Time);
|
||||
#endif
|
||||
const uint slice0 = i_LodIndex0;
|
||||
const uint slice1 = i_LodIndex1;
|
||||
|
||||
const Cascade cascade0 = Cascade::Make(slice0);
|
||||
const Cascade cascade1 = Cascade::Make(slice1);
|
||||
|
||||
float sceneRawZ = i_SceneDepthRaw;
|
||||
float negativeFog = _ProjectionParams.y;
|
||||
const float sceneZ = Utility::CrestLinearEyeDepth(i_SceneZRaw);
|
||||
const float pixelZ = -i_PositionVS.z;
|
||||
|
||||
#if (CREST_PORTALS != 0)
|
||||
#ifndef CREST_SHADOWPASS
|
||||
#if _ALPHATEST_ON
|
||||
if (m_CrestPortal)
|
||||
{
|
||||
const float pixelRawZ = i_ScreenPositionRaw.z / i_ScreenPositionRaw.w;
|
||||
if (Portal::EvaluateSurface(i_ScreenPosition.xy, pixelRawZ, i_PositionWS, underwater, sceneRawZ, negativeFog))
|
||||
{
|
||||
o_Alpha = 0.0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
float sceneZ = Utility::CrestLinearEyeDepth(sceneRawZ);
|
||||
float pixelZ = -i_PositionVS.z;
|
||||
|
||||
const bool isLastLod = _Crest_LodIndex == (uint)g_Crest_LodCount - 1;
|
||||
const bool isLastLod = slice0 == (g_Crest_LodCount - 1);
|
||||
const float weight0 = (1.0 - i_LodAlpha) * cascade0._Weight;
|
||||
const float weight1 = (1.0 - weight0) * cascade1._Weight;
|
||||
|
||||
// Data that fades towards the edge.
|
||||
half foam = 0.0; half _determinant = 0.0; half4 albedo = 0.0; half2 shadow = 0.0;
|
||||
half foam = 0.0; half _determinant = 0.0; half4 albedo = 0.0; half2 shadow = 0.0; half waterDepth = i_WaterLevelOffset; half shorelineDistance = 0.0; half2 flowData = 0.0;
|
||||
if (weight0 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
Cascade::MakeAnimatedWaves(slice0).SampleNormals(i_UndisplacedXZ, weight0, o_NormalWS.xz, _determinant);
|
||||
if (_Crest_ApplyDisplacementNormals)
|
||||
{
|
||||
Cascade::MakeAnimatedWaves(slice0).SampleDisplacementNormal(i_UndisplacedXZ, weight0, o_NormalWS.xz, _determinant);
|
||||
}
|
||||
|
||||
#if d_Crest_CustomMesh && d_Crest_FlowLod
|
||||
Cascade::MakeFlow(slice0).SampleFlow(i_UndisplacedXZ, weight0, flowData);
|
||||
#endif
|
||||
|
||||
if (_Crest_FoamEnabled)
|
||||
{
|
||||
Cascade::MakeFoam(slice0).SampleFoam(i_UndisplacedXZ, weight0, foam);
|
||||
}
|
||||
|
||||
#if d_Crest_AlbedoLod
|
||||
if (_Crest_AlbedoEnabled)
|
||||
{
|
||||
Cascade::MakeAlbedo(slice0).SampleAlbedo(i_UndisplacedXZ, weight0, albedo);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_Crest_ShadowLod
|
||||
if (_Crest_ShadowsEnabled)
|
||||
{
|
||||
Cascade::MakeShadow(slice0).SampleShadow(i_PositionWS.xz, weight0, shadow);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_Crest_SimpleTransparency || d_Crest_FoamBioluminescence
|
||||
#if !d_Crest_SimpleTransparency
|
||||
if (_Crest_FoamEnabled && _Crest_FoamBioluminescenceEnabled)
|
||||
#endif
|
||||
{
|
||||
Cascade::MakeDepth(slice0).SampleSignedDepthFromSeaLevelAndDistance(i_PositionWS.xz, weight0, waterDepth, shorelineDistance);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (weight1 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
Cascade::MakeAnimatedWaves(slice1).SampleNormals(i_UndisplacedXZ, weight1, o_NormalWS.xz, _determinant);
|
||||
if (_Crest_ApplyDisplacementNormals)
|
||||
{
|
||||
Cascade::MakeAnimatedWaves(slice1).SampleDisplacementNormal(i_UndisplacedXZ, weight1, o_NormalWS.xz, _determinant);
|
||||
}
|
||||
|
||||
#if d_Crest_CustomMesh && d_Crest_FlowLod
|
||||
Cascade::MakeFlow(slice1).SampleFlow(i_UndisplacedXZ, weight1, flowData);
|
||||
#endif
|
||||
|
||||
if (_Crest_FoamEnabled)
|
||||
{
|
||||
Cascade::MakeFoam(slice1).SampleFoam(i_UndisplacedXZ, weight1, foam);
|
||||
}
|
||||
|
||||
#if d_Crest_AlbedoLod
|
||||
if (_Crest_AlbedoEnabled)
|
||||
{
|
||||
Cascade::MakeAlbedo(slice1).SampleAlbedo(i_UndisplacedXZ, weight1, albedo);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_Crest_ShadowLod
|
||||
if (_Crest_ShadowsEnabled)
|
||||
{
|
||||
Cascade::MakeShadow(slice1).SampleShadow(i_PositionWS.xz, weight1, shadow);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_Crest_SimpleTransparency || d_Crest_FoamBioluminescence
|
||||
#if !d_Crest_SimpleTransparency
|
||||
if (_Crest_FoamEnabled && _Crest_FoamBioluminescenceEnabled)
|
||||
#endif
|
||||
{
|
||||
Cascade::MakeDepth(slice1).SampleSignedDepthFromSeaLevelAndDistance(i_PositionWS.xz, weight1, waterDepth, shorelineDistance);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Invert so shadows are black as we normally multiply this by lighting.
|
||||
@@ -191,99 +230,88 @@ void Fragment(m_Properties)
|
||||
|
||||
// Data that displays to the edge.
|
||||
// The default simulation value has been written to the border of the last slice.
|
||||
half3 absorption = 0.0; half3 scattering = 0.0;
|
||||
half3 absorption = _Crest_Absorption.xyz; half3 scattering = _Crest_Scattering.xyz;
|
||||
|
||||
#if d_Crest_AbsorptionLod || d_Crest_ScatteringLod
|
||||
{
|
||||
const float weight0 = (1.0 - (isLastLod ? 0.0 : i_LodAlpha)) * cascade0._Weight;
|
||||
const float weight1 = (1.0 - weight0) * cascade1._Weight;
|
||||
|
||||
#if d_Crest_ScatteringLod
|
||||
if (g_Crest_SampleScatteringSimulation)
|
||||
{
|
||||
scattering = 0.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_Crest_AbsorptionLod
|
||||
if (g_Crest_SampleAbsorptionSimulation)
|
||||
{
|
||||
absorption = 0.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (weight0 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
#if d_Crest_ScatteringLod
|
||||
if (g_Crest_SampleScatteringSimulation)
|
||||
{
|
||||
Cascade::MakeScattering(slice0).SampleScattering(i_UndisplacedXZ, weight0, scattering);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_Crest_AbsorptionLod
|
||||
if (g_Crest_SampleAbsorptionSimulation)
|
||||
{
|
||||
Cascade::MakeAbsorption(slice0).SampleAbsorption(i_UndisplacedXZ, weight0, absorption);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (weight1 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
#if d_Crest_ScatteringLod
|
||||
if (g_Crest_SampleScatteringSimulation)
|
||||
{
|
||||
Cascade::MakeScattering(slice1).SampleScattering(i_UndisplacedXZ, weight1, scattering);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_Crest_AbsorptionLod
|
||||
if (g_Crest_SampleAbsorptionSimulation)
|
||||
{
|
||||
Cascade::MakeAbsorption(slice1).SampleAbsorption(i_UndisplacedXZ, weight1, absorption);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!g_Crest_SampleScatteringSimulation)
|
||||
{
|
||||
scattering = _Crest_Scattering.xyz;
|
||||
}
|
||||
|
||||
if (!g_Crest_SampleAbsorptionSimulation)
|
||||
{
|
||||
absorption = _Crest_Absorption.xyz;
|
||||
}
|
||||
#if d_Crest_FlowLod
|
||||
#if !d_Crest_CustomMesh
|
||||
flowData = i_Flow;
|
||||
#endif
|
||||
const Flow flow = Flow::Make(flowData, g_Crest_Flow);
|
||||
#endif
|
||||
|
||||
// Determinant needs to be one when no waves.
|
||||
if (isLastLod)
|
||||
{
|
||||
_determinant += 1.0 - weight0;
|
||||
waterDepth = 10000.0;
|
||||
}
|
||||
|
||||
// Normal.
|
||||
{
|
||||
if (_Crest_NormalMapEnabled)
|
||||
{
|
||||
o_NormalWS.xz += SampleNormalMaps
|
||||
(
|
||||
#ifdef CREST_FLOW_ON
|
||||
flow,
|
||||
#if d_Transparent
|
||||
// Feather at intersection. Cannot be used for shadows since depth is not available.
|
||||
const float feather =
|
||||
#if d_Crest_SimpleTransparency
|
||||
saturate(waterDepth / 0.2);
|
||||
#else
|
||||
saturate((sceneZ - pixelZ) / 0.2);
|
||||
#endif
|
||||
#endif
|
||||
_Crest_NormalMapTiledTexture,
|
||||
_Crest_NormalMapStrength,
|
||||
i_UndisplacedXZ,
|
||||
i_LodAlpha,
|
||||
cascade0
|
||||
);
|
||||
}
|
||||
|
||||
o_NormalWS = normalize(o_NormalWS);
|
||||
|
||||
WaterNormal
|
||||
(
|
||||
i_WaterLevelDerivatives,
|
||||
i_ViewDirectionWS,
|
||||
_Crest_MinimumReflectionDirectionY,
|
||||
underwater,
|
||||
o_NormalWS
|
||||
);
|
||||
|
||||
o_NormalWS = normalize(o_NormalWS);
|
||||
|
||||
o_NormalWS.xz *= _Crest_NormalsStrengthOverall;
|
||||
o_NormalWS.y = lerp(1.0, o_NormalWS.y, _Crest_NormalsStrengthOverall);
|
||||
|
||||
if (underwater)
|
||||
{
|
||||
// Flip when underwater.
|
||||
o_NormalWS.xyz *= -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Default for opaque render type.
|
||||
float sceneDistance = 1000.0;
|
||||
float3 scenePositionWS = 0.0;
|
||||
|
||||
const half3 ambientLight = AmbientLight();
|
||||
const half3 extinction = VolumeExtinction(absorption, scattering);
|
||||
|
||||
float3 lightIntensity = 0.0;
|
||||
half3 lightDirection = 0.0;
|
||||
@@ -295,24 +323,110 @@ void Fragment(m_Properties)
|
||||
lightDirection
|
||||
);
|
||||
|
||||
half3 additionalLight = AdditionalLighting(i_PositionWS, i_ScreenPositionRaw, i_StaticLightMapUV);
|
||||
// Normal.
|
||||
{
|
||||
#if d_Crest_NormalMap
|
||||
if (_Crest_NormalMapEnabled)
|
||||
{
|
||||
const half2 normalMap = SampleNormalMaps
|
||||
(
|
||||
#if d_Crest_FlowLod
|
||||
flow,
|
||||
#endif
|
||||
_Crest_NormalMapTiledTexture,
|
||||
_Crest_NormalMapStrength,
|
||||
i_UndisplacedXZ,
|
||||
i_LodAlpha,
|
||||
cascade0
|
||||
);
|
||||
|
||||
half normalMapStrength = _Crest_NormalMapStrength;
|
||||
|
||||
if (_Crest_NormalMapTurbulenceEnabled)
|
||||
{
|
||||
normalMapStrength = NormalMapTurbulence
|
||||
(
|
||||
o_NormalWS,
|
||||
normalMap,
|
||||
normalMapStrength,
|
||||
_Crest_NormalMapTurbulenceCoverage,
|
||||
_Crest_NormalMapTurbulenceStrength,
|
||||
i_ViewDirectionWS,
|
||||
_determinant,
|
||||
g_Crest_WaterCenter.y + i_WaterLevelOffset,
|
||||
pixelZ,
|
||||
lightDirection
|
||||
);
|
||||
}
|
||||
|
||||
o_NormalWS.xz += normalMap * normalMapStrength;
|
||||
}
|
||||
#endif // d_Crest_NormalMap
|
||||
|
||||
// Handles normalization.
|
||||
WaterNormal
|
||||
(
|
||||
_Crest_NormalsStrengthOverall,
|
||||
i_Underwater,
|
||||
o_NormalWS
|
||||
);
|
||||
}
|
||||
|
||||
const half3 ambientLight = AmbientLight();
|
||||
half3 additionalLight = 0.0;
|
||||
#if d_Crest_AdditionalLights
|
||||
additionalLight = AdditionalLighting(i_PositionWS, i_ScreenPositionRaw, i_StaticLightMapUV, i_PositionSS, o_NormalWS);
|
||||
#endif
|
||||
|
||||
#if CREST_BIRP
|
||||
#ifndef USING_DIRECTIONAL_LIGHT
|
||||
// BIRP additional lights are the main light.
|
||||
lightIntensity *= max(k_Crest_AdditionalLightLerp, dot(o_NormalWS, lightDirection));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Default for opaque render type.
|
||||
float sceneDistance = 1000.0;
|
||||
float3 scenePositionWS = i_PositionWS;
|
||||
|
||||
#if d_Crest_SimpleTransparency
|
||||
sceneDistance = waterDepth;
|
||||
// Increase ray for grazing angles.
|
||||
sceneDistance += (1.0 - dot(i_ViewDirectionWS, o_NormalWS)) * waterDepth;
|
||||
scenePositionWS.y = i_PositionWS.y - waterDepth;
|
||||
// Cannot sample scene so go with average light.
|
||||
o_Emission = i_Underwater ? 0.0 : (0.5 * (lightIntensity + additionalLight + ambientLight) * INV_PI);
|
||||
#if CREST_HDRP
|
||||
o_Emission /= GetCurrentExposureMultiplier();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool caustics = !i_Underwater;
|
||||
|
||||
#if !d_Crest_SimpleTransparency
|
||||
#if d_Transparent
|
||||
#ifndef d_SkipRefraction
|
||||
bool caustics;
|
||||
RefractedScene
|
||||
(
|
||||
_Crest_RefractionStrength,
|
||||
1.000293, // air
|
||||
_Crest_RefractiveIndexOfWater,
|
||||
o_NormalWS,
|
||||
i_PositionWS,
|
||||
i_ScreenPosition.xy,
|
||||
i_ScreenPositionRaw,
|
||||
pixelZ,
|
||||
i_SceneColor,
|
||||
i_ViewDirectionWS,
|
||||
sceneZ,
|
||||
sceneRawZ,
|
||||
underwater,
|
||||
i_SceneZRaw,
|
||||
cascade0._Scale,
|
||||
i_LodAlpha,
|
||||
i_Underwater,
|
||||
_Crest_TotalInternalReflectionIntensity,
|
||||
o_Emission,
|
||||
sceneDistance,
|
||||
scenePositionWS,
|
||||
scenePositionSS,
|
||||
caustics
|
||||
);
|
||||
|
||||
@@ -329,45 +443,48 @@ void Fragment(m_Properties)
|
||||
#endif
|
||||
#endif // d_SkipRefraction
|
||||
#endif // d_Transparent
|
||||
#endif // d_Crest_SimpleTransparency
|
||||
|
||||
float refractedSeaLevel = g_Crest_WaterCenter.y;
|
||||
float3 refractedSurfacePosition = float3(0, refractedSeaLevel, 0);
|
||||
if (!underwater && slice1 < g_Crest_LodCount)
|
||||
{
|
||||
// Sample larger slice to avoid the first slice.
|
||||
float4 displacement = Cascade::MakeAnimatedWaves(slice1).Sample(scenePositionWS.xz);
|
||||
refractedSeaLevel = g_Crest_WaterCenter.y + displacement.w;
|
||||
refractedSurfacePosition = displacement.xyz;
|
||||
refractedSurfacePosition.y += refractedSeaLevel;
|
||||
}
|
||||
|
||||
#if d_Crest_OutScattering
|
||||
// Out-scattering.
|
||||
if (!underwater)
|
||||
if (!i_Underwater)
|
||||
{
|
||||
// Account for average extinction of light as it travels down through volume. Assume flat water as anything else would be expensive.
|
||||
half3 extinction = absorption.xyz + scattering.xyz;
|
||||
o_Emission *= exp(-extinction * max(0.0, refractedSeaLevel - scenePositionWS.y));
|
||||
// Account for extinction of light as it travels down through volume.
|
||||
o_Emission *= exp(-extinction * max(0.0, i_PositionWS.y - scenePositionWS.y));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_Transparent
|
||||
#ifndef d_SkipRefraction
|
||||
// Caustics
|
||||
if (_Crest_CausticsEnabled && !underwater && caustics)
|
||||
if (_Crest_CausticsEnabled && !i_Underwater && caustics)
|
||||
{
|
||||
half lightOcclusion = PrimaryLightShadows(scenePositionWS, positionSS);
|
||||
half lightOcclusion = 1.0;
|
||||
#if !d_Crest_SimpleTransparency
|
||||
lightOcclusion = PrimaryLightShadows(scenePositionWS, scenePositionSS);
|
||||
#endif
|
||||
|
||||
#if d_Crest_SimpleTransparency
|
||||
if (_Crest_RefractionStrength > 0.0)
|
||||
{
|
||||
// Gives a parallax like effect.
|
||||
const half3 ray = refract(-i_ViewDirectionWS, o_NormalWS, 1.0 / _Crest_RefractiveIndexOfWater) * _Crest_RefractionStrength;
|
||||
scenePositionWS += ray * waterDepth * 2.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
half blur = 0.0;
|
||||
#ifdef CREST_FLOW_ON
|
||||
#if d_Crest_FlowLod
|
||||
blur = _Crest_CausticsMotionBlur;
|
||||
#endif
|
||||
|
||||
o_Emission *= Caustics
|
||||
(
|
||||
#ifdef CREST_FLOW_ON
|
||||
#if d_Crest_FlowLod
|
||||
flow,
|
||||
#endif
|
||||
scenePositionWS,
|
||||
refractedSurfacePosition.y,
|
||||
i_PositionWS.y,
|
||||
lightIntensity,
|
||||
lightDirection,
|
||||
lightOcclusion,
|
||||
@@ -380,7 +497,7 @@ void Fragment(m_Properties)
|
||||
_Crest_CausticsDistortionTiledTexture,
|
||||
_Crest_CausticsDistortionStrength,
|
||||
blur,
|
||||
underwater
|
||||
_Crest_CausticsForceDistortion
|
||||
);
|
||||
}
|
||||
#endif // d_SkipRefraction
|
||||
@@ -404,7 +521,6 @@ void Fragment(m_Properties)
|
||||
}
|
||||
|
||||
// Volume Lighting
|
||||
const half3 extinction = VolumeExtinction(absorption, scattering);
|
||||
const half3 volumeOpacity = VolumeOpacity(extinction, sceneDistance);
|
||||
const half3 volumeLight = VolumeLighting
|
||||
(
|
||||
@@ -417,8 +533,10 @@ void Fragment(m_Properties)
|
||||
lightDirection,
|
||||
lightIntensity,
|
||||
additionalLight,
|
||||
_Crest_AdditionalLightsBlend,
|
||||
_Crest_AmbientTerm,
|
||||
_Crest_DirectTerm,
|
||||
_Crest_DirectTermAdditional,
|
||||
sss,
|
||||
_Crest_ShadowsAffectsAmbientFactor
|
||||
);
|
||||
@@ -431,15 +549,16 @@ void Fragment(m_Properties)
|
||||
(
|
||||
i_ViewDirectionWS,
|
||||
o_NormalWS,
|
||||
underwater,
|
||||
i_Underwater,
|
||||
1.0, // air
|
||||
_Crest_RefractiveIndexOfWater,
|
||||
_Crest_TotalInternalReflectionIntensity,
|
||||
_Crest_Fresnel,
|
||||
transmitted,
|
||||
reflected
|
||||
);
|
||||
|
||||
if (underwater)
|
||||
if (i_Underwater)
|
||||
{
|
||||
o_Emission *= transmitted;
|
||||
o_Emission += volumeLight * reflected;
|
||||
@@ -448,14 +567,20 @@ void Fragment(m_Properties)
|
||||
{
|
||||
o_Emission *= 1.0 - volumeOpacity;
|
||||
o_Emission += volumeLight * volumeOpacity;
|
||||
o_Emission *= transmitted;
|
||||
|
||||
if (_Crest_ApplyFresnelToVolumeLighting)
|
||||
{
|
||||
o_Emission *= transmitted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if _SPECULAR_SETUP
|
||||
// Specular
|
||||
{
|
||||
o_Specular = _Crest_Specular * reflected * shadow.y;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Smoothness
|
||||
{
|
||||
@@ -465,24 +590,26 @@ void Fragment(m_Properties)
|
||||
|
||||
// Occlusion
|
||||
{
|
||||
o_Occlusion = underwater ? _Crest_OcclusionUnderwater : _Crest_Occlusion;
|
||||
o_Occlusion = i_Underwater ? _Crest_OcclusionUnderwater : _Crest_Occlusion;
|
||||
}
|
||||
|
||||
// Planar Reflections
|
||||
#if d_Crest_PlanarReflections
|
||||
if (_Crest_PlanarReflectionsEnabled)
|
||||
{
|
||||
half4 reflection = PlanarReflection
|
||||
(
|
||||
_Crest_ReflectionTexture,
|
||||
sampler_Crest_ReflectionTexture,
|
||||
_Crest_ReflectionColorTexture,
|
||||
sampler_Crest_ReflectionColorTexture,
|
||||
_Crest_PlanarReflectionsIntensity,
|
||||
o_Smoothness,
|
||||
_Crest_PlanarReflectionsRoughness,
|
||||
pixelZ,
|
||||
o_NormalWS,
|
||||
_Crest_PlanarReflectionsDistortion,
|
||||
i_ViewDirectionWS,
|
||||
i_ScreenPosition.xy,
|
||||
underwater
|
||||
i_Underwater
|
||||
);
|
||||
|
||||
half alpha = reflection.a;
|
||||
@@ -491,13 +618,14 @@ void Fragment(m_Properties)
|
||||
// Results are darker than Unity's.
|
||||
o_Occlusion *= 1.0 - alpha;
|
||||
}
|
||||
#endif // d_Crest_PlanarReflections
|
||||
|
||||
// Foam
|
||||
if (_Crest_FoamEnabled)
|
||||
{
|
||||
half albedo = MultiScaleFoamAlbedo
|
||||
half2 albedo = MultiScaleFoamAlbedo
|
||||
(
|
||||
#ifdef CREST_FLOW_ON
|
||||
#if d_Crest_FlowLod
|
||||
flow,
|
||||
#endif
|
||||
_Crest_FoamTiledTexture,
|
||||
@@ -506,23 +634,24 @@ void Fragment(m_Properties)
|
||||
cascade0,
|
||||
cascade1,
|
||||
i_LodAlpha,
|
||||
i_UndisplacedXZ
|
||||
);
|
||||
|
||||
half2 normal = MultiScaleFoamNormal
|
||||
(
|
||||
#ifdef CREST_FLOW_ON
|
||||
flow,
|
||||
#endif
|
||||
_Crest_FoamTiledTexture,
|
||||
_Crest_FoamFeather,
|
||||
_Crest_FoamNormalStrength,
|
||||
foam,
|
||||
albedo,
|
||||
cascade0,
|
||||
cascade1,
|
||||
i_LodAlpha,
|
||||
i_UndisplacedXZ,
|
||||
_Crest_FoamBioluminescenceEnabled && _Crest_FoamBioluminescenceSparklesEnabled
|
||||
);
|
||||
|
||||
half2 normal = MultiScaleFoamNormal
|
||||
(
|
||||
#if d_Crest_FlowLod
|
||||
flow,
|
||||
#endif
|
||||
_Crest_FoamTiledTexture,
|
||||
_Crest_FoamFeather,
|
||||
foam,
|
||||
cascade0,
|
||||
cascade1,
|
||||
i_LodAlpha,
|
||||
i_UndisplacedXZ,
|
||||
_Crest_FoamNormalStrength,
|
||||
albedo.x,
|
||||
pixelZ
|
||||
);
|
||||
|
||||
@@ -530,13 +659,13 @@ void Fragment(m_Properties)
|
||||
|
||||
ApplyFoamToSurface
|
||||
(
|
||||
albedo,
|
||||
albedo.x,
|
||||
normal,
|
||||
intensity,
|
||||
_Crest_Occlusion,
|
||||
_Crest_FoamSmoothness,
|
||||
_Crest_Specular,
|
||||
underwater,
|
||||
i_Underwater,
|
||||
o_Albedo,
|
||||
o_NormalWS,
|
||||
o_Emission,
|
||||
@@ -546,92 +675,205 @@ void Fragment(m_Properties)
|
||||
);
|
||||
|
||||
// We will use this for shadow casting.
|
||||
foam = albedo;
|
||||
const half foamData = foam;
|
||||
foam = albedo.r;
|
||||
|
||||
#if d_Crest_FoamBioluminescence
|
||||
if (_Crest_FoamBioluminescenceEnabled)
|
||||
{
|
||||
half3 emission = FoamBioluminescence
|
||||
(
|
||||
foamData,
|
||||
albedo.r,
|
||||
_Crest_FoamBioluminescenceColor.rgb,
|
||||
_Crest_FoamBioluminescenceIntensity,
|
||||
_Crest_FoamBioluminescenceGlowCoverage,
|
||||
_Crest_FoamBioluminescenceGlowIntensity,
|
||||
_Crest_FoamBioluminescenceSparklesEnabled,
|
||||
albedo.y,
|
||||
_Crest_FoamBioluminescenceSparklesCoverage,
|
||||
_Crest_FoamBioluminescenceSparklesIntensity,
|
||||
_Crest_FoamBioluminescenceMaximumDepth,
|
||||
waterDepth
|
||||
);
|
||||
|
||||
emission *= _Crest_FoamBioluminescenceSeaLevelOnly ? saturate(1.0 - abs(i_WaterLevelOffset)) : 1.0;
|
||||
|
||||
#if d_Transparent
|
||||
// Apply feathering to avoid hardening the edge.
|
||||
emission *= feather * feather * feather;
|
||||
#endif
|
||||
|
||||
o_Emission += emission;
|
||||
}
|
||||
#endif // d_Crest_FoamBioluminescence
|
||||
}
|
||||
|
||||
// Albedo
|
||||
#if d_Crest_AlbedoLod
|
||||
if (_Crest_AlbedoEnabled)
|
||||
{
|
||||
const float foamMask = _Crest_AlbedoIgnoreFoam ? (1.0 - saturate(foam)) : 1.0;
|
||||
o_Albedo = lerp(o_Albedo, albedo.rgb, albedo.a * foamMask);
|
||||
o_Emission *= 1.0 - albedo.a * foamMask;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_Crest_SimpleTransparency
|
||||
o_Alpha = i_Underwater
|
||||
? 1.0 - transmitted
|
||||
: max(max(length(volumeOpacity), _Crest_TransparencyMinimumAlpha), max(foam, albedo.a));
|
||||
#endif
|
||||
|
||||
// Alpha
|
||||
{
|
||||
#ifndef CREST_SHADOWPASS
|
||||
#if d_Transparent
|
||||
// Feather at intersection. Cannot be used for shadows since depth is not available.
|
||||
o_Alpha = saturate((sceneZ - pixelZ) / 0.2);
|
||||
o_Alpha = min(o_Alpha, feather);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// This keyword works for all RPs despite BIRP having prefixes in serialised data.
|
||||
#if _ALPHATEST_ON
|
||||
#if d_Crest_AlphaTest
|
||||
#if CREST_SHADOWPASS
|
||||
o_Alpha = max(foam, albedo.a) - _Crest_ShadowCasterThreshold;
|
||||
o_Alpha = min(o_Alpha, max(foam, albedo.a) - _Crest_ShadowCasterThreshold);
|
||||
#endif
|
||||
|
||||
// Add 0.5 bias for LOD blending and texel resolution correction. This will help to
|
||||
// tighten and smooth clipped edges.
|
||||
o_Alpha -= ClipSurface(i_PositionWS.xz) > 0.5 ? 2.0 : 0.0;
|
||||
#endif // _ALPHATEST_ON
|
||||
#endif // d_Crest_AlphaTest
|
||||
|
||||
// Specular in HDRP is still affected outside the 0-1 alpha range.
|
||||
o_Alpha = min(o_Alpha, 1.0);
|
||||
}
|
||||
|
||||
if (!i_Underwater && _Crest_MinimumReflectionDirectionY > -1.0)
|
||||
{
|
||||
o_NormalWS = ApplyMinimumReflectionDirectionY(_Crest_MinimumReflectionDirectionY, i_ViewDirectionWS, o_NormalWS);
|
||||
}
|
||||
|
||||
SetUpFog
|
||||
(
|
||||
underwater,
|
||||
i_Underwater,
|
||||
i_PositionWS,
|
||||
1.0, // N/A: multiplier for fog nodes
|
||||
sceneDistance - negativeFog,
|
||||
pixelZ - i_NegativeFog,
|
||||
i_ViewDirectionWS,
|
||||
positionSS
|
||||
i_PositionSS
|
||||
);
|
||||
}
|
||||
|
||||
#if d_Crest_CustomMesh
|
||||
// Handles the last slice logic differently to match the mesh.
|
||||
// Clip surface for quad will not match chunks mesh at last LOD as collateral.
|
||||
#define PositionToSliceIndices MeshPositionToSliceIndices
|
||||
#endif
|
||||
|
||||
// IMPORTANT!
|
||||
// Do not branch on o_Alpha, as it is not robust. Rendering will break on stereo
|
||||
// rendering in the form of losing additional lighting and/or broken reflection
|
||||
// probe sampling. This is an issue with the shader compiler it seems.
|
||||
void Fragment(m_Properties(inout))
|
||||
{
|
||||
const float2 positionSS = i_ScreenPosition.xy * _ScreenSize.xy;
|
||||
|
||||
bool underwater = IsUnderWater(i_Facing, g_Crest_ForceUnderwater, positionSS);
|
||||
float sceneRawZ = i_SceneDepthRaw;
|
||||
float negativeFog = _ProjectionParams.y;
|
||||
|
||||
#if d_Crest_AlphaTest
|
||||
#if !d_Crest_SimpleTransparency
|
||||
#ifndef CREST_SHADOWPASS
|
||||
#if (CREST_PORTALS != 0)
|
||||
if (m_CrestPortal)
|
||||
{
|
||||
const float pixelRawZ = i_ScreenPositionRaw.z / i_ScreenPositionRaw.w;
|
||||
o_Alpha = Portal::EvaluateSurface(i_ScreenPosition.xy, pixelRawZ, i_PositionWS, underwater, sceneRawZ, negativeFog) ? -1.0 : 1.0;
|
||||
#ifndef SHADER_API_WEBGPU
|
||||
clip(o_Alpha);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint slice0;
|
||||
uint slice1;
|
||||
float alpha;
|
||||
|
||||
#if d_Crest_AlphaTest || d_Crest_CustomMesh
|
||||
PositionToSliceIndices(i_PositionWS.xz, 0, g_Crest_LodCount - 1, g_Crest_WaterScale, slice0, slice1, alpha);
|
||||
#endif
|
||||
|
||||
#if d_Crest_AlphaTest
|
||||
{
|
||||
const Cascade cascade0 = Cascade::Make(slice0);
|
||||
const Cascade cascade1 = Cascade::Make(slice1);
|
||||
const float weight0 = (1.0 - alpha) * cascade0._Weight;
|
||||
const float weight1 = (1.0 - weight0) * cascade1._Weight;
|
||||
|
||||
float clipSurface = 0.0;
|
||||
if (weight0 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
Cascade::MakeClip(slice0).SampleClip(i_PositionWS.xz, weight0, clipSurface);
|
||||
}
|
||||
if (weight1 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
Cascade::MakeClip(slice1).SampleClip(i_PositionWS.xz, weight1, clipSurface);
|
||||
}
|
||||
|
||||
// Add 0.5 bias for LOD blending and texel resolution correction. This will help to
|
||||
// tighten and smooth clipped edges.
|
||||
o_Alpha -= clipSurface > 0.5 ? 2.0 : 0.0;
|
||||
|
||||
#ifndef SHADER_API_WEBGPU
|
||||
clip(o_Alpha);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
#if !d_Crest_CustomMesh
|
||||
slice0 = _Crest_LodIndex;
|
||||
slice1 = _Crest_LodIndex + 1;
|
||||
alpha = i_LodAlpha;
|
||||
#endif
|
||||
|
||||
i_LodAlpha = alpha;
|
||||
|
||||
Fragment
|
||||
(
|
||||
m_Parameters,
|
||||
slice0,
|
||||
slice1,
|
||||
positionSS,
|
||||
underwater,
|
||||
sceneRawZ,
|
||||
negativeFog
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PosToSliceIndices
|
||||
#undef PosToSliceIndices
|
||||
#endif
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
#endif // SHADERGRAPH_PREVIEW
|
||||
|
||||
void Fragment_float(m_Properties)
|
||||
void Fragment_float(m_Properties(out))
|
||||
{
|
||||
#if SHADERGRAPH_PREVIEW
|
||||
o_Albedo = 0.0;
|
||||
o_NormalWS = half3(0.0, 1.0, 0.0);
|
||||
o_NormalWS = i_NormalWS;
|
||||
o_Specular = 0.0;
|
||||
o_Emission = 0.0;
|
||||
o_Smoothness = 0.7;
|
||||
o_Smoothness = 0.9;
|
||||
o_Occlusion = 1.0;
|
||||
o_Alpha = 1.0;
|
||||
#else // SHADERGRAPH_PREVIEW
|
||||
m_Crest::Fragment
|
||||
(
|
||||
i_UndisplacedXZ,
|
||||
i_LodAlpha,
|
||||
i_WaterLevelOffset,
|
||||
i_WaterLevelDerivatives,
|
||||
i_Flow,
|
||||
i_ViewDirectionWS,
|
||||
i_Facing,
|
||||
i_SceneColor,
|
||||
i_SceneDepthRaw,
|
||||
i_ScreenPosition,
|
||||
i_ScreenPositionRaw,
|
||||
i_PositionWS,
|
||||
i_PositionVS,
|
||||
i_StaticLightMapUV,
|
||||
o_Albedo,
|
||||
o_NormalWS,
|
||||
o_Specular,
|
||||
o_Emission,
|
||||
o_Smoothness,
|
||||
o_Occlusion,
|
||||
o_Alpha
|
||||
);
|
||||
#endif // SHADERGRAPH_PREVIEW
|
||||
|
||||
#if !SHADERGRAPH_PREVIEW
|
||||
m_Crest::Fragment(m_Parameters);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef m_Properties
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
float CalculateFresnelReflectionCoefficient(const float i_CosineTheta, const float i_RefractiveIndexOfAir, const float i_RefractiveIndexOfWater)
|
||||
float CalculateFresnelReflectionCoefficient(const float i_CosineTheta, const float i_RefractiveIndexOfAir, const float i_RefractiveIndexOfWater, const float i_Fresnel)
|
||||
{
|
||||
// Fresnel calculated using Schlick's approximation.
|
||||
// See: http://www.cs.virginia.edu/~jdl/bib/appearance/analytic%20models/schlick94b.pdf
|
||||
// Reflectance at facing angle.
|
||||
float R_0 = (i_RefractiveIndexOfAir - i_RefractiveIndexOfWater) / (i_RefractiveIndexOfAir + i_RefractiveIndexOfWater);
|
||||
R_0 *= R_0;
|
||||
const float R_theta = R_0 + (1.0 - R_0) * pow(max(0., 1.0 - i_CosineTheta), 5.0);
|
||||
const float R_theta = R_0 + (1.0 - R_0) * pow(max(0., 1.0 - i_CosineTheta), i_Fresnel);
|
||||
return R_theta;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ void ApplyReflectionUnderwater(
|
||||
const half3 i_NormalWS,
|
||||
const float i_RefractiveIndexOfAir,
|
||||
const float i_RefractiveIndexOfWater,
|
||||
const float i_Fresnel,
|
||||
out float o_LightTransmitted,
|
||||
out float o_LightReflected
|
||||
) {
|
||||
@@ -35,7 +36,7 @@ void ApplyReflectionUnderwater(
|
||||
// Have to calculate the incident angle of incoming light to water.
|
||||
// Surface based on how it would be refracted so as to hit the camera.
|
||||
const float cosIncomingAngle = cos(asin(clamp((i_RefractiveIndexOfWater * sin(acos(cosOutgoingAngle))) / i_RefractiveIndexOfAir, -1.0, 1.0)));
|
||||
const float reflectionCoefficient = CalculateFresnelReflectionCoefficient(cosIncomingAngle, i_RefractiveIndexOfAir, i_RefractiveIndexOfWater);
|
||||
const float reflectionCoefficient = CalculateFresnelReflectionCoefficient(cosIncomingAngle, i_RefractiveIndexOfAir, i_RefractiveIndexOfWater, i_Fresnel);
|
||||
o_LightTransmitted = (1.0 - reflectionCoefficient);
|
||||
o_LightTransmitted = max(o_LightTransmitted, 0.0);
|
||||
}
|
||||
@@ -44,7 +45,7 @@ void ApplyReflectionUnderwater(
|
||||
{
|
||||
// Angle of incident is angle of reflection.
|
||||
const float cosIncomingAngle = cosOutgoingAngle;
|
||||
const float reflectionCoefficient = CalculateFresnelReflectionCoefficient(cosIncomingAngle, i_RefractiveIndexOfAir, i_RefractiveIndexOfWater);
|
||||
const float reflectionCoefficient = CalculateFresnelReflectionCoefficient(cosIncomingAngle, i_RefractiveIndexOfAir, i_RefractiveIndexOfWater, i_Fresnel);
|
||||
o_LightReflected = reflectionCoefficient;
|
||||
}
|
||||
}
|
||||
@@ -57,15 +58,14 @@ void ApplyFresnel
|
||||
const float i_RefractiveIndexOfAir,
|
||||
const float i_RefractiveIndexOfWater,
|
||||
const float i_TirIntensity,
|
||||
const float i_Fresnel,
|
||||
out float o_LightTransmitted,
|
||||
out float o_LightReflected
|
||||
)
|
||||
{
|
||||
o_LightTransmitted = 1.0;
|
||||
|
||||
if (i_IsUnderwater)
|
||||
{
|
||||
ApplyReflectionUnderwater(i_ViewDirectionWS, i_NormalWS, i_RefractiveIndexOfAir, i_RefractiveIndexOfWater, o_LightTransmitted, o_LightReflected);
|
||||
ApplyReflectionUnderwater(i_ViewDirectionWS, i_NormalWS, i_RefractiveIndexOfAir, i_RefractiveIndexOfWater, i_Fresnel, o_LightTransmitted, o_LightReflected);
|
||||
// Limit how strong TIR is. Not sure if this is the best way but it seems to work gracefully.
|
||||
o_LightTransmitted = max(o_LightTransmitted, 1.0 - i_TirIntensity);
|
||||
o_LightReflected = min(o_LightReflected, i_TirIntensity);
|
||||
@@ -74,7 +74,8 @@ void ApplyFresnel
|
||||
{
|
||||
const float cosAngle = max(dot(i_NormalWS, i_ViewDirectionWS), 0.0);
|
||||
// Hardcode water IOR for above surface.
|
||||
o_LightReflected = CalculateFresnelReflectionCoefficient(cosAngle, i_RefractiveIndexOfAir, 1.33);
|
||||
o_LightReflected = CalculateFresnelReflectionCoefficient(cosAngle, i_RefractiveIndexOfAir, 1.33, i_Fresnel);
|
||||
o_LightTransmitted = 1.0 - o_LightReflected;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
// These are per cascade, set per chunk instance.
|
||||
CBUFFER_START(CrestChunkGeometryData)
|
||||
float _Crest_ChunkMeshScaleAlpha;
|
||||
float _Crest_ChunkMeshScaleAlphaSource;
|
||||
float _Crest_ChunkGeometryGridWidth;
|
||||
float _Crest_ChunkGeometryGridWidthSource;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
@@ -93,6 +91,22 @@ void SnapAndTransitionVertLayout(in const float i_meshScaleAlpha, in const Casca
|
||||
SnapAndTransitionVertLayout(UNITY_MATRIX_M, i_meshScaleAlpha, i_cascadeData0, i_geometryGridSize, io_worldPos, o_lodAlpha);
|
||||
}
|
||||
|
||||
// Fix precision errors at edges.
|
||||
void PatchVerticeLayout(const float2 i_ObjectPosition, const float2 i_CameraPosition, inout float2 io_PositionWS)
|
||||
{
|
||||
// Scale up by small "epsilon" to solve numerical issues. Expand slightly about tile center.
|
||||
// :WaterGridPrecisionErrors
|
||||
const float2 center = i_ObjectPosition;
|
||||
const float2 camera = abs(i_CameraPosition);
|
||||
// Scale "epsilon" by distance from zero. 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.
|
||||
io_PositionWS = lerp(center, io_PositionWS, lerp(1.0, 1.01, max(camera.x, camera.y) * 0.00001));
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
#endif // CREST_WATER_VERT_HELPERS_H
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c23f497aedede4290815c65dbfb8c41e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 092e2d3b5cf2b4befb63be63e99ea668
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,997 @@
|
||||
{
|
||||
"m_SGVersion": 3,
|
||||
"m_Type": "UnityEditor.ShaderGraph.GraphData",
|
||||
"m_ObjectId": "dc52d11acc8d40b988b7e8c972022334",
|
||||
"m_Properties": [
|
||||
{
|
||||
"m_Id": "7e9059fbe5bd45138f2798978fec8e1b"
|
||||
},
|
||||
{
|
||||
"m_Id": "d6811a4a90da4a1d90dd116b1166e9a7"
|
||||
},
|
||||
{
|
||||
"m_Id": "a504c5e2669b46a0806878bfc4e5fe6e"
|
||||
},
|
||||
{
|
||||
"m_Id": "657822dfe20e4bd7bbbc6c91b2559f83"
|
||||
},
|
||||
{
|
||||
"m_Id": "3aae6ac983e147359b4cad3288a29ddb"
|
||||
},
|
||||
{
|
||||
"m_Id": "9af11505f365474aa6e944c99d98ce7d"
|
||||
},
|
||||
{
|
||||
"m_Id": "79c65b5b5cd84bb0a37a4a4194cb788b"
|
||||
}
|
||||
],
|
||||
"m_Keywords": [],
|
||||
"m_Dropdowns": [],
|
||||
"m_CategoryData": [
|
||||
{
|
||||
"m_Id": "69e164e167b84918b199406f9b8e6e73"
|
||||
}
|
||||
],
|
||||
"m_Nodes": [
|
||||
{
|
||||
"m_Id": "306ab5d97971411ead8ce1393f42a506"
|
||||
},
|
||||
{
|
||||
"m_Id": "dccd939768524dfca8b5ae9341b86c38"
|
||||
},
|
||||
{
|
||||
"m_Id": "fda07576d7f341dc91fe8387cfa3c734"
|
||||
},
|
||||
{
|
||||
"m_Id": "aee239246fb14f14a6d36e34c4c9409f"
|
||||
},
|
||||
{
|
||||
"m_Id": "79217e2ae0ce456e95d9d7b3753b66b9"
|
||||
},
|
||||
{
|
||||
"m_Id": "d3ea3be5f6c346cd99299ee3715a57f9"
|
||||
},
|
||||
{
|
||||
"m_Id": "117ce02e4acf4112916c65582270c166"
|
||||
},
|
||||
{
|
||||
"m_Id": "74a7acf692b54b4c8635c91fe0731654"
|
||||
}
|
||||
],
|
||||
"m_GroupDatas": [],
|
||||
"m_StickyNoteDatas": [],
|
||||
"m_Edges": [
|
||||
{
|
||||
"m_OutputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "117ce02e4acf4112916c65582270c166"
|
||||
},
|
||||
"m_SlotId": 0
|
||||
},
|
||||
"m_InputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "306ab5d97971411ead8ce1393f42a506"
|
||||
},
|
||||
"m_SlotId": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"m_OutputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "74a7acf692b54b4c8635c91fe0731654"
|
||||
},
|
||||
"m_SlotId": 0
|
||||
},
|
||||
"m_InputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "306ab5d97971411ead8ce1393f42a506"
|
||||
},
|
||||
"m_SlotId": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"m_OutputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "79217e2ae0ce456e95d9d7b3753b66b9"
|
||||
},
|
||||
"m_SlotId": 0
|
||||
},
|
||||
"m_InputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "306ab5d97971411ead8ce1393f42a506"
|
||||
},
|
||||
"m_SlotId": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"m_OutputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "aee239246fb14f14a6d36e34c4c9409f"
|
||||
},
|
||||
"m_SlotId": 0
|
||||
},
|
||||
"m_InputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "306ab5d97971411ead8ce1393f42a506"
|
||||
},
|
||||
"m_SlotId": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"m_OutputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "d3ea3be5f6c346cd99299ee3715a57f9"
|
||||
},
|
||||
"m_SlotId": 0
|
||||
},
|
||||
"m_InputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "306ab5d97971411ead8ce1393f42a506"
|
||||
},
|
||||
"m_SlotId": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"m_OutputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "dccd939768524dfca8b5ae9341b86c38"
|
||||
},
|
||||
"m_SlotId": 0
|
||||
},
|
||||
"m_InputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "306ab5d97971411ead8ce1393f42a506"
|
||||
},
|
||||
"m_SlotId": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"m_OutputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "fda07576d7f341dc91fe8387cfa3c734"
|
||||
},
|
||||
"m_SlotId": 0
|
||||
},
|
||||
"m_InputSlot": {
|
||||
"m_Node": {
|
||||
"m_Id": "306ab5d97971411ead8ce1393f42a506"
|
||||
},
|
||||
"m_SlotId": 2
|
||||
}
|
||||
}
|
||||
],
|
||||
"m_VertexContext": {
|
||||
"m_Position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0
|
||||
},
|
||||
"m_Blocks": []
|
||||
},
|
||||
"m_FragmentContext": {
|
||||
"m_Position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0
|
||||
},
|
||||
"m_Blocks": []
|
||||
},
|
||||
"m_PreviewData": {
|
||||
"serializedMesh": {
|
||||
"m_SerializedMesh": "{\"mesh\":{\"instanceID\":0}}",
|
||||
"m_Guid": ""
|
||||
},
|
||||
"preventRotation": false
|
||||
},
|
||||
"m_Path": "Crest/Surface/Fragment",
|
||||
"m_GraphPrecision": 1,
|
||||
"m_PreviewMode": 2,
|
||||
"m_OutputNode": {
|
||||
"m_Id": "306ab5d97971411ead8ce1393f42a506"
|
||||
},
|
||||
"m_SubDatas": [],
|
||||
"m_ActiveTargets": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.PropertyNode",
|
||||
"m_ObjectId": "117ce02e4acf4112916c65582270c166",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "Property",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": -164.0,
|
||||
"y": 179.5,
|
||||
"width": 126.5,
|
||||
"height": 34.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "914b44103326464e8b55a8d65c402de4"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_Property": {
|
||||
"m_Id": "9af11505f365474aa6e944c99d98ce7d"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot",
|
||||
"m_ObjectId": "1aeebfec5a8a4655b6a85cc4aff7a1dc",
|
||||
"m_Id": 3,
|
||||
"m_DisplayName": "Specular",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Specular",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot",
|
||||
"m_ObjectId": "259210c0e86a4a4e9a9b189da396d21a",
|
||||
"m_Id": 1,
|
||||
"m_DisplayName": "Color",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Color",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot",
|
||||
"m_ObjectId": "2b75f1714337440c8ce94bce183a9e55",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Color",
|
||||
"m_SlotType": 1,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Out",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.SubGraphOutputNode",
|
||||
"m_ObjectId": "306ab5d97971411ead8ce1393f42a506",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "Output",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"width": 0.0,
|
||||
"height": 0.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "259210c0e86a4a4e9a9b189da396d21a"
|
||||
},
|
||||
{
|
||||
"m_Id": "6b3889ded68f4399b05b25ed7b2079f4"
|
||||
},
|
||||
{
|
||||
"m_Id": "1aeebfec5a8a4655b6a85cc4aff7a1dc"
|
||||
},
|
||||
{
|
||||
"m_Id": "cd595cbfa4314f1392f1cb929b93947e"
|
||||
},
|
||||
{
|
||||
"m_Id": "e75d6aef43794a5fa61bb21fcec7ef9f"
|
||||
},
|
||||
{
|
||||
"m_Id": "fe004333f6074821afe4321924775fbb"
|
||||
},
|
||||
{
|
||||
"m_Id": "d1b1ec100cfd4b0a8959c2fba3da0112"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"IsFirstSlotValid": true
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 1,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty",
|
||||
"m_ObjectId": "3aae6ac983e147359b4cad3288a29ddb",
|
||||
"m_Guid": {
|
||||
"m_GuidSerialized": "03c28b79-a1da-4276-8d2c-91a977859ad5"
|
||||
},
|
||||
"m_Name": "Smoothness",
|
||||
"m_DefaultRefNameVersion": 1,
|
||||
"m_RefNameGeneratedByDisplayName": "Smoothness",
|
||||
"m_DefaultReferenceName": "_Smoothness",
|
||||
"m_OverrideReferenceName": "",
|
||||
"m_GeneratePropertyBlock": true,
|
||||
"m_UseCustomSlotLabel": false,
|
||||
"m_CustomSlotLabel": "",
|
||||
"m_DismissedVersion": 0,
|
||||
"m_Precision": 0,
|
||||
"overrideHLSLDeclaration": false,
|
||||
"hlslDeclarationOverride": 0,
|
||||
"m_Hidden": false,
|
||||
"m_Value": 0.0,
|
||||
"m_FloatType": 0,
|
||||
"m_RangeValues": {
|
||||
"x": 0.0,
|
||||
"y": 1.0
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
|
||||
"m_ObjectId": "62b398277ad74c2e9c99f796aa93a891",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Smoothness",
|
||||
"m_SlotType": 1,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Out",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": 0.0,
|
||||
"m_DefaultValue": 0.0,
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 1,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Internal.Vector3ShaderProperty",
|
||||
"m_ObjectId": "657822dfe20e4bd7bbbc6c91b2559f83",
|
||||
"m_Guid": {
|
||||
"m_GuidSerialized": "c87cbf93-a5b2-4b0e-bd11-61f5452b1b8f"
|
||||
},
|
||||
"m_Name": "Emission",
|
||||
"m_DefaultRefNameVersion": 1,
|
||||
"m_RefNameGeneratedByDisplayName": "Emission",
|
||||
"m_DefaultReferenceName": "_Emission",
|
||||
"m_OverrideReferenceName": "",
|
||||
"m_GeneratePropertyBlock": true,
|
||||
"m_UseCustomSlotLabel": false,
|
||||
"m_CustomSlotLabel": "",
|
||||
"m_DismissedVersion": 0,
|
||||
"m_Precision": 0,
|
||||
"overrideHLSLDeclaration": false,
|
||||
"hlslDeclarationOverride": 0,
|
||||
"m_Hidden": false,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"w": 0.0
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.CategoryData",
|
||||
"m_ObjectId": "69e164e167b84918b199406f9b8e6e73",
|
||||
"m_Name": "",
|
||||
"m_ChildObjectList": [
|
||||
{
|
||||
"m_Id": "7e9059fbe5bd45138f2798978fec8e1b"
|
||||
},
|
||||
{
|
||||
"m_Id": "d6811a4a90da4a1d90dd116b1166e9a7"
|
||||
},
|
||||
{
|
||||
"m_Id": "a504c5e2669b46a0806878bfc4e5fe6e"
|
||||
},
|
||||
{
|
||||
"m_Id": "657822dfe20e4bd7bbbc6c91b2559f83"
|
||||
},
|
||||
{
|
||||
"m_Id": "3aae6ac983e147359b4cad3288a29ddb"
|
||||
},
|
||||
{
|
||||
"m_Id": "9af11505f365474aa6e944c99d98ce7d"
|
||||
},
|
||||
{
|
||||
"m_Id": "79c65b5b5cd84bb0a37a4a4194cb788b"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot",
|
||||
"m_ObjectId": "6b3889ded68f4399b05b25ed7b2079f4",
|
||||
"m_Id": 2,
|
||||
"m_DisplayName": "Normal",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Normal",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.PropertyNode",
|
||||
"m_ObjectId": "74a7acf692b54b4c8635c91fe0731654",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "Property",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": -142.5,
|
||||
"y": 213.5,
|
||||
"width": 105.0,
|
||||
"height": 34.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "7deef838b6744b40a3bacb0d96991f2f"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_Property": {
|
||||
"m_Id": "79c65b5b5cd84bb0a37a4a4194cb788b"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.PropertyNode",
|
||||
"m_ObjectId": "79217e2ae0ce456e95d9d7b3753b66b9",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "Property",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": -160.5,
|
||||
"y": 111.5,
|
||||
"width": 123.0,
|
||||
"height": 34.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "94eddae4a910492b81d2a10f9aa4b3ce"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_Property": {
|
||||
"m_Id": "657822dfe20e4bd7bbbc6c91b2559f83"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 1,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty",
|
||||
"m_ObjectId": "79c65b5b5cd84bb0a37a4a4194cb788b",
|
||||
"m_Guid": {
|
||||
"m_GuidSerialized": "3a9dc46c-6bfe-45f8-8b09-e890761dbd17"
|
||||
},
|
||||
"m_Name": "Alpha",
|
||||
"m_DefaultRefNameVersion": 1,
|
||||
"m_RefNameGeneratedByDisplayName": "Alpha",
|
||||
"m_DefaultReferenceName": "_Alpha",
|
||||
"m_OverrideReferenceName": "",
|
||||
"m_GeneratePropertyBlock": true,
|
||||
"m_UseCustomSlotLabel": false,
|
||||
"m_CustomSlotLabel": "",
|
||||
"m_DismissedVersion": 0,
|
||||
"m_Precision": 0,
|
||||
"overrideHLSLDeclaration": false,
|
||||
"hlslDeclarationOverride": 0,
|
||||
"m_Hidden": false,
|
||||
"m_Value": 0.0,
|
||||
"m_FloatType": 0,
|
||||
"m_RangeValues": {
|
||||
"x": 0.0,
|
||||
"y": 1.0
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
|
||||
"m_ObjectId": "7deef838b6744b40a3bacb0d96991f2f",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Alpha",
|
||||
"m_SlotType": 1,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Out",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": 0.0,
|
||||
"m_DefaultValue": 0.0,
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 1,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Internal.Vector3ShaderProperty",
|
||||
"m_ObjectId": "7e9059fbe5bd45138f2798978fec8e1b",
|
||||
"m_Guid": {
|
||||
"m_GuidSerialized": "550c25ce-1870-45ea-a63d-ed7249d6bfc3"
|
||||
},
|
||||
"m_Name": "Color",
|
||||
"m_DefaultRefNameVersion": 1,
|
||||
"m_RefNameGeneratedByDisplayName": "Color",
|
||||
"m_DefaultReferenceName": "_Color",
|
||||
"m_OverrideReferenceName": "",
|
||||
"m_GeneratePropertyBlock": true,
|
||||
"m_UseCustomSlotLabel": false,
|
||||
"m_CustomSlotLabel": "",
|
||||
"m_DismissedVersion": 0,
|
||||
"m_Precision": 0,
|
||||
"overrideHLSLDeclaration": false,
|
||||
"hlslDeclarationOverride": 0,
|
||||
"m_Hidden": false,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"w": 0.0
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot",
|
||||
"m_ObjectId": "8e3e2614b2d844848527e0bf103cda9f",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Normal",
|
||||
"m_SlotType": 1,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Out",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
|
||||
"m_ObjectId": "914b44103326464e8b55a8d65c402de4",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Occlusion",
|
||||
"m_SlotType": 1,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Out",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": 0.0,
|
||||
"m_DefaultValue": 0.0,
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot",
|
||||
"m_ObjectId": "94eddae4a910492b81d2a10f9aa4b3ce",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Emission",
|
||||
"m_SlotType": 1,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Out",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 1,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty",
|
||||
"m_ObjectId": "9af11505f365474aa6e944c99d98ce7d",
|
||||
"m_Guid": {
|
||||
"m_GuidSerialized": "9b1b639c-8d8a-4493-800e-3b16c796d901"
|
||||
},
|
||||
"m_Name": "Occlusion",
|
||||
"m_DefaultRefNameVersion": 1,
|
||||
"m_RefNameGeneratedByDisplayName": "Occlusion",
|
||||
"m_DefaultReferenceName": "_Occlusion",
|
||||
"m_OverrideReferenceName": "",
|
||||
"m_GeneratePropertyBlock": true,
|
||||
"m_UseCustomSlotLabel": false,
|
||||
"m_CustomSlotLabel": "",
|
||||
"m_DismissedVersion": 0,
|
||||
"m_Precision": 0,
|
||||
"overrideHLSLDeclaration": false,
|
||||
"hlslDeclarationOverride": 0,
|
||||
"m_Hidden": false,
|
||||
"m_Value": 0.0,
|
||||
"m_FloatType": 0,
|
||||
"m_RangeValues": {
|
||||
"x": 0.0,
|
||||
"y": 1.0
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 1,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Internal.Vector3ShaderProperty",
|
||||
"m_ObjectId": "a504c5e2669b46a0806878bfc4e5fe6e",
|
||||
"m_Guid": {
|
||||
"m_GuidSerialized": "a0454ac6-fe90-4f58-8357-c64bf491ecc8"
|
||||
},
|
||||
"m_Name": "Specular",
|
||||
"m_DefaultRefNameVersion": 1,
|
||||
"m_RefNameGeneratedByDisplayName": "Specular",
|
||||
"m_DefaultReferenceName": "_Specular",
|
||||
"m_OverrideReferenceName": "",
|
||||
"m_GeneratePropertyBlock": true,
|
||||
"m_UseCustomSlotLabel": false,
|
||||
"m_CustomSlotLabel": "",
|
||||
"m_DismissedVersion": 0,
|
||||
"m_Precision": 0,
|
||||
"overrideHLSLDeclaration": false,
|
||||
"hlslDeclarationOverride": 0,
|
||||
"m_Hidden": false,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"w": 0.0
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.PropertyNode",
|
||||
"m_ObjectId": "aee239246fb14f14a6d36e34c4c9409f",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "Property",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": -160.5,
|
||||
"y": 77.5,
|
||||
"width": 123.0,
|
||||
"height": 34.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "c266950bb3ba42f6afe7ea63308a0ad4"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_Property": {
|
||||
"m_Id": "a504c5e2669b46a0806878bfc4e5fe6e"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot",
|
||||
"m_ObjectId": "c266950bb3ba42f6afe7ea63308a0ad4",
|
||||
"m_Id": 0,
|
||||
"m_DisplayName": "Specular",
|
||||
"m_SlotType": 1,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Out",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot",
|
||||
"m_ObjectId": "cd595cbfa4314f1392f1cb929b93947e",
|
||||
"m_Id": 4,
|
||||
"m_DisplayName": "Emission",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Emission",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_DefaultValue": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
|
||||
"m_ObjectId": "d1b1ec100cfd4b0a8959c2fba3da0112",
|
||||
"m_Id": 7,
|
||||
"m_DisplayName": "Alpha",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Alpha",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": 0.0,
|
||||
"m_DefaultValue": 0.0,
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.PropertyNode",
|
||||
"m_ObjectId": "d3ea3be5f6c346cd99299ee3715a57f9",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "Property",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": -177.5,
|
||||
"y": 145.5,
|
||||
"width": 140.0,
|
||||
"height": 34.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "62b398277ad74c2e9c99f796aa93a891"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_Property": {
|
||||
"m_Id": "3aae6ac983e147359b4cad3288a29ddb"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 1,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Internal.Vector3ShaderProperty",
|
||||
"m_ObjectId": "d6811a4a90da4a1d90dd116b1166e9a7",
|
||||
"m_Guid": {
|
||||
"m_GuidSerialized": "32196100-75e9-4862-a1f5-ad8a050bcb34"
|
||||
},
|
||||
"m_Name": "Normal",
|
||||
"m_DefaultRefNameVersion": 1,
|
||||
"m_RefNameGeneratedByDisplayName": "Normal",
|
||||
"m_DefaultReferenceName": "_Normal",
|
||||
"m_OverrideReferenceName": "",
|
||||
"m_GeneratePropertyBlock": true,
|
||||
"m_UseCustomSlotLabel": false,
|
||||
"m_CustomSlotLabel": "",
|
||||
"m_DismissedVersion": 0,
|
||||
"m_Precision": 0,
|
||||
"overrideHLSLDeclaration": false,
|
||||
"hlslDeclarationOverride": 0,
|
||||
"m_Hidden": false,
|
||||
"m_Value": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"w": 0.0
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.PropertyNode",
|
||||
"m_ObjectId": "dccd939768524dfca8b5ae9341b86c38",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "Property",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": -142.5,
|
||||
"y": 9.5,
|
||||
"width": 105.0,
|
||||
"height": 34.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "2b75f1714337440c8ce94bce183a9e55"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_Property": {
|
||||
"m_Id": "7e9059fbe5bd45138f2798978fec8e1b"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
|
||||
"m_ObjectId": "e75d6aef43794a5fa61bb21fcec7ef9f",
|
||||
"m_Id": 5,
|
||||
"m_DisplayName": "Smoothness",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Smoothness",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": 0.0,
|
||||
"m_DefaultValue": 0.0,
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.PropertyNode",
|
||||
"m_ObjectId": "fda07576d7f341dc91fe8387cfa3c734",
|
||||
"m_Group": {
|
||||
"m_Id": ""
|
||||
},
|
||||
"m_Name": "Property",
|
||||
"m_DrawState": {
|
||||
"m_Expanded": true,
|
||||
"m_Position": {
|
||||
"serializedVersion": "2",
|
||||
"x": -152.0,
|
||||
"y": 43.5,
|
||||
"width": 114.5,
|
||||
"height": 34.0
|
||||
}
|
||||
},
|
||||
"m_Slots": [
|
||||
{
|
||||
"m_Id": "8e3e2614b2d844848527e0bf103cda9f"
|
||||
}
|
||||
],
|
||||
"synonyms": [],
|
||||
"m_Precision": 0,
|
||||
"m_PreviewExpanded": true,
|
||||
"m_DismissedVersion": 0,
|
||||
"m_PreviewMode": 0,
|
||||
"m_CustomColors": {
|
||||
"m_SerializableColors": []
|
||||
},
|
||||
"m_Property": {
|
||||
"m_Id": "d6811a4a90da4a1d90dd116b1166e9a7"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"m_SGVersion": 0,
|
||||
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
|
||||
"m_ObjectId": "fe004333f6074821afe4321924775fbb",
|
||||
"m_Id": 6,
|
||||
"m_DisplayName": "Occlusion",
|
||||
"m_SlotType": 0,
|
||||
"m_Hidden": false,
|
||||
"m_ShaderOutputName": "Occlusion",
|
||||
"m_StageCapability": 3,
|
||||
"m_Value": 0.0,
|
||||
"m_DefaultValue": 0.0,
|
||||
"m_Labels": []
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae86d543ea8a2487e931ca754792c4c0
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 11500000, guid: 60072b568d64c40a485e0fc55012dc9f, type: 3}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#ifndef d_WaveHarmonic_Crest_SurfaceKeywords
|
||||
#define d_WaveHarmonic_Crest_SurfaceKeywords
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Keywords.hlsl"
|
||||
|
||||
#define d_Crest_AlphaTest defined(_ALPHATEST_ON)
|
||||
#define d_Crest_MotionVectors defined(_TRANSPARENT_WRITES_MOTION_VEC)
|
||||
|
||||
#define d_Crest_CustomMesh defined(_CREST_CUSTOM_MESH)
|
||||
|
||||
#define d_Crest_AdditionalLights CREST_ADDITIONAL_LIGHTS
|
||||
#define d_Crest_CausticsForceDistortion CREST_CAUSTICS_FORCE_DISTORTION
|
||||
#define d_Crest_FoamBioluminescence CREST_FOAM_BIOLUMINESCENCE
|
||||
#define d_Crest_FoamMultiScale CREST_FOAM_SAMPLING_MULTI_SCALE
|
||||
#define d_Crest_FoamStochastic CREST_FOAM_SAMPLING_STOCHASTIC
|
||||
#define d_Crest_NormalMap CREST_NORMAL_MAPS
|
||||
#define d_Crest_SimpleTransparency CREST_SIMPLE_TRANSPARENCY
|
||||
#define d_Crest_PlanarReflections CREST_PLANAR_REFLECTIONS
|
||||
#define d_Crest_PlanarReflectionsApplySmoothness CREST_PLANAR_REFLECTIONS_APPLY_SMOOTHNESS
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d4fdd4ba0e96485c93d748132deef6a
|
||||
ShaderIncludeImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -5,6 +5,7 @@
|
||||
#define CREST_WATER_NORMAL_H
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Texture.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Flow.hlsl"
|
||||
@@ -13,12 +14,43 @@
|
||||
#include "Packages/com.waveharmonic.crest.shifting-origin/Runtime/Shaders/ShiftingOrigin.hlsl"
|
||||
#endif
|
||||
|
||||
#if _CREST_CUSTOM_MESH
|
||||
float4 _Crest_NormalMapParameters[MAX_LOD_COUNT];
|
||||
#define _Crest_ChunkNormalMapParameters _Crest_NormalMapParameters[i_CascadeData._IndexI]
|
||||
#else
|
||||
// These are per cascade, set per chunk instance.
|
||||
float _Crest_ChunkFarNormalsWeight;
|
||||
float2 _Crest_ChunkNormalScrollSpeed;
|
||||
#define _Crest_ChunkNormalMapParameters float3(_Crest_ChunkNormalScrollSpeed, _Crest_ChunkFarNormalsWeight)
|
||||
#endif
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
// Limit how close to horizontal reflection ray can get, useful to avoid unsightly below-horizon reflections.
|
||||
half3 ApplyMinimumReflectionDirectionY
|
||||
(
|
||||
const half i_MinimumReflectionDirectionY,
|
||||
const half3 i_ViewDirectionWS,
|
||||
const half3 i_NormalWS
|
||||
)
|
||||
{
|
||||
half3 normal = i_NormalWS;
|
||||
|
||||
float3 refl = reflect(-i_ViewDirectionWS, normal);
|
||||
if (refl.y < i_MinimumReflectionDirectionY)
|
||||
{
|
||||
// Find the normal that keeps the reflection direction above the horizon. Compute
|
||||
// the reflection dir that does work, normalize it, and then normal is half vector
|
||||
// between this good reflection direction and view direction.
|
||||
float3 FL = refl;
|
||||
FL.y = i_MinimumReflectionDirectionY;
|
||||
FL = normalize(FL);
|
||||
normal = normalize(FL + i_ViewDirectionWS);
|
||||
}
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
half2 SampleNormalMaps
|
||||
(
|
||||
const TiledTexture i_NormalMap,
|
||||
@@ -35,28 +67,33 @@ half2 SampleNormalMaps
|
||||
worldXZUndisplaced -= ShiftingOriginOffset(i_NormalMap, i_CascadeData);
|
||||
#endif
|
||||
|
||||
const float3 parameters = _Crest_ChunkNormalMapParameters.xyz;
|
||||
const float2 speed = parameters.xy;
|
||||
const float farWeight = parameters.z;
|
||||
|
||||
const float2 v0 = float2(0.94, 0.34), v1 = float2(-0.85, -0.53);
|
||||
float scale = i_NormalMap._scale * i_CascadeData._Scale / 10.0;
|
||||
const float spdmulL = _Crest_ChunkNormalScrollSpeed.x * i_NormalMap._speed;
|
||||
float scale = i_NormalMap._scale * i_CascadeData._Scale * 0.1;
|
||||
const float time = i_NormalMap._speed * g_Crest_Time;
|
||||
const float spdmulL = speed.x * time;
|
||||
half2 norm =
|
||||
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v0 * g_Crest_Time * spdmulL) / scale)).xy +
|
||||
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v1 * g_Crest_Time * spdmulL) / scale)).xy;
|
||||
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v0 * spdmulL) / scale)).xy +
|
||||
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v1 * spdmulL) / scale)).xy;
|
||||
|
||||
// blend in next higher scale of normals to obtain continuity
|
||||
const half nblend = i_LodAlpha * _Crest_ChunkFarNormalsWeight;
|
||||
const half nblend = i_LodAlpha * farWeight;
|
||||
if (nblend > 0.001)
|
||||
{
|
||||
// next lod level
|
||||
scale *= 2.0;
|
||||
const float spdmulH = _Crest_ChunkNormalScrollSpeed.y * i_NormalMap._speed;
|
||||
const float spdmulH = speed.y * time;
|
||||
norm = lerp(norm,
|
||||
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v0 * g_Crest_Time * spdmulH) / scale)).xy +
|
||||
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v1 * g_Crest_Time * spdmulH) / scale)).xy,
|
||||
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v0 * spdmulH) / scale)).xy +
|
||||
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v1 * spdmulH) / scale)).xy,
|
||||
nblend);
|
||||
}
|
||||
|
||||
// approximate combine of normals. would be better if normals applied in local frame.
|
||||
return i_Strength * norm;
|
||||
return norm;
|
||||
}
|
||||
|
||||
half2 SampleNormalMaps
|
||||
@@ -86,42 +123,66 @@ half2 SampleNormalMaps
|
||||
) * i_Flow._Weight1;
|
||||
}
|
||||
|
||||
half NormalMapTurbulence
|
||||
(
|
||||
const half3 i_NormalWS,
|
||||
const half2 i_NormalMap,
|
||||
const half i_NormalMapStrength,
|
||||
const half i_Coverage,
|
||||
const half i_Strength,
|
||||
const half3 i_ViewDirectionWS,
|
||||
const half i_Determinant,
|
||||
const half i_WaterLevel,
|
||||
const float i_PixelZ,
|
||||
const half3 i_PrimaryLightDirection
|
||||
)
|
||||
{
|
||||
half strength = i_NormalMapStrength;
|
||||
|
||||
if (saturate(i_Coverage - i_Determinant) > 0)
|
||||
{
|
||||
// Add boosted normal map.
|
||||
half3 normal = i_NormalWS;
|
||||
normal.xz += i_NormalMap * i_Strength;
|
||||
normal = normalize(normal);
|
||||
|
||||
// Increase normal map strength only if "sparkle".
|
||||
if (dot(normal, normalize(i_ViewDirectionWS + i_PrimaryLightDirection)) >= 0.99)
|
||||
{
|
||||
// Height (100m) & distance (2m) cull. Looks odd up close and degrades up high.
|
||||
const half cull = max(saturate(abs(_WorldSpaceCameraPos.y - i_WaterLevel) * 0.01), 1.0 - saturate(i_PixelZ * 0.5));
|
||||
strength = lerp(i_Strength, strength, cull);
|
||||
}
|
||||
}
|
||||
|
||||
return strength;
|
||||
}
|
||||
|
||||
void WaterNormal
|
||||
(
|
||||
const float2 i_WaterLevelDerivatives,
|
||||
const half3 i_ViewDirectionWS,
|
||||
const half i_MinimumReflectionDirectionY,
|
||||
const half i_Strength,
|
||||
const bool i_Underwater,
|
||||
inout half3 io_NormalWS
|
||||
)
|
||||
{
|
||||
// Account for water level changes which change angle of water surface, impacting normal.
|
||||
io_NormalWS.xz += -i_WaterLevelDerivatives;
|
||||
|
||||
// Finalise normal
|
||||
io_NormalWS = normalize(io_NormalWS);
|
||||
|
||||
if (i_Underwater)
|
||||
if (i_Strength < 1.0)
|
||||
{
|
||||
return;
|
||||
io_NormalWS.xz *= i_Strength;
|
||||
io_NormalWS.y = lerp(1.0, io_NormalWS.y, i_Strength);
|
||||
}
|
||||
|
||||
// Limit how close to horizontal reflection ray can get, useful to avoid unsightly below-horizon reflections.
|
||||
if (i_Underwater)
|
||||
{
|
||||
float3 refl = reflect(-i_ViewDirectionWS, io_NormalWS);
|
||||
if (refl.y < i_MinimumReflectionDirectionY)
|
||||
{
|
||||
// Find the normal that keeps the reflection direction above the horizon. Compute
|
||||
// the reflection dir that does work, normalize it, and then normal is half vector
|
||||
// between this good reflection direction and view direction.
|
||||
float3 FL = refl;
|
||||
FL.y = i_MinimumReflectionDirectionY;
|
||||
FL = normalize(FL);
|
||||
io_NormalWS = normalize(FL + i_ViewDirectionWS);
|
||||
}
|
||||
// Flip when underwater.
|
||||
io_NormalWS.xyz *= -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,12 +4,25 @@
|
||||
#ifndef CREST_WATER_REFLECTION_H
|
||||
#define CREST_WATER_REFLECTION_H
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Keywords.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Utility.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Helpers.hlsl"
|
||||
|
||||
float _Crest_ReflectionOverscan;
|
||||
float4 _Crest_ReflectionPositionNormal[2];
|
||||
Texture2DArray _Crest_ReflectionTexture;
|
||||
SamplerState sampler_Crest_ReflectionTexture;
|
||||
float4x4 _Crest_ReflectionMatrixIVP[2];
|
||||
float4x4 _Crest_ReflectionMatrixV[2];
|
||||
Texture2DArray _Crest_ReflectionColorTexture;
|
||||
SamplerState sampler_Crest_ReflectionColorTexture;
|
||||
Texture2DArray _Crest_ReflectionDepthTexture;
|
||||
|
||||
// Try and use already defined samplers.
|
||||
#if defined(CREST_HDRP) && defined(SHADERCONFIG_CS_HLSL) && defined(UNITY_SHADER_VARIABLES_INCLUDED)
|
||||
#define sampler_Crest_point_clamp s_point_clamp_sampler
|
||||
#else
|
||||
SamplerState sampler_Crest_point_clamp;
|
||||
#endif
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
@@ -20,6 +33,7 @@ half4 PlanarReflection
|
||||
const half i_Intensity,
|
||||
const half i_Smoothness,
|
||||
const half i_Roughness,
|
||||
const float i_SurfaceDepth,
|
||||
const half3 i_NormalWS,
|
||||
const half i_NormalStrength,
|
||||
const half3 i_ViewDirectionWS,
|
||||
@@ -27,6 +41,8 @@ half4 PlanarReflection
|
||||
const bool i_Underwater
|
||||
)
|
||||
{
|
||||
const uint slice = i_Underwater ? 1 : 0;
|
||||
|
||||
half3 planeNormal = half3(0.0, i_Underwater ? -1.0 : 1.0, 0.0);
|
||||
half3 reflected = reflect(-i_ViewDirectionWS, lerp(planeNormal, i_NormalWS, i_NormalStrength));
|
||||
reflected.y = -reflected.y;
|
||||
@@ -38,19 +54,52 @@ half4 PlanarReflection
|
||||
|
||||
float2 positionNDC = positionCS.xy * rcp(positionCS.w) * 0.5 + 0.5;
|
||||
|
||||
// Overscan.
|
||||
positionNDC.xy -= 0.5;
|
||||
positionNDC.xy *= _Crest_ReflectionOverscan;
|
||||
positionNDC.xy += 0.5;
|
||||
|
||||
// Cancel out distortion if out of bounds. We could make this nicer by doing an edge fade but the improvement is
|
||||
// barely noticeable. Edge fade requires recalculating the above a second time.
|
||||
const float4 positionAndNormal = _Crest_ReflectionPositionNormal[slice];
|
||||
|
||||
if (dot(positionNDC - positionAndNormal.xy, positionAndNormal.zw) < 0.0)
|
||||
{
|
||||
float4 positionAndNormal = _Crest_ReflectionPositionNormal[i_Underwater];
|
||||
if (dot(positionNDC - positionAndNormal.xy, positionAndNormal.zw) < 0.0)
|
||||
if (i_Underwater)
|
||||
{
|
||||
positionNDC = lerp(i_PositionNDC, positionNDC, 0.25);
|
||||
float2 ndc = i_PositionNDC;
|
||||
ndc.xy -= 0.5;
|
||||
ndc.xy *= _Crest_ReflectionOverscan;
|
||||
ndc.xy += 0.5;
|
||||
|
||||
positionNDC = lerp(ndc, positionNDC, 0.25);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Below horizon sample!
|
||||
// There are still some bad samples, but they are very minor.
|
||||
const half2 hypotenuse = positionAndNormal.xy - positionNDC;
|
||||
const half angle = acos(saturate(dot(positionAndNormal.zw, normalize(hypotenuse))));
|
||||
const half adjacentLength = (cos(angle) * length(hypotenuse));
|
||||
|
||||
positionNDC += (positionAndNormal.zw * adjacentLength) / _Crest_ReflectionOverscan;
|
||||
}
|
||||
}
|
||||
|
||||
const half roughness = PerceptualSmoothnessToPerceptualRoughness(i_Smoothness);
|
||||
const half level = PerceptualRoughnessToMipmapLevel(roughness, i_Roughness);
|
||||
half4 reflection = i_ReflectionsTexture.SampleLevel(sampler_Crest_ReflectionTexture, float3(positionNDC, i_Underwater), level);
|
||||
half4 reflection;
|
||||
|
||||
#if d_Crest_PlanarReflectionsApplySmoothness
|
||||
if (_Crest_PlanarReflectionsApplySmoothness)
|
||||
{
|
||||
const half roughness = PerceptualSmoothnessToPerceptualRoughness(i_Smoothness);
|
||||
half level = PerceptualRoughnessToMipmapLevel(roughness, i_Roughness);
|
||||
reflection = i_ReflectionsTexture.SampleLevel(sampler_Crest_ReflectionColorTexture, float3(positionNDC, i_Underwater), level);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
reflection = i_ReflectionsTexture.SampleLevel(sampler_Crest_point_clamp, float3(positionNDC, i_Underwater), 0.0);
|
||||
}
|
||||
|
||||
// If more than four layers are used on the terrain, they will appear black if HDR
|
||||
// is enabled on the planar reflection camera. Alpha is probably a negative value.
|
||||
@@ -58,6 +107,21 @@ half4 PlanarReflection
|
||||
|
||||
reflection.a *= i_Intensity;
|
||||
|
||||
// Mitigate leaks.
|
||||
{
|
||||
// TODO: calculate linear depth from device depth directly. First attempt failed.
|
||||
// Most effective when surface is smooth due to mip-maps. Surprisingly effective
|
||||
// even when rough.
|
||||
const float rRawDepth = _Crest_ReflectionDepthTexture.SampleLevel(sampler_Crest_point_clamp, float3(positionNDC, i_Underwater), 0).r;
|
||||
const float3 rPositionWS = Utility::SafeComputeWorldSpacePosition(positionNDC, rRawDepth, _Crest_ReflectionMatrixIVP[slice]);
|
||||
const float rDepth = LinearEyeDepth(rPositionWS, _Crest_ReflectionMatrixV[slice]);
|
||||
|
||||
if (rRawDepth > 0.0 && rDepth <= i_SurfaceDepth)
|
||||
{
|
||||
reflection.a = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
return reflection;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#ifndef CREST_WATER_REFRACTION_H
|
||||
#define CREST_WATER_REFRACTION_H
|
||||
|
||||
#if !d_Crest_SimpleTransparency
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl"
|
||||
@@ -18,91 +20,144 @@
|
||||
#define FoveatedRemapLinearToNonUniform(uv) uv
|
||||
#endif
|
||||
|
||||
#if (UNITY_VERSION < 60000000) || !defined(CREST_URP)
|
||||
float4 _CameraDepthTexture_TexelSize;
|
||||
#endif
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
float2 GetRefractionCoordinates(const half3 i_View, const half3 i_Normal, const float3 i_Position, const half i_IOR, const half i_Strength)
|
||||
{
|
||||
float3 position = i_Position;
|
||||
|
||||
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
|
||||
position -= _WorldSpaceCameraPos;
|
||||
#endif
|
||||
|
||||
const half3 ray = refract(-i_View, i_Normal, i_IOR) * i_Strength;
|
||||
float2 uv = ComputeNormalizedDeviceCoordinates(position + ray, UNITY_MATRIX_VP);
|
||||
|
||||
#if CREST_HDRP
|
||||
// Prevent artifacts at edge. Maybe because depth is an atlas for HDRP.
|
||||
uv = clamp(uv, _CameraDepthTexture_TexelSize.xy, 1.0 - _CameraDepthTexture_TexelSize.xy);
|
||||
#endif
|
||||
|
||||
return FoveatedRemapLinearToNonUniform(uv);
|
||||
}
|
||||
|
||||
// We take the unrefracted scene colour as input because having a Scene Colour node in the graph
|
||||
// appears to be necessary to ensure the scene colours are bound?
|
||||
void RefractedScene
|
||||
(
|
||||
const half i_RefractionStrength,
|
||||
const half i_AirIOR,
|
||||
const half i_WaterIOR,
|
||||
const half3 i_NormalWS,
|
||||
const float3 i_PositionWS,
|
||||
const float2 i_PositionNDC,
|
||||
const float4 i_ScreenPositionRaw,
|
||||
const float i_PixelZ,
|
||||
const half3 i_SceneColorUnrefracted,
|
||||
const half3 i_View,
|
||||
const float i_SceneZ,
|
||||
const float i_SceneZRaw,
|
||||
const float i_Scale,
|
||||
const float i_LodAlpha,
|
||||
const bool i_Underwater,
|
||||
const half i_TotalInternalReflectionIntensity,
|
||||
out half3 o_SceneColor,
|
||||
out float o_SceneDistance,
|
||||
out float3 o_ScenePositionWS,
|
||||
out float2 o_PositionSS,
|
||||
out bool o_Caustics
|
||||
)
|
||||
{
|
||||
float2 positionNDC = i_PositionNDC;
|
||||
float sceneDepthRaw = i_SceneZRaw;
|
||||
|
||||
o_Caustics = true;
|
||||
|
||||
// View ray intersects geometry surface either above or below water surface.
|
||||
float2 refractOffset = i_RefractionStrength * i_NormalWS.xz;
|
||||
if (!i_Underwater)
|
||||
half strength = i_RefractionStrength;
|
||||
|
||||
const half _AirToWaterRatio = i_AirIOR / i_WaterIOR;
|
||||
const half _WaterToAirRatio = i_WaterIOR / i_AirIOR;
|
||||
|
||||
// If no TIR, then use same IOR.
|
||||
const bool isA2WR = !i_Underwater || i_TotalInternalReflectionIntensity < 1.0;
|
||||
|
||||
const half eta = isA2WR ? _AirToWaterRatio : _WaterToAirRatio;
|
||||
|
||||
half3 normal = i_NormalWS;
|
||||
|
||||
// Exchanges accuracy for less artifacts.
|
||||
if (isA2WR)
|
||||
{
|
||||
// We're above the water, so behind interface is depth fog.
|
||||
refractOffset *= min(1.0, 0.5 * (i_SceneZ - i_PixelZ)) / i_SceneZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// When looking up through water, full strength ends up being quite intense so reduce it a bunch.
|
||||
refractOffset *= 0.3;
|
||||
half multiplier = 0.0;
|
||||
|
||||
if (i_Underwater)
|
||||
{
|
||||
multiplier = 1.0;
|
||||
// Max fade when water is 5m deep.
|
||||
multiplier = saturate(g_Crest_WaterDepthAtViewer * 0.2);
|
||||
// Max fade by displacement.
|
||||
multiplier *= saturate(g_Crest_MaximumVerticalDisplacement - 1.0);
|
||||
// Fade towards screen edge where off screen samples happen. + n is fade start.
|
||||
multiplier *= saturate((dot(i_PositionNDC - 0.5, -g_Crest_HorizonNormal) + 0.5) * 2.0);
|
||||
}
|
||||
|
||||
normal.y *= multiplier;
|
||||
}
|
||||
|
||||
// Blend at the edge of the screen to avoid artifacts.
|
||||
refractOffset *= 1.0 - EdgeBlendingFactor(positionNDC, i_PixelZ);
|
||||
// Since we lose detail at a distance, boosting refraction helps visually.
|
||||
strength *= lerp(i_Scale, i_Scale * 2.0, i_LodAlpha) * 0.25;
|
||||
|
||||
const float2 positionNDCRefracted = FoveatedRemapLinearToNonUniform(positionNDC + refractOffset);
|
||||
float sceneDepthRawRefracted = SHADERGRAPH_SAMPLE_SCENE_DEPTH(positionNDCRefracted);
|
||||
// Restrict to a reasonable maximum.
|
||||
strength = min(strength, i_RefractionStrength * 4.0);
|
||||
|
||||
float2 uv = GetRefractionCoordinates(i_View, normal, i_PositionWS, eta, strength);
|
||||
|
||||
o_PositionSS = min(uv * _ScreenSize.xy, _ScreenSize.xy - 1.0);
|
||||
|
||||
#if CREST_BIRP
|
||||
float deviceDepth = LoadSceneDepth(o_PositionSS);
|
||||
#else
|
||||
float deviceDepth = SHADERGRAPH_SAMPLE_SCENE_DEPTH(uv);
|
||||
#endif
|
||||
|
||||
#if (CREST_PORTALS != 0)
|
||||
#if _ALPHATEST_ON
|
||||
// Portals
|
||||
Portal::EvaluateRefraction(positionNDCRefracted, i_SceneZRaw, i_Underwater, sceneDepthRawRefracted, o_Caustics);
|
||||
Portal::EvaluateRefraction(uv, i_SceneZRaw, i_Underwater, deviceDepth, o_Caustics);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
float linearDepth = Utility::CrestLinearEyeDepth(deviceDepth);
|
||||
float depthDifference = linearDepth - i_PixelZ;
|
||||
|
||||
const float sceneZRefract = Utility::CrestLinearEyeDepth(sceneDepthRawRefracted);
|
||||
normal *= saturate(depthDifference);
|
||||
|
||||
// Depth fog & caustics - only if view ray starts from above water.
|
||||
// Compute depth fog alpha based on refracted position if it landed on an
|
||||
// underwater surface, or on unrefracted depth otherwise.
|
||||
if (sceneZRefract > i_PixelZ)
|
||||
{
|
||||
// Refracted.
|
||||
o_SceneDistance = sceneZRefract - i_PixelZ;
|
||||
o_SceneColor = SHADERGRAPH_SAMPLE_SCENE_COLOR(positionNDCRefracted);
|
||||
uv = GetRefractionCoordinates(i_View, normal, i_PositionWS, eta, strength);
|
||||
|
||||
positionNDC = positionNDCRefracted;
|
||||
sceneDepthRaw = sceneDepthRawRefracted;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unrefracted.
|
||||
// It seems that when MSAA is enabled this can sometimes be negative.
|
||||
o_SceneDistance = max(i_SceneZ - i_PixelZ, 0.0);
|
||||
o_SceneColor = i_SceneColorUnrefracted;
|
||||
o_PositionSS = min(uv * _ScreenSize.xy, _ScreenSize.xy - 1.0);
|
||||
|
||||
// NOTE: Causes refraction artifact with caustics. Cannot remember exactly why this was added.
|
||||
// o_Caustics = false;
|
||||
positionNDC = FoveatedRemapLinearToNonUniform(positionNDC);
|
||||
}
|
||||
#if CREST_BIRP
|
||||
deviceDepth = LoadSceneDepth(o_PositionSS);
|
||||
#else
|
||||
deviceDepth = SHADERGRAPH_SAMPLE_SCENE_DEPTH(uv);
|
||||
#endif
|
||||
|
||||
if (i_Underwater)
|
||||
{
|
||||
// Depth fog is handled by underwater shader.
|
||||
o_SceneDistance = i_PixelZ;
|
||||
}
|
||||
linearDepth = Utility::CrestLinearEyeDepth(deviceDepth);
|
||||
// It seems that when MSAA is enabled this can sometimes be negative.
|
||||
depthDifference = max(linearDepth - i_PixelZ, 0.0);
|
||||
|
||||
o_ScenePositionWS = ComputeWorldSpacePosition(positionNDC, sceneDepthRaw, UNITY_MATRIX_I_VP);
|
||||
#if CREST_BIRP
|
||||
// Sampling artifacts which manifest as a fine outline around refractions. Always
|
||||
// affects BIRP unless we use Load. Does not affect URP unless downsampling or MSAA
|
||||
// is used, but Load exposes us to RT scaling. Best to use Sample with HDRP too.
|
||||
o_SceneColor = LoadSceneColor(o_PositionSS).rgb;
|
||||
#else
|
||||
// Sampling artifacts if downsampling or MSAA used. Load does not help. And we get
|
||||
// outlines around all objects irrespective of refraction.
|
||||
o_SceneColor = SHADERGRAPH_SAMPLE_SCENE_COLOR(uv).rgb;
|
||||
#endif
|
||||
|
||||
o_SceneDistance = depthDifference;
|
||||
o_ScenePositionWS = ComputeWorldSpacePosition(uv, deviceDepth, UNITY_MATRIX_I_VP);
|
||||
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
|
||||
o_ScenePositionWS += _WorldSpaceCameraPos;
|
||||
#endif
|
||||
@@ -111,3 +166,4 @@ void RefractedScene
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -58,4 +58,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(CREST_HDRP) && (SHADERPASS == SHADERPASS_MOTION_VECTORS)
|
||||
#define _TRANSPARENT_WRITES_MOTION_VEC
|
||||
#endif
|
||||
|
||||
#endif // CREST_SHADERGRAPH_CONSTANTS_H
|
||||
|
||||
@@ -4,39 +4,34 @@
|
||||
// Guard against missing uniforms.
|
||||
#ifdef SHADERPASS
|
||||
|
||||
#define m_Properties \
|
||||
#define m_Properties(iomod) \
|
||||
const float3 i_PositionWS, \
|
||||
const half3 i_Normal, \
|
||||
const float3 i_ObjectPosition, \
|
||||
const float3 i_CameraPosition, \
|
||||
const float i_Time, \
|
||||
out float3 o_PositionWS, \
|
||||
out float2 o_UndisplacedXZ, \
|
||||
out float o_LodAlpha, \
|
||||
out half o_WaterLevelOffset, \
|
||||
out float2 o_WaterLevelDerivatives, \
|
||||
out half2 o_Flow
|
||||
iomod float3 o_PositionWS, \
|
||||
iomod half3 o_Normal, \
|
||||
iomod float2 o_UndisplacedXZ, \
|
||||
iomod float o_LodAlpha, \
|
||||
iomod half o_WaterLevelOffset, \
|
||||
iomod half2 o_Flow
|
||||
|
||||
// Guard against Shader Graph preview.
|
||||
#ifndef SHADERGRAPH_PREVIEW
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Shim.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Keywords.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Geometry.hlsl"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl"
|
||||
|
||||
#ifndef CREST_HDRP
|
||||
#if (SHADERPASS == SHADERPASS_MOTION_VECTORS)
|
||||
#define _TRANSPARENT_WRITES_MOTION_VEC 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if _TRANSPARENT_WRITES_MOTION_VEC
|
||||
#define m_Slice clamp((int)_Crest_LodIndex + (isMotionVectors ? g_Crest_LodChange : 0), 0, g_Crest_LodCount)
|
||||
#if d_Crest_MotionVectors
|
||||
#define m_Slice ComputeSlice(_Crest_LodIndex, isMotionVectors ? g_Crest_LodChange : 0, g_Crest_LodCount)
|
||||
#define m_Make(slice) Make(slice, isMotionVectors)
|
||||
#else
|
||||
#define m_Slice _Crest_LodIndex
|
||||
@@ -45,17 +40,14 @@
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void Vertex(m_Properties)
|
||||
#if !d_Crest_CustomMesh
|
||||
void Vertex(m_Properties(inout))
|
||||
{
|
||||
// Chunk mesh has no normals.
|
||||
o_Normal = half3(0.0, 1.0, 0.0);
|
||||
|
||||
// This will get called twice.
|
||||
// With current and previous time respectively.
|
||||
|
||||
o_UndisplacedXZ = 0.0;
|
||||
o_LodAlpha = 0.0;
|
||||
o_WaterLevelOffset = 0.0;
|
||||
o_WaterLevelDerivatives = 0.0;
|
||||
o_Flow = 0.0;
|
||||
|
||||
const bool isMotionVectors = i_Time < _Time.y;
|
||||
|
||||
const float slice0 = m_Slice;
|
||||
@@ -63,8 +55,6 @@ void Vertex(m_Properties)
|
||||
const Cascade cascade0 = Cascade::m_Make(slice0);
|
||||
const Cascade cascade1 = Cascade::m_Make(slice1);
|
||||
|
||||
o_PositionWS = i_PositionWS;
|
||||
|
||||
// Vertex snapping and LOD transition.
|
||||
SnapAndTransitionVertLayout
|
||||
(
|
||||
@@ -75,20 +65,7 @@ void Vertex(m_Properties)
|
||||
o_LodAlpha
|
||||
);
|
||||
|
||||
// Fix precision errors at edges.
|
||||
{
|
||||
// Scale up by small "epsilon" to solve numerical issues. Expand slightly about tile center.
|
||||
// :WaterGridPrecisionErrors
|
||||
const float2 tileCenterXZ = i_ObjectPosition.xz;
|
||||
const float2 cameraPositionXZ = abs(i_CameraPosition.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.
|
||||
o_PositionWS.xz = lerp(tileCenterXZ, o_PositionWS.xz, lerp(1.0, 1.01, max(cameraPositionXZ.x, cameraPositionXZ.y) * 0.00001));
|
||||
}
|
||||
PatchVerticeLayout(i_ObjectPosition.xz, i_CameraPosition.xz, o_PositionWS.xz);
|
||||
|
||||
o_UndisplacedXZ = o_PositionWS.xz;
|
||||
|
||||
@@ -96,51 +73,56 @@ void Vertex(m_Properties)
|
||||
const float weight0 = (1.0 - o_LodAlpha) * cascade0._Weight;
|
||||
const float weight1 = (1.0 - weight0) * cascade1._Weight;
|
||||
|
||||
half2 derivatives = 0.0;
|
||||
|
||||
// Data that needs to be sampled at the undisplaced position.
|
||||
if (weight0 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
#if _TRANSPARENT_WRITES_MOTION_VEC
|
||||
#if d_Crest_MotionVectors
|
||||
if (isMotionVectors)
|
||||
{
|
||||
Cascade::MakeAnimatedWavesSource(slice0).SampleDisplacement(o_UndisplacedXZ, weight0, o_PositionWS, o_WaterLevelDerivatives);
|
||||
Cascade::MakeAnimatedWavesSource(slice0).SampleDisplacement(o_UndisplacedXZ, weight0, o_PositionWS);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Cascade::MakeAnimatedWaves(slice0).SampleDisplacement(o_UndisplacedXZ, weight0, o_PositionWS, o_WaterLevelDerivatives);
|
||||
Cascade::MakeAnimatedWaves(slice0).SampleDisplacement(o_UndisplacedXZ, weight0, o_PositionWS, derivatives, o_WaterLevelOffset);
|
||||
}
|
||||
}
|
||||
|
||||
if (weight1 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
#if _TRANSPARENT_WRITES_MOTION_VEC
|
||||
#if d_Crest_MotionVectors
|
||||
if (isMotionVectors)
|
||||
{
|
||||
Cascade::MakeAnimatedWavesSource(slice1).SampleDisplacement(o_UndisplacedXZ, weight1, o_PositionWS, o_WaterLevelDerivatives);
|
||||
Cascade::MakeAnimatedWavesSource(slice1).SampleDisplacement(o_UndisplacedXZ, weight1, o_PositionWS);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Cascade::MakeAnimatedWaves(slice1).SampleDisplacement(o_UndisplacedXZ, weight1, o_PositionWS, o_WaterLevelDerivatives);
|
||||
Cascade::MakeAnimatedWaves(slice1).SampleDisplacement(o_UndisplacedXZ, weight1, o_PositionWS, derivatives, o_WaterLevelOffset);
|
||||
}
|
||||
}
|
||||
|
||||
// Account for water level changes which change angle of water surface, impacting normal.
|
||||
// true = normalize.
|
||||
o_Normal.xz += -derivatives;
|
||||
o_Normal = TransformWorldToObjectNormal(o_Normal, true);
|
||||
|
||||
#if d_Crest_FlowLod
|
||||
// Data that needs to be sampled at the displaced position.
|
||||
if (weight0 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
#if CREST_FLOW_ON
|
||||
Cascade::MakeFlow(slice0).SampleFlow(o_UndisplacedXZ, weight0, o_Flow);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (weight1 > m_CrestSampleLodThreshold)
|
||||
{
|
||||
#if CREST_FLOW_ON
|
||||
Cascade::MakeFlow(slice1).SampleFlow(o_UndisplacedXZ, weight1, o_Flow);
|
||||
#endif
|
||||
}
|
||||
#endif // d_Crest_FlowLod
|
||||
|
||||
#if _TRANSPARENT_WRITES_MOTION_VEC
|
||||
#if d_Crest_MotionVectors
|
||||
if (isMotionVectors)
|
||||
{
|
||||
o_PositionWS.xz -= g_Crest_WaterCenter.xz;
|
||||
@@ -150,35 +132,39 @@ void Vertex(m_Properties)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
#endif // SHADERGRAPH_PREVIEW
|
||||
|
||||
void Vertex_float(m_Properties)
|
||||
void Vertex_float(m_Properties(out))
|
||||
{
|
||||
#if SHADERGRAPH_PREVIEW
|
||||
o_PositionWS = 0.0;
|
||||
o_UndisplacedXZ = 0.0;
|
||||
o_Normal = i_Normal;
|
||||
o_PositionWS = i_PositionWS;
|
||||
o_UndisplacedXZ = i_PositionWS.xz;
|
||||
o_LodAlpha = 0.0;
|
||||
o_WaterLevelOffset = 0.0;
|
||||
o_WaterLevelDerivatives = 0.0;
|
||||
o_Flow = 0.0;
|
||||
#else // SHADERGRAPH_PREVIEW
|
||||
|
||||
#if !d_Crest_CustomMesh
|
||||
#if !SHADERGRAPH_PREVIEW
|
||||
m_Crest::Vertex
|
||||
(
|
||||
i_PositionWS,
|
||||
i_Normal,
|
||||
i_ObjectPosition,
|
||||
i_CameraPosition,
|
||||
i_Time,
|
||||
o_PositionWS,
|
||||
o_Normal,
|
||||
o_UndisplacedXZ,
|
||||
o_LodAlpha,
|
||||
o_WaterLevelOffset,
|
||||
o_WaterLevelDerivatives,
|
||||
o_Flow
|
||||
);
|
||||
#endif // SHADERGRAPH_PREVIEW
|
||||
#endif // d_Crest_CustomMesh
|
||||
}
|
||||
|
||||
#undef m_Properties
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#ifndef CREST_WATER_VOLUME_LIGHTING_H
|
||||
#define CREST_WATER_VOLUME_LIGHTING_H
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Keywords.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Utility.hlsl"
|
||||
@@ -11,10 +12,10 @@
|
||||
m_CrestNameSpace
|
||||
|
||||
// Schlick phase function.
|
||||
float SchlickPhase(float phaseG, float cosTheta)
|
||||
half SchlickPhase(half phaseG, half cosTheta)
|
||||
{
|
||||
const float schlickK = 1.5 * phaseG - 0.5 * phaseG * phaseG * phaseG;
|
||||
const float phaseFactor = 1.0 + schlickK * cosTheta;
|
||||
const half schlickK = 1.5 * phaseG - 0.5 * phaseG * phaseG * phaseG;
|
||||
const half phaseFactor = 1.0 + schlickK * cosTheta;
|
||||
return (1.0 - schlickK * schlickK) / (4.0 * PI * phaseFactor * phaseFactor);
|
||||
}
|
||||
|
||||
@@ -42,36 +43,49 @@ half3 VolumeLighting
|
||||
const half3 i_PrimaryLightDirection,
|
||||
const half3 i_PrimaryLightIntensity,
|
||||
const half3 i_AdditionalLight,
|
||||
const half i_AdditionalLightBlend,
|
||||
const half i_AmbientLightingTerm,
|
||||
const half i_PrimaryLightingTerm,
|
||||
const half i_AdditionalLightingTerm,
|
||||
const half3 i_SunBoost,
|
||||
const half i_ShadowsAffectAmbientLightingFactor
|
||||
)
|
||||
{
|
||||
const half3 extinction = i_Extinction;
|
||||
|
||||
const float ambientLightShadow = lerp
|
||||
half ambientLightShadow = 1.0;
|
||||
|
||||
#if d_Crest_ShadowLod
|
||||
ambientLightShadow = lerp
|
||||
(
|
||||
1.0,
|
||||
i_DirectionalLightShadow,
|
||||
saturate(min(min(extinction.x, extinction.y), extinction.z) * i_ShadowsAffectAmbientLightingFactor * g_Crest_DynamicSoftShadowsFactor)
|
||||
);
|
||||
|
||||
#ifdef d_IsAdditionalLight
|
||||
const float3 inscattered = i_PrimaryLightIntensity;
|
||||
#else
|
||||
// Sun
|
||||
const float sunPhase = SchlickPhase(i_PhaseG, dot(i_PrimaryLightDirection, i_ViewDirectionWS));
|
||||
const float3 inScatteredSun = (1.0 + i_SunBoost) * sunPhase * i_PrimaryLightIntensity * i_PrimaryLightingTerm;
|
||||
const float3 inScatteredAmbient = i_AmbientLighting * i_AmbientLightingTerm * ambientLightShadow;
|
||||
|
||||
// Total inscattered
|
||||
const float3 inscattered = (inScatteredAmbient + i_AdditionalLight + inScatteredSun * i_DirectionalLightShadow);
|
||||
#endif
|
||||
|
||||
const float3 scatteringAmount = saturate(i_Scattering / max(extinction, 0.00001));
|
||||
#ifdef d_IsAdditionalLight
|
||||
half3 inScattered = 0.0;
|
||||
half3 inScatteredAdditional = i_PrimaryLightIntensity;
|
||||
#else
|
||||
// Sun
|
||||
const half sunPhase = SchlickPhase(i_PhaseG, dot(i_PrimaryLightDirection, i_ViewDirectionWS));
|
||||
const half3 inScatteredSun = (1.0 + i_SunBoost) * sunPhase * i_PrimaryLightIntensity * i_PrimaryLightingTerm;
|
||||
const half3 inScatteredAmbient = i_AmbientLighting * i_AmbientLightingTerm * ambientLightShadow;
|
||||
|
||||
return inscattered * scatteringAmount;
|
||||
half3 inScattered = inScatteredAmbient + inScatteredSun * i_DirectionalLightShadow;
|
||||
half3 inScatteredAdditional = i_AdditionalLight;
|
||||
#endif
|
||||
|
||||
const half3 scatteringAmount = saturate(i_Scattering / max(extinction, 0.00001));
|
||||
inScattered *= scatteringAmount;
|
||||
|
||||
#if d_Crest_AdditionalLights
|
||||
inScatteredAdditional *= i_AdditionalLightingTerm;
|
||||
inScatteredAdditional *= (1.0 - i_AdditionalLightBlend) + scatteringAmount * i_AdditionalLightBlend;
|
||||
#endif
|
||||
|
||||
return inScattered + inScatteredAdditional;
|
||||
}
|
||||
|
||||
half PinchSSS
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user