Einmal den Fortschritt mit dem Wasser sichern

This commit is contained in:
2026-06-06 09:05:25 +02:00
parent d56f2ea41f
commit 7faed35287
21 changed files with 853 additions and 152 deletions

View File

@@ -2,11 +2,13 @@ MaterialDef Flowing Water {
MaterialParameters {
Texture2D NormalMap
Texture2D FoamMap
Texture2D DiffuseMap
Color Tint
Float UVScale : 6.0
Float Time : 0.0
Float FlowSpeed : 1.0
Float FoamAmount : 0.0
Float UVScale : 6.0
Float NormalUVScale : 0.5
Float Time : 0.0
Float FlowSpeed : 1.0
Float FoamAmount : 0.0
}
Technique {
VertexShader GLSL150: Shaders/FlowingWater.vert
@@ -15,8 +17,9 @@ MaterialDef Flowing Water {
WorldViewProjectionMatrix
}
Defines {
HAS_NORMALMAP : NormalMap
HAS_FOAMMAP : FoamMap
HAS_NORMALMAP : NormalMap
HAS_FOAMMAP : FoamMap
HAS_DIFFUSEMAP : DiffuseMap
}
}
}

View File

@@ -4,6 +4,9 @@ uniform sampler2D m_NormalMap;
#ifdef HAS_FOAMMAP
uniform sampler2D m_FoamMap;
#endif
#ifdef HAS_DIFFUSEMAP
uniform sampler2D m_DiffuseMap;
#endif
uniform vec4 m_Tint;
uniform float m_FoamAmount;
@@ -27,15 +30,18 @@ void main() {
float specular = 0.0;
float ripple = 0.0;
#ifdef HAS_NORMALMAP
vec3 n1 = texture(m_NormalMap, vTex1).rgb * 2.0 - 1.0;
vec3 n2 = texture(m_NormalMap, vTex2).rgb * 2.0 - 1.0;
vec3 raw1 = texture(m_NormalMap, vTex1).rgb * 2.0 - 1.0;
vec3 raw2 = texture(m_NormalMap, vTex2).rgb * 2.0 - 1.0;
// Tangent-Space → World-Space für horizontales Mesh (T=X, B=Z, N=Y):
// raw.xyz = (tangent-X, tangent-Y, depth) → world = (raw.x, raw.z, raw.y)
vec3 n1 = normalize(vec3(raw1.x, raw1.z, raw1.y));
vec3 n2 = normalize(vec3(raw2.x, raw2.z, raw2.y));
vec3 n = normalize(n1 + n2);
// Feste Sonnenrichtung gut für Bachlauf-Optik
vec3 sunDir = normalize(vec3(0.5, 1.0, 0.3));
specular = pow(max(0.0, dot(n, sunDir)), 22.0);
// Wellenhelligkeit variiert den Basiston leicht
ripple = dot(n, vec3(0.0, 1.0, 0.0)) * 0.10;
specular = pow(max(0.0, dot(n, sunDir)), 8.0);
// Ripple: Bereiche mit starker Oberflächenneigung (Wellenkämme) heller
ripple = (abs(n.x) + abs(n.z)) * 0.30;
#endif
// ── Schaum ────────────────────────────────────────────────────────────────
@@ -54,9 +60,26 @@ void main() {
#endif
// ── Zusammenführen ────────────────────────────────────────────────────────
vec3 waterColor = baseColor + ripple + vec3(0.35, 0.45, 0.55) * specular;
// specular-Anteil erhöht (0.55→0.75) damit Glanzlichter deutlich sichtbar sind
vec3 waterColor = baseColor + ripple + vec3(0.55, 0.65, 0.75) * specular;
vec3 finalColor = mix(waterColor, vec3(1.0), foamMask);
float finalAlpha = max(baseAlpha, foamMask * 0.9);
// ── Diffuse-Map: Fluss = Farbmodulation in Fließrichtung, Wasserfall = Gischt ──
#ifdef HAS_DIFFUSEMAP
float d1 = texture(m_DiffuseMap, vTex1 * 0.55).r;
float d2 = texture(m_DiffuseMap, vTex2 * 0.40).r;
float diffuseBlend = max(d1, d2 * 0.6);
// Fluss (FoamAmount=0): Textur moduliert die Wasserfarbe (dunkle/helle Strömungsmuster)
float riverMod = (diffuseBlend - 0.5) * 0.4 * (1.0 - m_FoamAmount);
finalColor = clamp(finalColor + riverMod, 0.0, 1.0);
// Wasserfall (FoamAmount>0): weiße Gischt-Überlagerung
float foamStr = diffuseBlend * m_FoamAmount * 0.85;
finalColor = mix(finalColor, vec3(1.0), foamStr);
finalAlpha = max(finalAlpha, foamStr * 0.9);
#endif
outFragColor = vec4(clamp(finalColor, 0.0, 1.0), finalAlpha);
}

View File

@@ -1,6 +1,7 @@
uniform mat4 g_WorldViewProjectionMatrix;
uniform float m_Time;
uniform float m_UVScale;
uniform float m_NormalUVScale;
uniform float m_FlowSpeed;
in vec3 inPosition;
@@ -12,10 +13,11 @@ out vec2 vTex2; // scrollende Normal-Map-UV (diagonal, gegenläufig)
void main() {
vUV = inTexCoord;
float t = m_Time * m_FlowSpeed;
vTex1 = vec2(inTexCoord.x * m_UVScale,
inTexCoord.y * m_UVScale - t);
vTex2 = vec2(inTexCoord.x * m_UVScale * 0.7 - t * 0.25,
inTexCoord.y * m_UVScale * 0.7 + t * 0.55);
float ns = m_UVScale * m_NormalUVScale; // Normal-Map UV-Dichte (0.5 = 2x größeres Muster)
float t = m_Time * m_FlowSpeed * m_NormalUVScale; // Scroll-Geschwindigkeit skaliert mit
vTex1 = vec2(inTexCoord.x * ns,
inTexCoord.y * ns - t);
vTex2 = vec2(inTexCoord.x * ns * 0.7 - t * 0.25,
inTexCoord.y * ns * 0.7 + t * 0.55);
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
}