uniform mat4 g_WorldViewProjectionMatrix; uniform mat4 g_WorldMatrix; uniform float g_Time; uniform float m_WindSpeed; uniform float m_WindStrength; uniform vec2 m_WindDir; // normierter XZ-Windvektor in vec3 inPosition; in vec3 inNormal; in vec4 inColor; in vec2 inTexCoord; // .x = windFactor (0=Wurzel, 1=Spitze) .y = randPhase (pro Halm, aus Java gebacken) out vec4 varColor; out vec3 varNormal; void main() { vec4 pos = vec4(inPosition, 1.0); float wf = inTexCoord.x; if (wf > 0.001) { vec2 worldXZ = (g_WorldMatrix * pos).xz; float t = g_Time * m_WindSpeed; // Windrichtung (Fallback: Süd) vec2 windN = (dot(m_WindDir, m_WindDir) > 0.001) ? normalize(m_WindDir) : vec2(0.0, 1.0); // randPhase in Java aus der Halm-Wurzel gebacken (hash(bx,bz)*2π) → identisch für // alle Vertices desselben Halms, kein Breitenflackern bei starkem Wind. float randPhase = inTexCoord.y; float wavePhase = dot(worldXZ, windN); float sway = sin(t * 2.1 + wavePhase * 0.10 + randPhase) * 0.6 + sin(t * 1.4 + wavePhase * 0.06 + randPhase * 0.73) * 0.4; // Mindest-Stärke damit bei wenig Wind noch Bewegung sichtbar ist float effectiveStrength = max(m_WindStrength, 0.05); // Quadratische Gewichtung: Spitze biegt sich mehr als Basis float bend = sway * effectiveStrength * wf * wf; pos.x += windN.x * bend; pos.z += windN.y * bend; // Y-Kompression: Halm neigt sich statt zu strecken → verhindert visuelles Breiterwerden pos.y -= bend * bend * 0.5; } varColor = inColor; varNormal = normalize(mat3(g_WorldMatrix) * inNormal); gl_Position = g_WorldViewProjectionMatrix * pos; }