Add surface displacement feature to water material
This commit is contained in:
@@ -696,6 +696,9 @@ export function createWaterMaterial(options) {
|
||||
const reflectionEnabledUniform = {
|
||||
value: options.reflection?.enabled === true ? Math.max(0, Math.min(1, options.reflection?.strength ?? 0.36)) : 0
|
||||
};
|
||||
const surfaceDisplacementEnabledUniform = {
|
||||
value: options.surfaceDisplacementEnabled === true ? 1 : 0
|
||||
};
|
||||
const waveStrength = Math.max(0, options.waveStrength);
|
||||
const clampedOpacity = Math.max(0.14, Math.min(1, options.opacity));
|
||||
const topFaceFlag = options.isTopFace ? 1 : 0;
|
||||
@@ -708,6 +711,7 @@ export function createWaterMaterial(options) {
|
||||
uniform float time;
|
||||
uniform float waveStrength;
|
||||
uniform float isTopFace;
|
||||
uniform float surfaceDisplacementEnabled;
|
||||
uniform mat4 reflectionMatrix;
|
||||
|
||||
varying vec2 vLocalSurfaceUv;
|
||||
@@ -733,12 +737,17 @@ export function createWaterMaterial(options) {
|
||||
float waveA = sin(phaseA) * 0.55;
|
||||
float waveB = sin(phaseB) * 0.30;
|
||||
float waveC = sin(phaseC) * 0.15;
|
||||
float combinedWave = waveA + waveB + waveC;
|
||||
|
||||
vec2 slope =
|
||||
dirA * (cos(phaseA) / 2.3) * 0.55 +
|
||||
dirB * (cos(phaseB) / 1.45) * 0.30 +
|
||||
dirC * (cos(phaseC) / 0.82) * 0.15;
|
||||
vWaveNormal = normalize(vec3(-slope.x * (0.3 + waveStrength * 0.7), 1.0, -slope.y * (0.3 + waveStrength * 0.7)));
|
||||
|
||||
if (surfaceDisplacementEnabled > 0.5) {
|
||||
transformedPosition.y += combinedWave * (0.035 + waveStrength * 0.09);
|
||||
}
|
||||
}
|
||||
|
||||
vec4 worldPos = modelMatrix * vec4(transformedPosition, 1.0);
|
||||
@@ -836,6 +845,11 @@ export function createWaterMaterial(options) {
|
||||
float contactSheen = 0.0;
|
||||
float reflectionMask = 0.0;
|
||||
vec3 reflectionColor = vec3(0.0);
|
||||
vec2 foamDrift = vec2(
|
||||
sin(time * 0.52 + vLocalSurfaceUv.y * 1.15),
|
||||
cos(time * 0.46 + vLocalSurfaceUv.x * 1.08)
|
||||
) * (0.06 + waveStrength * 0.12);
|
||||
vec2 foamUv = vLocalSurfaceUv + foamDrift + normal.xz * (0.08 + waveStrength * 0.14);
|
||||
|
||||
float edgeDistance = min(halfSize.x - abs(vLocalSurfaceUv.x), halfSize.y - abs(vLocalSurfaceUv.y));
|
||||
float edgeBand = max(0.22, min(halfSize.x, halfSize.y) * 0.12);
|
||||
@@ -856,7 +870,7 @@ export function createWaterMaterial(options) {
|
||||
patchAxis = normalize(patchAxis);
|
||||
}
|
||||
|
||||
float alongDistance = dot(vLocalSurfaceUv - patchData.xy, patchAxis);
|
||||
float alongDistance = dot(foamUv - patchData.xy, patchAxis);
|
||||
float contactBody = 0.0;
|
||||
float ripple = 0.0;
|
||||
float normalizedDistance = 1.0;
|
||||
@@ -864,21 +878,22 @@ export function createWaterMaterial(options) {
|
||||
|
||||
if (contactPatchShapes[patchIndex] > 0.5) {
|
||||
float segmentRadius = max(patchData.w * mix(0.82, 1.18, tangentNoise), 0.05);
|
||||
float segmentDistance = distanceToSegmentBand(vLocalSurfaceUv, patchData.xy, patchAxis, patchData.z);
|
||||
float segmentDistance = distanceToSegmentBand(foamUv, patchData.xy, patchAxis, patchData.z);
|
||||
normalizedDistance = segmentDistance / segmentRadius;
|
||||
contactBody = 1.0 - smoothstep(0.0, 1.0, normalizedDistance);
|
||||
ripple = (sin(normalizedDistance * 11.0 - time * 3.2 + alongDistance * 0.48) * 0.5 + 0.5) * exp(-normalizedDistance * 1.9);
|
||||
}
|
||||
else {
|
||||
float boundaryScale = max(min(patchData.z, patchData.w), 0.18) * mix(0.86, 1.14, tangentNoise);
|
||||
float signedDistance = signedDistanceToRegion(vLocalSurfaceUv, patchData.xy, patchAxis, patchData.zw);
|
||||
float signedDistance = signedDistanceToRegion(foamUv, patchData.xy, patchAxis, patchData.zw);
|
||||
normalizedDistance = abs(signedDistance) / max(boundaryScale, 0.05);
|
||||
contactBody = 1.0 - smoothstep(0.0, 1.0, normalizedDistance);
|
||||
ripple = (sin(normalizedDistance * 13.0 - time * 3.2 + alongDistance * 0.35) * 0.5 + 0.5) * exp(-normalizedDistance * 2.6);
|
||||
}
|
||||
|
||||
float wakeNoise = noise(vLocalSurfaceUv * 3.4 + vec2(time * 0.34, -time * 0.28));
|
||||
float foamField = max(contactBody * 0.48, ripple * (0.68 + wakeNoise * 0.32));
|
||||
float wakeNoise = noise(foamUv * 3.4 + vec2(time * 0.34, -time * 0.28));
|
||||
float foamFlow = fbm(foamUv * 1.95 + vec2(time * 0.22, -time * 0.18));
|
||||
float foamField = max(contactBody * (0.42 + foamFlow * 0.18), ripple * (0.68 + wakeNoise * 0.32));
|
||||
contactFoam = max(contactFoam, foamField);
|
||||
contactRipple = max(contactRipple, ripple);
|
||||
contactSheen = max(contactSheen, contactBody);
|
||||
@@ -893,9 +908,11 @@ export function createWaterMaterial(options) {
|
||||
vec2 reflectionUv = vReflectionCoord.xy / vReflectionCoord.w;
|
||||
reflectionUv += normal.xz * (0.01 + waveStrength * 0.012) + vec2((microWave - 0.5) * 0.018, (mediumWave - 0.5) * 0.015);
|
||||
if (reflectionUv.x >= 0.0 && reflectionUv.x <= 1.0 && reflectionUv.y >= 0.0 && reflectionUv.y <= 1.0) {
|
||||
reflectionColor = texture2D(reflectionTexture, clamp(reflectionUv, vec2(0.001), vec2(0.999))).rgb;
|
||||
reflectionColor = mix(reflectionColor, shallowTint, 0.16);
|
||||
reflectionMask = reflectionEnabled * clamp(0.12 + fresnel * 0.92 + glints * 0.28, 0.0, 0.92);
|
||||
vec4 reflectionSample = texture2D(reflectionTexture, clamp(reflectionUv, vec2(0.001), vec2(0.999)));
|
||||
if (reflectionSample.a > 0.001) {
|
||||
reflectionColor = mix(reflectionSample.rgb, shallowTint, 0.16);
|
||||
reflectionMask = reflectionEnabled * reflectionSample.a * clamp(0.12 + fresnel * 0.92 + glints * 0.28, 0.0, 0.92);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -925,6 +942,7 @@ export function createWaterMaterial(options) {
|
||||
surfaceOpacity: { value: clampedOpacity },
|
||||
waveStrength: { value: waveStrength },
|
||||
isTopFace: { value: topFaceFlag },
|
||||
surfaceDisplacementEnabled: surfaceDisplacementEnabledUniform,
|
||||
halfSize: { value: halfSize },
|
||||
contactPatches: contactPatchesUniform,
|
||||
contactPatchAxes: contactPatchAxesUniform,
|
||||
|
||||
Reference in New Issue
Block a user