diff options
Diffstat (limited to 'themes/src/shaders')
| -rw-r--r-- | themes/src/shaders/grass_frag.cpp | 14 | ||||
| -rw-r--r-- | themes/src/shaders/grass_frag.h | 4 | ||||
| -rw-r--r-- | themes/src/shaders/grass_vert.cpp | 28 | ||||
| -rw-r--r-- | themes/src/shaders/grass_vert.h | 4 | ||||
| -rw-r--r-- | themes/src/shaders/sky_frag.cpp | 81 | ||||
| -rw-r--r-- | themes/src/shaders/sky_frag.h | 4 | ||||
| -rw-r--r-- | themes/src/shaders/sky_vert.cpp | 13 | ||||
| -rw-r--r-- | themes/src/shaders/sky_vert.h | 4 | ||||
| -rw-r--r-- | themes/src/shaders/snowflake_frag.cpp | 76 | ||||
| -rw-r--r-- | themes/src/shaders/snowflake_frag.h | 4 | ||||
| -rw-r--r-- | themes/src/shaders/snowflake_vert.cpp | 33 | ||||
| -rw-r--r-- | themes/src/shaders/snowflake_vert.h | 4 | ||||
| -rw-r--r-- | themes/src/shaders/sun_frag.cpp | 40 | ||||
| -rw-r--r-- | themes/src/shaders/sun_vert.cpp | 27 | ||||
| -rw-r--r-- | themes/src/shaders/water_frag.cpp | 66 | ||||
| -rw-r--r-- | themes/src/shaders/water_frag.h | 4 | ||||
| -rw-r--r-- | themes/src/shaders/water_vert.cpp | 66 | ||||
| -rw-r--r-- | themes/src/shaders/water_vert.h | 4 |
18 files changed, 466 insertions, 10 deletions
diff --git a/themes/src/shaders/grass_frag.cpp b/themes/src/shaders/grass_frag.cpp new file mode 100644 index 0000000..5a62cf2 --- /dev/null +++ b/themes/src/shaders/grass_frag.cpp @@ -0,0 +1,14 @@ +#include "grass_frag.h" + +const char* shader_grass_frag = "varying lowp vec2 vUV; \n" +" \n" +"void main() { \n" +" lowp float halfWidth = 0.5 * (1.0 - vUV.y); \n" +" lowp float distFromCenter = abs(vUV.x - 0.5); \n" +" if (distFromCenter > halfWidth) discard; \n" +" \n" +" lowp vec3 baseColor = vec3(0.15, 0.45, 0.10); \n" +" lowp vec3 tipColor = vec3(0.40, 0.75, 0.20); \n" +" gl_FragColor = vec4(mix(baseColor, tipColor, vUV.y), 1.0); \n" +"} \n" +" \n"; diff --git a/themes/src/shaders/grass_frag.h b/themes/src/shaders/grass_frag.h new file mode 100644 index 0000000..16cc29a --- /dev/null +++ b/themes/src/shaders/grass_frag.h @@ -0,0 +1,4 @@ +#ifndef SHADER_GRASS_FRAG +#define SHADER_GRASS_FRAG +extern const char* shader_grass_frag; +#endif diff --git a/themes/src/shaders/grass_vert.cpp b/themes/src/shaders/grass_vert.cpp new file mode 100644 index 0000000..c9d2955 --- /dev/null +++ b/themes/src/shaders/grass_vert.cpp @@ -0,0 +1,28 @@ +#include "grass_vert.h" + +const char* shader_grass_vert = "attribute vec2 position; // Local quad vertex: x in [-0.5, 0.5], y in [0, 1] \n" +"attribute vec3 instancePos; // Per-instance: world-space base of blade \n" +"attribute float instancePhase; // Per-instance: random phase offset for sway \n" +"attribute float instanceHeight; // Per-instance: height scale multiplier \n" +" \n" +"uniform mat4 projection; \n" +"uniform mat4 view; \n" +"uniform float time; \n" +"uniform float bladeWidth; \n" +"uniform float bladeHeight; \n" +"uniform float swayAmount; \n" +" \n" +"varying lowp vec2 vUV; \n" +" \n" +"void main() { \n" +" vec3 cameraRight = vec3(view[0][0], view[1][0], view[2][0]); \n" +" float h = bladeHeight * instanceHeight; \n" +" float sway = sin(time * 1.5 + instancePhase) * swayAmount * position.y; \n" +" vec3 worldPos = instancePos \n" +" + cameraRight * (position.x + sway) * bladeWidth \n" +" + vec3(0.0, 1.0, 0.0) * position.y * h; \n" +" \n" +" gl_Position = projection * view * vec4(worldPos, 1.0); \n" +" vUV = vec2(position.x + 0.5, position.y); \n" +"} \n" +" \n"; diff --git a/themes/src/shaders/grass_vert.h b/themes/src/shaders/grass_vert.h new file mode 100644 index 0000000..7ab52b6 --- /dev/null +++ b/themes/src/shaders/grass_vert.h @@ -0,0 +1,4 @@ +#ifndef SHADER_GRASS_VERT +#define SHADER_GRASS_VERT +extern const char* shader_grass_vert; +#endif diff --git a/themes/src/shaders/sky_frag.cpp b/themes/src/shaders/sky_frag.cpp new file mode 100644 index 0000000..400f07c --- /dev/null +++ b/themes/src/shaders/sky_frag.cpp @@ -0,0 +1,81 @@ +#include "sky_frag.h" + +const char* shader_sky_frag = "precision highp float; \n" +" \n" +"varying vec2 vUv; \n" +" \n" +"uniform float time; // seconds, for slow cloud drift \n" +"uniform float horizon; // screen-space y of the water horizon (~0.5) \n" +" \n" +"float hash(vec2 p) { \n" +" p = fract(p * vec2(123.34, 456.21)); \n" +" p += dot(p, p + 45.32); \n" +" return fract(p.x * p.y); \n" +"} \n" +" \n" +"float valueNoise(vec2 p) { \n" +" vec2 i = floor(p); \n" +" vec2 f = fract(p); \n" +" float a = hash(i); \n" +" float b = hash(i + vec2(1.0, 0.0)); \n" +" float c = hash(i + vec2(0.0, 1.0)); \n" +" float d = hash(i + vec2(1.0, 1.0)); \n" +" vec2 u = f * f * (3.0 - 2.0 * f); \n" +" return mix(mix(a, b, u.x), mix(c, d, u.x), u.y); \n" +"} \n" +" \n" +"float fbm(vec2 p) { \n" +" float v = 0.0; \n" +" float amp = 0.5; \n" +" for (int i = 0; i < 4; i++) { \n" +" v += amp * valueNoise(p); \n" +" p *= 2.0; \n" +" amp *= 0.5; \n" +" } \n" +" return v; \n" +"} \n" +" \n" +"const vec3 SKY_HORIZON = vec3(0.80, 0.88, 0.98); // matches water horizon fade \n" +"const vec3 SKY_TOP = vec3(0.22, 0.48, 0.86); // deeper zenith blue \n" +"const vec3 CLOUD_COLOR = vec3(1.00, 0.98, 0.95); // white, slightly warm \n" +" \n" +"const float DEPTH_BIAS = 0.05; // caps frequency at the horizon (larger = gentler shrink) \n" +"const float CLOUD_FREQ = 2.7; // overall cloud scale (larger = more, smaller clouds) \n" +"const float X_STRETCH = 0.35; // < 1 stretches clouds horizontally -> wispy \n" +"const float CLOUD_THRESH = 0.55; // coverage cutoff; higher = sparser sky \n" +"const float CLOUD_SOFT = 0.22; // edge softness of the cloud mask \n" +"const float CLOUD_OPACITY = 0.85; // max cloud whiteness \n" +"const float DRIFT_SPEED = 0.03; // slow lateral drift (noise units / sec) \n" +"const float H_FADE = 0.12; // band over which clouds fade in above horizon \n" +" \n" +"void main() { \n" +" // Height above the water horizon: 0 at the waterline, (1 - horizon) at the top. \n" +" float above = max(vUv.y - horizon, 0.0); \n" +" \n" +" // Vertical gradient. \n" +" float g = clamp(above / (1.0 - horizon), 0.0, 1.0); \n" +" vec3 col = mix(SKY_HORIZON, SKY_TOP, pow(g, 0.75)); \n" +" float haze = 1.0 - smoothstep(0.0, 0.35, g); \n" +" col += vec3(0.06, 0.04, 0.00) * haze; \n" +" \n" +" // Flat cloud-ceiling perspective: distance along the view ~ 1/above, so \n" +" // features shrink AND compress vertically toward the horizon. \n" +" float depth = 1.0 / (above + DEPTH_BIAS); \n" +" vec2 q; \n" +" q.x = (vUv.x - 0.5) * depth; \n" +" q.y = depth; \n" +" \n" +" vec2 p = vec2(q.x * X_STRETCH, q.y) * CLOUD_FREQ; \n" +" p.x += time * DRIFT_SPEED; \n" +" \n" +" float n = fbm(p); \n" +" float cloud = smoothstep(CLOUD_THRESH, CLOUD_THRESH + CLOUD_SOFT, n); \n" +" \n" +" // Fade clouds into the haze right at the horizon. \n" +" cloud *= smoothstep(0.0, H_FADE, above); \n" +" \n" +" col = mix(col, CLOUD_COLOR, cloud * CLOUD_OPACITY); \n" +" \n" +" gl_FragColor = vec4(col, 1.0); \n" +"} \n" +" \n"; diff --git a/themes/src/shaders/sky_frag.h b/themes/src/shaders/sky_frag.h new file mode 100644 index 0000000..886b6eb --- /dev/null +++ b/themes/src/shaders/sky_frag.h @@ -0,0 +1,4 @@ +#ifndef SHADER_SKY_FRAG +#define SHADER_SKY_FRAG +extern const char* shader_sky_frag; +#endif diff --git a/themes/src/shaders/sky_vert.cpp b/themes/src/shaders/sky_vert.cpp new file mode 100644 index 0000000..b43aa73 --- /dev/null +++ b/themes/src/shaders/sky_vert.cpp @@ -0,0 +1,13 @@ +#include "sky_vert.h" + +const char* shader_sky_vert = "precision highp float; \n" +" \n" +"attribute vec2 position; // fullscreen quad, clip-space corners in [-1, 1] \n" +" \n" +"varying vec2 vUv; \n" +" \n" +"void main() { \n" +" vUv = position * 0.5 + 0.5; // uv.y = 0 bottom, 1 top \n" +" gl_Position = vec4(position, 0.0, 1.0); \n" +"} \n" +" \n"; diff --git a/themes/src/shaders/sky_vert.h b/themes/src/shaders/sky_vert.h new file mode 100644 index 0000000..114fe63 --- /dev/null +++ b/themes/src/shaders/sky_vert.h @@ -0,0 +1,4 @@ +#ifndef SHADER_SKY_VERT +#define SHADER_SKY_VERT +extern const char* shader_sky_vert; +#endif diff --git a/themes/src/shaders/snowflake_frag.cpp b/themes/src/shaders/snowflake_frag.cpp new file mode 100644 index 0000000..52d535d --- /dev/null +++ b/themes/src/shaders/snowflake_frag.cpp @@ -0,0 +1,76 @@ +#include "snowflake_frag.h" + +const char* shader_snowflake_frag = "// Procedural star fragment shader \n" +"varying lowp vec2 vUV; \n" +"varying lowp float vSeed; \n" +"varying lowp float vScale; \n" +" \n" +"const lowp float PI = 3.14159265359; \n" +" \n" +"// Simple hash function for deterministic randomness \n" +"lowp float hash(lowp float n) { \n" +" return fract(sin(n) * 43758.5453123); \n" +"} \n" +" \n" +"// Generate star pattern procedurally \n" +"lowp float starPattern(lowp vec2 uv) { \n" +" lowp float dist = length(uv); \n" +" lowp float angle = atan(uv.y, uv.x); \n" +" \n" +" // Number of star points (4 or 5) \n" +" lowp float numPoints = 4.0 + floor(hash(vSeed) * 2.0); \n" +" \n" +" // Create sharp star with triangular points \n" +" lowp float angleStep = 2.0 * PI / numPoints; \n" +" lowp float currentAngle = mod(angle + PI / numPoints, angleStep) - angleStep * 0.5; \n" +" \n" +" // Create triangular points - distance from center to edge varies linearly with angle \n" +" lowp float normalizedAngle = abs(currentAngle) / (angleStep * 0.5); \n" +" \n" +" // Outer tip radius and inner valley radius \n" +" lowp float tipRadius = 0.5; \n" +" lowp float valleyRadius = 0.15; \n" +" \n" +" // Linear interpolation creates sharp triangular points \n" +" lowp float rayEdge = mix(tipRadius, valleyRadius, normalizedAngle); \n" +" \n" +" // Hard cutoff for sharp edges \n" +" lowp float star = step(dist, rayEdge); \n" +" \n" +" return star; \n" +"} \n" +" \n" +"void main() { \n" +" lowp float pattern = starPattern(vUV); \n" +" \n" +" // Color variation based on seed - white and blue tints \n" +" lowp float colorVar = hash(vSeed * 3.0); \n" +" lowp vec3 starColor; \n" +" \n" +" if (colorVar < 0.5) { \n" +" // Pure white \n" +" starColor = vec3(1.0, 1.0, 1.0); \n" +" } else if (colorVar < 0.75) { \n" +" // Light blue tint \n" +" starColor = vec3(0.9, 0.95, 1.0); \n" +" } else { \n" +" // Stronger blue tint \n" +" starColor = vec3(0.85, 0.92, 1.0); \n" +" } \n" +" \n" +" // Scale alpha based on size - smaller stars are more transparent \n" +" // Normalize scale from range [16, 48] to [0, 1] \n" +" lowp float sizeRatio = (vScale - 16.0) / (48.0 - 16.0); \n" +" // Map to alpha range [0.3, 1.0] - smaller stars at 30% opacity, larger at 100% \n" +" lowp float alpha = mix(0.3, 1.0, sizeRatio); \n" +" \n" +" lowp vec4 color = vec4(starColor, pattern * alpha); \n" +" \n" +" // Discard fully transparent pixels for performance \n" +" if (color.a < 0.01) { \n" +" discard; \n" +" } \n" +" \n" +" gl_FragColor = color; \n" +"} \n" +" \n"; diff --git a/themes/src/shaders/snowflake_frag.h b/themes/src/shaders/snowflake_frag.h new file mode 100644 index 0000000..b34328f --- /dev/null +++ b/themes/src/shaders/snowflake_frag.h @@ -0,0 +1,4 @@ +#ifndef SHADER_SNOWFLAKE_FRAG +#define SHADER_SNOWFLAKE_FRAG +extern const char* shader_snowflake_frag; +#endif diff --git a/themes/src/shaders/snowflake_vert.cpp b/themes/src/shaders/snowflake_vert.cpp new file mode 100644 index 0000000..199009d --- /dev/null +++ b/themes/src/shaders/snowflake_vert.cpp @@ -0,0 +1,33 @@ +#include "snowflake_vert.h" + +const char* shader_snowflake_vert = "// Instanced snowflake vertex shader \n" +"attribute vec2 position; // Base quad vertex position \n" +"attribute vec2 instancePos; // Per-instance: snowflake center position \n" +"attribute float instanceRot; // Per-instance: rotation angle \n" +"attribute float instanceScale; // Per-instance: size scale \n" +"attribute float instanceSeed; // Per-instance: random seed for variation \n" +" \n" +"uniform mat4 projection; \n" +"uniform mat4 model; \n" +" \n" +"varying lowp vec2 vUV; // UV coordinates for fragment shader \n" +"varying lowp float vSeed; // Pass seed to fragment shader \n" +"varying lowp float vScale; // Pass scale to fragment shader \n" +" \n" +"void main() { \n" +" // Rotate and scale the base quad \n" +" float c = cos(instanceRot); \n" +" float s = sin(instanceRot); \n" +" mat2 rotation = mat2(c, s, -s, c); \n" +" \n" +" vec2 rotatedPos = rotation * (position * instanceScale); \n" +" vec2 worldPos = instancePos + rotatedPos; \n" +" \n" +" gl_Position = projection * model * vec4(worldPos, 0.0, 1.0); \n" +" \n" +" // Pass UV in range [-1, 1] for procedural generation \n" +" vUV = position; \n" +" vSeed = instanceSeed; \n" +" vScale = instanceScale; \n" +"} \n" +" \n"; diff --git a/themes/src/shaders/snowflake_vert.h b/themes/src/shaders/snowflake_vert.h new file mode 100644 index 0000000..36bf8b0 --- /dev/null +++ b/themes/src/shaders/snowflake_vert.h @@ -0,0 +1,4 @@ +#ifndef SHADER_SNOWFLAKE_VERT +#define SHADER_SNOWFLAKE_VERT +extern const char* shader_snowflake_vert; +#endif diff --git a/themes/src/shaders/sun_frag.cpp b/themes/src/shaders/sun_frag.cpp index d1ea160..696b3b9 100644 --- a/themes/src/shaders/sun_frag.cpp +++ b/themes/src/shaders/sun_frag.cpp @@ -1,8 +1,46 @@ #include "sun_frag.h" const char* shader_sun_frag = "varying lowp vec4 VertexColor; \n" +"varying lowp vec2 TexCoord; \n" +"uniform lowp float time; \n" +" \n" +"// Simple noise function for edge distortion \n" +"lowp float noise(lowp vec2 p) { \n" +" return sin(p.x * 10.0 + time) * cos(p.y * 10.0 + time * 0.5) * 0.5 + 0.5; \n" +"} \n" " \n" "void main() { \n" -" gl_FragColor = VertexColor; \n" +" // TexCoord is now normalized: center is (0,0), edges are at distance ~1 \n" +" lowp float dist = length(TexCoord); \n" +" \n" +" // Add animated noise to the edge \n" +" lowp float angle = atan(TexCoord.y, TexCoord.x); \n" +" lowp float wave = sin(angle * 8.0 + time * 2.0) * 0.05 + sin(angle * 4.0 - time * 1.5) * 0.03; \n" +" lowp float noiseValue = noise(TexCoord + time * 0.1) * 0.02; \n" +" \n" +" // Create soft edge using smoothstep - ensure fade reaches zero at the actual edge \n" +" lowp float innerEdge = 0.8; \n" +" lowp float outerEdge = 1.0; \n" +" lowp float alpha = 1.0 - smoothstep(innerEdge, outerEdge, dist); \n" +" \n" +" // Apply wave distortion to the edge \n" +" alpha *= 1.0 - smoothstep(0.85 + wave + noiseValue * 2.0, 1.0, dist); \n" +" \n" +" // Make edges more transparent but not too much \n" +" alpha = alpha * alpha; \n" +" \n" +" // Add slight glow effect at the edge \n" +" lowp float glow = smoothstep(0.5, 0.8, dist) * (1.0 - smoothstep(0.8, 1.0, dist)); \n" +" \n" +" // Create orange gradient from center \n" +" lowp vec3 orangeColor = vec3(1.0, 0.5, 0.1); \n" +" lowp float centerGradient = smoothstep(0.6, 0.0, dist); \n" +" lowp vec3 baseColor = mix(VertexColor.rgb, orangeColor, centerGradient * 0.6); \n" +" \n" +" // Mix in the glow with a brighter color \n" +" lowp vec3 glowColor = baseColor * 1.3; \n" +" lowp vec3 finalColor = mix(baseColor, glowColor, glow * 0.5); \n" +" \n" +" gl_FragColor = vec4(finalColor, VertexColor.a * alpha); \n" "} \n" " \n"; diff --git a/themes/src/shaders/sun_vert.cpp b/themes/src/shaders/sun_vert.cpp index ca617c0..bacf3a6 100644 --- a/themes/src/shaders/sun_vert.cpp +++ b/themes/src/shaders/sun_vert.cpp @@ -1,16 +1,25 @@ #include "sun_vert.h" const char* shader_sun_vert = " \n" -"attribute vec2 position; \n" -"attribute vec4 color; \n" -"attribute mat4 vMatrix; \n" -"uniform mat4 projection; \n" -"uniform mat4 model; \n" +"attribute vec2 position; \n" +"attribute vec4 color; \n" +"attribute mat4 vMatrix; \n" +"uniform mat4 projection; \n" +"uniform mat4 model; \n" "varying lowp vec4 VertexColor; \n" +"varying lowp vec2 TexCoord; \n" " \n" -"void main() { \n" -" vec4 fragmentPosition = projection * model * vMatrix * vec4(position.x, position.y, 0, 1); \n" -" gl_Position = fragmentPosition; \n" -" VertexColor = color; \n" +"void main() { \n" +" vec4 fragmentPosition = projection * model * vMatrix * vec4(position.x, position.y, 0, 1); \n" +" gl_Position = fragmentPosition; \n" +" VertexColor = color; \n" +" // Normalize the position - the center is at (0,0) and edge vertices are at distance 'radius' \n" +" // We want TexCoord to be in the range roughly [-1, 1] at the edges \n" +" lowp float maxDist = length(position); \n" +" if (maxDist > 0.1) { \n" +" TexCoord = position / maxDist; \n" +" } else { \n" +" TexCoord = vec2(0.0, 0.0); \n" +" } \n" "} \n" " \n"; diff --git a/themes/src/shaders/water_frag.cpp b/themes/src/shaders/water_frag.cpp new file mode 100644 index 0000000..91c50f9 --- /dev/null +++ b/themes/src/shaders/water_frag.cpp @@ -0,0 +1,66 @@ +#include "water_frag.h" + +const char* shader_water_frag = "precision highp float; \n" +" \n" +"varying vec3 vWorldPos; \n" +"varying vec3 vNormal; \n" +" \n" +"uniform vec3 cameraPos; \n" +"uniform vec3 sunDir; // normalized direction from the water toward the sun \n" +"uniform vec3 sunColor; \n" +"uniform float time; \n" +" \n" +"float hash(vec2 p) { \n" +" p = fract(p * vec2(123.34, 456.21)); \n" +" p += dot(p, p + 45.32); \n" +" return fract(p.x * p.y); \n" +"} \n" +" \n" +"float valueNoise(vec2 p) { \n" +" vec2 i = floor(p); \n" +" vec2 f = fract(p); \n" +" float a = hash(i); \n" +" float b = hash(i + vec2(1.0, 0.0)); \n" +" float c = hash(i + vec2(0.0, 1.0)); \n" +" float d = hash(i + vec2(1.0, 1.0)); \n" +" vec2 u = f * f * (3.0 - 2.0 * f); \n" +" return mix(mix(a, b, u.x), mix(c, d, u.x), u.y); \n" +"} \n" +" \n" +"void main() { \n" +" vec3 N = normalize(vNormal); \n" +" vec3 V = normalize(cameraPos - vWorldPos); \n" +" \n" +" // Fresnel (Schlick). \n" +" float f0 = 0.02; \n" +" float fres = f0 + (1.0 - f0) * pow(1.0 - max(dot(N, V), 0.0), 5.0); \n" +" \n" +" // Refraction: depth-tinted water body, wobbled by the surface normal. \n" +" float depth01 = clamp((vWorldPos.z + 350.0) / 400.0, 0.0, 1.0); \n" +" float wob = (N.x + N.z) * 0.5; \n" +" vec3 shallow = vec3(0.10, 0.55, 0.60); \n" +" vec3 deep = vec3(0.02, 0.14, 0.28); \n" +" vec3 refractCol = mix(shallow, deep, clamp(depth01 + wob * 0.15, 0.0, 1.0)); \n" +" \n" +" // Reflection: sky gradient + reflected sun glow + broken-up specular glitter. \n" +" vec3 R = reflect(-V, N); \n" +" vec3 skyHorizon = vec3(0.80, 0.88, 0.98); \n" +" vec3 skyTop = vec3(0.30, 0.55, 0.95); \n" +" float skyT = clamp(R.y * 2.0, 0.0, 1.0); \n" +" vec3 reflectCol = mix(skyHorizon, skyTop, skyT); \n" +" \n" +" float sunAmt = max(dot(R, sunDir), 0.0); \n" +" reflectCol += sunColor * pow(sunAmt, 8.0) * 0.6; \n" +" float sparkle = valueNoise(vWorldPos.xz * 0.5 + vec2(time * 1.3, time * 0.7)); \n" +" float spec = pow(sunAmt, 200.0) * smoothstep(0.55, 0.9, sparkle); \n" +" reflectCol += sunColor * spec * 4.0; \n" +" \n" +" vec3 color = mix(refractCol, reflectCol, fres); \n" +" \n" +" // Horizon haze: hide the far straight edge of the plane by fading to sky. \n" +" float horizonFade = clamp((vWorldPos.z + 350.0) / 90.0, 0.0, 1.0); \n" +" color = mix(skyHorizon, color, horizonFade); \n" +" \n" +" gl_FragColor = vec4(color, 1.0); // opaque -> occludes the sun below the waterline \n" +"} \n" +" \n"; diff --git a/themes/src/shaders/water_frag.h b/themes/src/shaders/water_frag.h new file mode 100644 index 0000000..104cb04 --- /dev/null +++ b/themes/src/shaders/water_frag.h @@ -0,0 +1,4 @@ +#ifndef SHADER_WATER_FRAG +#define SHADER_WATER_FRAG +extern const char* shader_water_frag; +#endif diff --git a/themes/src/shaders/water_vert.cpp b/themes/src/shaders/water_vert.cpp new file mode 100644 index 0000000..44dabd8 --- /dev/null +++ b/themes/src/shaders/water_vert.cpp @@ -0,0 +1,66 @@ +#include "water_vert.h" + +const char* shader_water_vert = "precision highp float; \n" +" \n" +"attribute vec2 position; // local (x, z) on the plane \n" +" \n" +"uniform mat4 projection; \n" +"uniform mat4 view; \n" +"uniform mat4 model; \n" +"uniform float time; \n" +"uniform float amplitude; \n" +" \n" +"varying vec3 vWorldPos; \n" +"varying vec3 vNormal; \n" +" \n" +"float hash(vec2 p) { \n" +" p = fract(p * vec2(123.34, 456.21)); \n" +" p += dot(p, p + 45.32); \n" +" return fract(p.x * p.y); \n" +"} \n" +" \n" +"float valueNoise(vec2 p) { \n" +" vec2 i = floor(p); \n" +" vec2 f = fract(p); \n" +" float a = hash(i); \n" +" float b = hash(i + vec2(1.0, 0.0)); \n" +" float c = hash(i + vec2(0.0, 1.0)); \n" +" float d = hash(i + vec2(1.0, 1.0)); \n" +" vec2 u = f * f * (3.0 - 2.0 * f); \n" +" return mix(mix(a, b, u.x), mix(c, d, u.x), u.y); \n" +"} \n" +" \n" +"// Irregular height: non-harmonic directional sines plus two octaves of \n" +"// scrolling value noise so it never reads as a single clean wave. \n" +"float waveHeight(vec2 p, float t) { \n" +" float h = 0.0; \n" +" h += 0.30 * sin(dot(p, vec2(0.90, 0.30)) * 0.35 + t * 1.1); \n" +" h += 0.20 * sin(dot(p, vec2(-0.40, 1.00)) * 0.55 - t * 1.7); \n" +" h += 0.12 * sin(dot(p, vec2(0.70, -0.80)) * 0.90 + t * 2.3); \n" +" h += 0.08 * sin(dot(p, vec2(1.00, 0.60)) * 1.60 - t * 3.1); \n" +" h += 0.18 * (valueNoise(p * 0.25 + vec2(t * 0.15, t * 0.10)) - 0.5); \n" +" h += 0.09 * (valueNoise(p * 0.70 - vec2(t * 0.20, 0.0)) - 0.5); \n" +" return h; \n" +"} \n" +" \n" +"void main() { \n" +" vec2 p = position; \n" +" float t = time; \n" +" \n" +" float h = waveHeight(p, t) * amplitude; \n" +" \n" +" // Analytic normal via central differences of the same height function. \n" +" float e = 2.0; \n" +" float hL = waveHeight(p - vec2(e, 0.0), t) * amplitude; \n" +" float hR = waveHeight(p + vec2(e, 0.0), t) * amplitude; \n" +" float hD = waveHeight(p - vec2(0.0, e), t) * amplitude; \n" +" float hU = waveHeight(p + vec2(0.0, e), t) * amplitude; \n" +" vec3 N = normalize(vec3(hL - hR, 2.0 * e, hD - hU)); \n" +" \n" +" vec4 worldPos = model * vec4(p.x, h, p.y, 1.0); \n" +" vWorldPos = worldPos.xyz; \n" +" vNormal = N; // model is translation-only, so no normal matrix needed \n" +" \n" +" gl_Position = projection * view * worldPos; \n" +"} \n" +" \n"; diff --git a/themes/src/shaders/water_vert.h b/themes/src/shaders/water_vert.h new file mode 100644 index 0000000..638b22b --- /dev/null +++ b/themes/src/shaders/water_vert.h @@ -0,0 +1,4 @@ +#ifndef SHADER_WATER_VERT +#define SHADER_WATER_VERT +extern const char* shader_water_vert; +#endif |
