Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spectrum Driven Small Details #638

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,364 changes: 2,357 additions & 7 deletions crest/Assets/Crest/Crest-Examples/Main/Scenes/main.unity

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions crest/Assets/Crest/Crest/Materials/Ocean-Underwater.mat
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Material:
- _CausticsTextureAverage: 0.07
- _CausticsTextureScale: 5
- _ClipSurface: 1
- _ClipUnderTerrain: 0
- _CompileShaderWithDebugInfo: 0
- _ComputeDirectionalLight: 1
- _CullMode: 0
Expand All @@ -118,8 +119,10 @@ Material:
- _Invert: 1
- _MipBias: 0
- _Moving: 0.17
- _NormalsMaxScale: 80
- _NormalsMinScale: 40
- _NormalsScale: 40
- _NormalsStrength: 0.36
- _NormalsStrength: 1
- _Offset: 0.00008
- _OverrideReflectionCubemap: 0
- _PlanarReflectionIntensity: 1
Expand All @@ -130,7 +133,7 @@ Material:
- _RefractionStrength: 1
- _RefractiveIndexOfAir: 1.2
- _RefractiveIndexOfWater: 1.333
- _Roughness: 0
- _Roughness: 1
- _S: 1
- _Shadows: 1
- _ShorelineFoamMinDepth: 0.27
Expand Down
65 changes: 64 additions & 1 deletion crest/Assets/Crest/Crest/Scripts/OceanChunkRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class OceanChunkRenderer : MonoBehaviour
PropertyWrapperMPB _mpb;

// Cache these off to support regenerating ocean surface
int _lodIndex = -1;
public int _lodIndex = -1;
int _totalLodCount = -1;
int _lodDataResolution = 256;
int _geoDownSampleFactor = 1;
Expand All @@ -32,11 +32,35 @@ public class OceanChunkRenderer : MonoBehaviour
// MeshScaleLerp, FarNormalsWeight, LODIndex (debug)
public static int sp_InstanceData = Shader.PropertyToID("_InstanceData");

static int sp_SpectrumDrivenNormals = Shader.PropertyToID("_SpectrumDrivenNormals");
static int sp_SpectrumDrivenNormalsNext = Shader.PropertyToID("_SpectrumDrivenNormalsNext");
static int sp_SpectrumDrivenRoughness = Shader.PropertyToID("_SpectrumDrivenRoughness");

// TODO: This should be a static list on the ShapeGerstnerBatched
ShapeGerstnerBatched _dominantShapedGerstnerBatched;

// NOTE: Storing these here temporarily so they can be viewed in inspector.
public float maxWaveLength = 0;
public float minWaveLength = 0;
public float normalsWaveLength = 0;
public float normalsWaveLengthNext = 0;
public float roughnessWaveLength = 0;
public int normalsWaveLengthIndex = 0;
public int normalsWaveLengthNextIndex = 0;
public int roughnessWaveLengthIndex = 0;
public float normalsAmplitude = 0;
public float normalsAmplitudeNext = 0;
public float roughnessAmplitude = 0;

void Start()
{
Rend = GetComponent<Renderer>();
_mesh = GetComponent<MeshFilter>().sharedMesh;

// TODO: How to handle multiple and local gerstners. Multiple gerstners should be simply taking the highest
// value. The only issue is with local gerstners, but they could be ignored for now.
_dominantShapedGerstnerBatched = FindObjectOfType<ShapeGerstnerBatched>();

UpdateMeshBounds();
}

Expand Down Expand Up @@ -112,6 +136,8 @@ void OnWillRenderObject()
var normalScrollSpeed1 = Mathf.Pow(Mathf.Log(1f + 4f * gridSizeLodData) * mul, pow);
_mpb.SetVector(sp_GeomData, new Vector4(gridSizeLodData, gridSizeGeo, normalScrollSpeed0, normalScrollSpeed1));

