Преглед изворни кода

最强水材质!!!!!!!!!!!!

BAI пре 3 недеља
родитељ
комит
6d3ac144e3
4 измењених фајлова са 44 додато и 16 уклоњено
  1. BIN
      src/assets/texture/sky.jpg
  2. 7 3
      src/config/sceneConfig.ts
  3. 35 13
      src/materials/waterNew.ts
  4. 2 0
      src/scenes/Scene3D.vue

BIN
src/assets/texture/sky.jpg


+ 7 - 3
src/config/sceneConfig.ts

@@ -31,6 +31,8 @@ export interface WaterMaterialParams {
   waterNormalTiling: number
   collisionFoamThreshold: number
   collisionFoamStrength: number
+  fresnelDistanceNear: number
+  fresnelDistanceFar: number
 }
 
 /** CSCwater 材质参数类型(独立于主水面配置) */
@@ -138,7 +140,7 @@ export const modelTransformMap: Record<string, ModelTransform> = {
 /** 水面材质参数默认值 */
 export const defaultWaterParams: WaterMaterialParams = {
   alpha: 0.95,
-  waterColor: '#566a6c',
+  waterColor: '#486165',
   deepColor: '#0a2a4a',
   flowSpeed: 3.0,
   flowDirectionX: -1,
@@ -148,13 +150,15 @@ export const defaultWaterParams: WaterMaterialParams = {
   foamIntensity: 0.25,
   specIntensity: 2.0,
   specPower: 64.0,
-  fresnelPower: 2.5,
-  fresnelIntensity: 1.0,
+  fresnelPower: 1.8,
+  fresnelIntensity: 2.5,
   depthRange: 44.0,
   waterNormalStrength: 1.0,
   waterNormalTiling: 0.46,
   collisionFoamThreshold: 0.10,
   collisionFoamStrength: 0.5,
+  fresnelDistanceNear: 5.0,
+  fresnelDistanceFar: 15.0,
 }
 
 /** CSCwater 材质参数默认值 */

+ 35 - 13
src/materials/waterNew.ts

@@ -76,6 +76,9 @@ uniform float collisionFoamThreshold;
 uniform float collisionFoamStrength;
 uniform vec3 collisionFoamColor;
 uniform float collisionFoamTime;
+uniform sampler2D skyTexture;
+uniform float fresnelDistanceNear;
+uniform float fresnelDistanceFar;
 
 varying vec2 vUv;
 varying vec3 vWorldPosition;
@@ -174,6 +177,12 @@ float getCollisionFoam(vec2 pos, float depthDiff) {
     return clamp(foam, 0.0, 1.0);
 }
 
+vec2 equirectangularUV(vec3 dir) {
+    float u = atan(dir.z, dir.x) * 0.1591549 + 0.5;
+    float v = acos(clamp(dir.y, -1.0, 1.0)) * 0.3183099;
+    return vec2(u, v);
+}
+
 void main() {
     vec2 screenUV = vClipSpace.xy / vClipSpace.w * 0.5 + 0.5;
 
@@ -246,33 +255,39 @@ void main() {
     vec3 ambientLight = vec3(0.45, 0.50, 0.55);
     vec3 sunLight = vec3(1.8, 1.7, 1.5);
 
-    vec3 skyReflection = mix(
-        vec3(0.4, 0.5, 0.6),
-        vec3(0.7, 0.8, 0.9),
-        fresnel
-    );
-
     vec3 diffuse = NdotL * sunLight;
     vec3 lighting = diffuse + ambientLight;
 
     vec3 finalColor = waterCol * lighting;
 
-    finalColor += specular * sunLight * 0.3 * (1.0 - fresnel * 0.5);
+    finalColor += specular * sunLight * 0.4;
 
     vec3 foamColor = vec3(0.95, 0.97, 1.0);
     finalColor = mix(finalColor, foamColor, foam);
 
     finalColor = mix(finalColor, collisionFoamColor, collisionFoam);
 
-    vec3 fresnelColor = mix(vec3(0.55, 0.65, 0.75), sunLight * 0.25, fresnel);
-    finalColor = mix(finalColor, fresnelColor, fresnel * 0.45);
+    float viewDist = length(cameraPos - vWorldPosition);
+    float distanceFactor = clamp((viewDist - fresnelDistanceNear) / (fresnelDistanceFar - fresnelDistanceNear), 0.0, 1.0);
+
+    float finalFresnel = fresnel * distanceFactor;
+    finalFresnel = clamp(finalFresnel, 0.0, 1.0);
+
+    vec3 reflectDir = reflect(-viewDir, finalNormal);
+    vec3 skyReflection = texture2D(skyTexture, equirectangularUV(reflectDir)).rgb;
+
+    vec3 reflectionColor = skyReflection;
+    reflectionColor += sunLight * 0.1;
+    float reflectionStrength = finalFresnel * 0.75;
+    finalColor = mix(finalColor, reflectionColor, reflectionStrength);
 
     float edgeFade = smoothstep(0.0, 0.02, screenUV.x) * smoothstep(0.0, 0.02, screenUV.y) *
                      smoothstep(0.0, 0.02, 1.0 - screenUV.x) * smoothstep(0.0, 0.02, 1.0 - screenUV.y);
 
     finalColor *= 1.0 + foam * 0.2;
 
-    float finalAlpha = alpha * (0.6 + 0.4 * (1.0 - depthFactor));
+    float fresnelAlpha = clamp((viewDist - fresnelDistanceNear) / (fresnelDistanceFar * 0.6 - fresnelDistanceNear), 0.0, 1.0);
+    float finalAlpha = mix(alpha * 0.05, 0.98, fresnelAlpha);
 
     gl_FragColor = vec4(finalColor, finalAlpha * edgeFade);
 }
@@ -291,6 +306,10 @@ const waterNormalTex1 = loadRepeatTexture('../assets/texture/Water_1_Normal.PNG'
 const waterNormalTex2 = loadRepeatTexture('../assets/texture/Water_2_Normal.PNG')
 const waterNormalTex3 = loadRepeatTexture('../assets/texture/Water_3_Normal.PNG')
 
+const skyTex = textureLoader.load(new URL('../assets/texture/sky.jpg', import.meta.url).href)
+skyTex.wrapS = THREE.RepeatWrapping
+skyTex.wrapT = THREE.ClampToEdgeWrapping
+
 export const StylizedWaterMaterial = new THREE.ShaderMaterial({
     transparent: true,
     side: THREE.DoubleSide,
@@ -304,14 +323,14 @@ export const StylizedWaterMaterial = new THREE.ShaderMaterial({
         waterLevel: { value: 0.0 },
         waveHeight: { value: 0.6 },
         flowSpeed: { value: 0.5 },
-        shallowColor: { value: new THREE.Color('#566c67') },
+        shallowColor: { value: new THREE.Color('#6a9b8a') },
         deepColor: { value: new THREE.Color('#0a2a4a') },
         foamIntensity: { value: 0.25 },
         alpha: { value: 0.85 },
         specIntensity: { value: 2.0 },
         specPower: { value: 64.0 },
-        fresnelPower: { value: 2.5 },
-        fresnelIntensity: { value: 1.0 },
+        fresnelPower: { value: 1.8 },
+        fresnelIntensity: { value: 2.5 },
         depthRange: { value: 44.0 },
         cameraPos: { value: new THREE.Vector3(0, 0, 0) },
         sunDirection: { value: new THREE.Vector3(0.5, 0.8, 0.3).normalize() },
@@ -326,6 +345,9 @@ export const StylizedWaterMaterial = new THREE.ShaderMaterial({
         collisionFoamStrength: { value: 0.5 },
         collisionFoamColor: { value: new THREE.Color(1, 1, 1) },
         collisionFoamTime: { value: 0 },
+        skyTexture: { value: skyTex },
+        fresnelDistanceNear: { value: 2.0 },
+        fresnelDistanceFar: { value: 15.0 },
     },
     vertexShader: lakeVertexShader,
     fragmentShader: lakeFragmentShader

+ 2 - 0
src/scenes/Scene3D.vue

@@ -955,6 +955,8 @@ function syncWaterParams() {
   StylizedWaterMaterial.uniforms.waterNormalTiling.value = p.waterNormalTiling
   StylizedWaterMaterial.uniforms.collisionFoamThreshold.value = p.collisionFoamThreshold
   StylizedWaterMaterial.uniforms.collisionFoamStrength.value = p.collisionFoamStrength
+  StylizedWaterMaterial.uniforms.fresnelDistanceNear.value = p.fresnelDistanceNear
+  StylizedWaterMaterial.uniforms.fresnelDistanceFar.value = p.fresnelDistanceFar
 }
 
 watch(() => waterParams.value, syncWaterParams, { deep: true })