fix: stabilize water depth and rounded mask
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
PLAYER_SPAWN_POSITION_PHYSICS,
|
||||
} from "@/data/player/playerConfig";
|
||||
import { useCameraMode } from "@/hooks/debug/useCameraMode";
|
||||
import { useEnvironmentDebug } from "@/hooks/debug/useEnvironmentDebug";
|
||||
import { useMapPerformanceDebug } from "@/hooks/debug/useMapPerformanceDebug";
|
||||
import { useSceneMode } from "@/hooks/debug/useSceneMode";
|
||||
import { useHandTrackingSnapshot } from "@/hooks/handTracking/useHandTrackingSnapshot";
|
||||
@@ -36,6 +37,7 @@ interface WorldProps {
|
||||
}
|
||||
|
||||
export function World({ onLoadingStateChange }: WorldProps): React.JSX.Element {
|
||||
useEnvironmentDebug();
|
||||
useMapPerformanceDebug();
|
||||
|
||||
const cameraMode = useCameraMode();
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { useMemo, useRef } from "react";
|
||||
import * as THREE from "three";
|
||||
import { useFrame } from "@react-three/fiber";
|
||||
import { getWindVector } from "@/data/world/windConfig";
|
||||
import { WATER_SHADER_CONFIG } from "@/data/world/waterConfig";
|
||||
import type { WaterSurfaceConfig } from "@/data/world/waterConfig";
|
||||
import { useWind } from "@/hooks/world/useWind";
|
||||
import {
|
||||
WATER_FRAGMENT_SHADER,
|
||||
WATER_VERTEX_SHADER,
|
||||
@@ -15,6 +17,7 @@ export function WaterSurface({
|
||||
size,
|
||||
}: WaterSurfaceConfig): React.JSX.Element {
|
||||
const materialRef = useRef<THREE.ShaderMaterial>(null);
|
||||
const wind = useWind();
|
||||
const uniforms = useMemo(
|
||||
() => ({
|
||||
uTime: { value: 0 },
|
||||
@@ -28,6 +31,8 @@ export function WaterSurface({
|
||||
uNoiseScale: { value: WATER_SHADER_CONFIG.noiseScale },
|
||||
uNoiseFlowSpeed: { value: WATER_SHADER_CONFIG.noiseFlowSpeed },
|
||||
uDistortAmount: { value: WATER_SHADER_CONFIG.distortAmount },
|
||||
uBorderRadius: { value: WATER_SHADER_CONFIG.borderRadius },
|
||||
uBorderSoftness: { value: WATER_SHADER_CONFIG.borderSoftness },
|
||||
uDeepColor: { value: new THREE.Color(WATER_SHADER_CONFIG.deepColor) },
|
||||
uMidColor: { value: new THREE.Color(WATER_SHADER_CONFIG.midColor) },
|
||||
uMidPos: { value: WATER_SHADER_CONFIG.midPos },
|
||||
@@ -41,15 +46,28 @@ export function WaterSurface({
|
||||
);
|
||||
|
||||
useFrame(({ clock }) => {
|
||||
const uniform = materialRef.current?.uniforms.uTime;
|
||||
if (uniform) {
|
||||
uniform.value = clock.getElapsedTime();
|
||||
const material = materialRef.current;
|
||||
if (!material) return;
|
||||
|
||||
const windVector = getWindVector(wind);
|
||||
|
||||
const { uFlowX, uFlowZ, uNoiseScale, uTime } = material.uniforms;
|
||||
|
||||
if (uTime) uTime.value = clock.getElapsedTime();
|
||||
if (uFlowX) uFlowX.value = WATER_SHADER_CONFIG.flowX + windVector.x;
|
||||
if (uFlowZ) uFlowZ.value = WATER_SHADER_CONFIG.flowZ + windVector.z;
|
||||
if (uNoiseScale) {
|
||||
uNoiseScale.value = WATER_SHADER_CONFIG.noiseScale * wind.noiseScale;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<mesh
|
||||
position={position}
|
||||
position={[
|
||||
position[0],
|
||||
position[1] + WATER_SHADER_CONFIG.depthOffset,
|
||||
position[2],
|
||||
]}
|
||||
rotation={[-Math.PI / 2 + rotation[0], rotation[1], rotation[2]]}
|
||||
renderOrder={renderOrder}
|
||||
>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
export const WATER_VERTEX_SHADER = /* glsl */ `
|
||||
varying vec2 vUv;
|
||||
varying vec2 vWorldPos;
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
vec4 worldPosition = modelMatrix * vec4(position, 1.0);
|
||||
vWorldPos = worldPosition.xz;
|
||||
gl_Position = projectionMatrix * viewMatrix * worldPosition;
|
||||
@@ -20,6 +22,8 @@ export const WATER_FRAGMENT_SHADER = /* glsl */ `
|
||||
uniform float uNoiseScale;
|
||||
uniform float uNoiseFlowSpeed;
|
||||
uniform float uDistortAmount;
|
||||
uniform float uBorderRadius;
|
||||
uniform float uBorderSoftness;
|
||||
uniform vec3 uDeepColor;
|
||||
uniform vec3 uMidColor;
|
||||
uniform float uMidPos;
|
||||
@@ -27,8 +31,18 @@ export const WATER_FRAGMENT_SHADER = /* glsl */ `
|
||||
uniform float uOpacity;
|
||||
uniform float uDeepOpacity;
|
||||
|
||||
varying vec2 vUv;
|
||||
varying vec2 vWorldPos;
|
||||
|
||||
float roundedBoxMask(vec2 uv, float radius, float softness) {
|
||||
vec2 centeredUv = uv * 2.0 - 1.0;
|
||||
vec2 boxSize = vec2(1.0 - radius);
|
||||
vec2 distanceToEdge = abs(centeredUv) - boxSize;
|
||||
float outsideDistance = length(max(distanceToEdge, 0.0)) - radius;
|
||||
|
||||
return 1.0 - smoothstep(-softness, softness, outsideDistance);
|
||||
}
|
||||
|
||||
vec2 hash2(vec2 p) {
|
||||
p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));
|
||||
return fract(sin(p) * 43758.5453);
|
||||
@@ -126,6 +140,11 @@ export const WATER_FRAGMENT_SHADER = /* glsl */ `
|
||||
inSecondSegment
|
||||
);
|
||||
float alpha = mix(uDeepOpacity, 1.0, ramp) * uOpacity;
|
||||
alpha *= roundedBoxMask(vUv, uBorderRadius, uBorderSoftness);
|
||||
|
||||
if (alpha < 0.01) {
|
||||
discard;
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(color, alpha);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user