Tracker & ShaderNova
Hey ShaderNova, I've been chasing that perfect glint on a waterfall at sunrise—trying to catch the exact refraction of light through the mist. Ever tried capturing that same effect in a shader? I think we could swap tricks: I could show you how I set up my gear to catch that moment, and you could drop me a snippet to reproduce it on screen. What do you think?
That’s a sweet setup. I’d love to see the exact angle you’re shooting from—especially where the sun hits the mist at that “golden” tilt. I can write a water shader that splits the light into a fresnel‑boosted refraction for the glint and a fresnel‑bloom for the mist. Just send me the camera height, water angle, and the refractive index you’re aiming for. We’ll make the screen shimmer like the real thing.
Sure thing, ShaderNova. I was shooting from about 2.5 meters above the water, with the camera almost level so the angle of the sun was just right—about 5 degrees above the horizon. The water surface was angled slightly downward at roughly 10 degrees from true horizontal to catch the mist. I used a refractive index of 1.33 for the water, matching fresh water. Send over the shader code and let me see how close you can get!
```glsl
// Vertex shader
#version 300 es
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aNormal;
out vec3 vNormal;
out vec3 vWorldPos;
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProj;
void main() {
vec4 worldPos = uModel * vec4(aPosition, 1.0);
vWorldPos = worldPos.xyz;
vNormal = mat3(transpose(inverse(uModel))) * aNormal;
gl_Position = uProj * uView * worldPos;
}
// Fragment shader
#version 300 es
precision highp float;
in vec3 vNormal;
in vec3 vWorldPos;
out vec4 fragColor;
uniform samplerCube uEnvMap;
uniform vec3 uCameraPos;
uniform float uTime;
// Fresnel approximation
float fresnel(float cosTheta, float f0) {
return f0 + (1.0 - f0) * pow(1.0 - cosTheta, 5.0);
}
void main() {
vec3 N = normalize(vNormal);
vec3 V = normalize(uCameraPos - vWorldPos);
// Fresnel for the glint
float F = fresnel(dot(V, N), 0.04);
vec3 refVec = refract(-V, N, 1.0 / 1.33);
vec3 refColor = texture(uEnvMap, refVec).rgb;
// Mist: soft bloom on the surface
float mistFactor = smoothstep(0.0, 0.2, dot(V, N));
vec3 mistColor = vec3(1.0) * mistFactor * 0.6; // light white
vec3 color = mix(refColor, mistColor, 0.3) * F;
fragColor = vec4(color, 1.0);
}
```
Looks solid, ShaderNova. The fresnel tweak for the glint is spot on, and the mist blend gives that soft haze you’re after. If you want that extra sparkle, try boosting the refraction’s intensity slightly—maybe push the F factor a touch higher when the angle is super shallow. And hey, remember to keep the environment map a bit fresher than your base skybox; a little jitter in the cube map can make the reflection feel more alive. Give it a shot, and let me see how it looks in a quick preview.
You’re right, a touch more F when the angle is near zero will punch that sparkle. Try this tweak in the fragment:
```glsl
float shallow = clamp(1.0 - dot(V,N), 0.0, 1.0);
float F = fresnel(dot(V,N), 0.04) * (1.0 + 0.3 * shallow);
```
That gives a 30 % boost when the view glances the surface. And for the env map, add a tiny random offset to the sampling:
```glsl
vec3 refVec = refract(-V, N, 1.0 / 1.33);
refVec += 0.002 * vec3(noise(uTime + vWorldPos.xy));
vec3 refColor = texture(uEnvMap, refVec).rgb;
```
The `noise` function can be a simple hash‑based noise, just to jitter the reflection a bit. Give that a spin, grab a quick screenshot, and let me know if the sparkle feels alive.