DriveSmallDetailsStrength();

// Assign LOD data to ocean shader
var ldaws = OceanRenderer.Instance._lodDataAnimWaves;
var ldsds = OceanRenderer.Instance._lodDataSeaDepths;
Expand Down Expand Up @@ -148,6 +174,43 @@ void OnWillRenderObject()
Rend.SetPropertyBlock(_mpb.materialPropertyBlock);
}

public void DriveSmallDetailsStrength()
{
// TODO: We could reduce work by only computing all of this once per lod index.
maxWaveLength = OceanRenderer.Instance._lodTransform.MaxWavelength(_lodIndex);
minWaveLength = maxWaveLength * 0.5f;

normalsWaveLength = minWaveLength * 0.5f;
normalsWaveLengthNext = minWaveLength;
roughnessWaveLength = normalsWaveLength * 0.5f;

normalsAmplitude = CalculateSmallDetailsStrength(normalsWaveLength, ref normalsWaveLengthIndex);
normalsAmplitudeNext = CalculateSmallDetailsStrength(normalsWaveLengthNext, ref normalsWaveLengthNextIndex);
roughnessAmplitude = CalculateSmallDetailsStrength(roughnessWaveLength, ref roughnessWaveLengthIndex);

_mpb.SetFloat(sp_SpectrumDrivenNormals, OceanRenderer.Instance.EnableSpectrumDrivenNormals ? normalsAmplitude : 1f);
_mpb.SetFloat(sp_SpectrumDrivenNormalsNext, OceanRenderer.Instance.EnableSpectrumDrivenNormals ? normalsAmplitudeNext : 1f);
_mpb.SetFloat(sp_SpectrumDrivenRoughness, OceanRenderer.Instance.EnableSpectrumDrivenRoughness ? roughnessAmplitude : 1f);
}

// NOTE: ref waveLengthIndex parameter is only used for debugging purposes. It will be removed.
public float CalculateSmallDetailsStrength(float waveLength, ref int waveLengthIndex)
{
waveLengthIndex = (int)Mathf.Max(-1, OceanWaveSpectrum.OctaveIndex(waveLength)) * _dominantShapedGerstnerBatched._componentsPerOctave;
var amplitude = 0f;
if (waveLengthIndex >= 0)
{
var maximumAmplitudeIndex = waveLengthIndex + _dominantShapedGerstnerBatched._componentsPerOctave;
for (var i = 0; i < maximumAmplitudeIndex; i++)
{
amplitude = Mathf.Max(amplitude, _dominantShapedGerstnerBatched._amplitudes[i]);
}
}

// Without multiplying by 10, results were not showing since the numbers were too small.
return amplitude * OceanRenderer.Instance.AmplitudeMultiplier;
}

// this is called every frame because the bounds are given in world space and depend on the transform scale, which
// can change depending on view altitude
public static void ExpandBoundsForDisplacements(Transform transform, ref Bounds bounds)
Expand Down
5 changes: 5 additions & 0 deletions crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ public enum DefaultClippingState
bool _followSceneCamera = true;
#pragma warning restore 414

[Header("Spectrum Driven Details")]
public bool EnableSpectrumDrivenNormals = true;
public bool EnableSpectrumDrivenRoughness = true;
[Range(0, 100)] public float AmplitudeMultiplier = 10f;

[Header("Debug Params")]

[Tooltip("Attach debug gui that adds some controls and allows to visualise the ocean data."), SerializeField]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public enum SpectrumModel
#endif

public static float SmallWavelength(float octaveIndex) { return Mathf.Pow(2f, SMALLEST_WL_POW_2 + octaveIndex); }
public static float OctaveIndex(float waveLength) => Mathf.Log(waveLength, 2f) - SMALLEST_WL_POW_2;

public float GetAmplitude(float wavelength, float componentsPerOctave)
{
Expand Down
2 changes: 2 additions & 0 deletions crest/Assets/Crest/Crest/Shaders/Ocean.shader
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Shader "Crest/Ocean"
_NormalsStrength("Strength", Range(0.01, 2.0)) = 0.36
// Scale of normal map texture
_NormalsScale("Scale", Range(0.01, 200.0)) = 40.0
_NormalsMinScale("Min Scale", Range(0.01, 200.0)) = 20.0
_NormalsMaxScale("Max Scale", Range(0.01, 200.0)) = 80.0

// Base light scattering settings which give water colour
[Header(Scattering)]
Expand Down
12 changes: 9 additions & 3 deletions crest/Assets/Crest/Crest/Shaders/OceanNormalMapping.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@

uniform half _NormalsStrength;
uniform half _NormalsScale;
uniform half _NormalsMinScale;
uniform half _NormalsMaxScale;
uniform half _SpectrumDrivenNormals;
uniform half _SpectrumDrivenNormalsNext;

half2 SampleNormalMaps(float2 worldXZUndisplaced, float lodAlpha)
{
const float2 v0 = float2(0.94, 0.34), v1 = float2(-0.85, -0.53);
const float lodDataGridSize = _GeomData.x;
float nstretch = _NormalsScale * lodDataGridSize; // normals scaled with geometry
float nstretch = clamp(_NormalsScale * _SpectrumDrivenNormals, _NormalsMinScale, _NormalsMaxScale) * lodDataGridSize; // normals scaled with geometry
const float spdmulL = _GeomData.z;
half2 norm =
UnpackNormal(tex2D(_Normals, (v0*_CrestTime*spdmulL + worldXZUndisplaced) / nstretch)).xy +
Expand All @@ -23,19 +27,21 @@ half2 SampleNormalMaps(float2 worldXZUndisplaced, float lodAlpha)
// blend in next higher scale of normals to obtain continuity
const float farNormalsWeight = _InstanceData.y;
const half nblend = lodAlpha * farNormalsWeight;
half normalsStrength = _NormalsStrength * _SpectrumDrivenNormals;
if (nblend > 0.001)
{
// next lod level
nstretch *= 2.;
nstretch = clamp(_NormalsScale * _SpectrumDrivenNormalsNext, _NormalsMinScale, _NormalsMaxScale) * lodDataGridSize * 2.0;
const float spdmulH = _GeomData.w;
norm = lerp(norm,
UnpackNormal(tex2D(_Normals, (v0*_CrestTime*spdmulH + worldXZUndisplaced) / nstretch)).xy +
UnpackNormal(tex2D(_Normals, (v1*_CrestTime*spdmulH + worldXZUndisplaced) / nstretch)).xy,
nblend);
normalsStrength = lerp(normalsStrength, _NormalsStrength * _SpectrumDrivenNormalsNext, nblend);
}

// approximate combine of normals. would be better if normals applied in local frame.
return _NormalsStrength * norm;
return normalsStrength * norm;
}

void ApplyNormalMapsWithFlow(float2 worldXZUndisplaced, float2 flow, float lodAlpha, inout half3 io_n)
Expand Down
4 changes: 3 additions & 1 deletion crest/Assets/Crest/Crest/Shaders/OceanReflection.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)

uniform half _SpectrumDrivenRoughness;

#if _PROCEDURALSKY_ON
uniform half3 _SkyBase, _SkyAwayFromSun, _SkyTowardsSun;
uniform half _SkyDirectionality;
Expand Down Expand Up @@ -87,7 +89,7 @@ void ApplyReflectionSky(in const half3 i_view, in const half3 i_n_pixel, in cons
skyColour = val.rgb;
#else
Unity_GlossyEnvironmentData envData;
envData.roughness = _Roughness;
envData.roughness = _Roughness * _SpectrumDrivenRoughness;
envData.reflUVW = refl;
float3 probe0 = Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, envData);
#if UNITY_SPECCUBE_BLENDING
Expand Down