feat(immersive): add GPU blur + noise distortion in shader
- Multi-sample blur: 12 samples in circular pattern - Noise-based UV distortion to break up pixelation - Random sample offsets for organic blur effect - All blur computation is GPU-side (no CPU cost)
This commit is contained in:
1 parent
6fc1156b93
commit
add1cf3cc0
1 file changed
+67
-25
@@ -2,59 +2,101 @@
|
||||
/**
|
||||
* Ambient Motion Fragment Shader
|
||||
*
|
||||
* Adds subtle GPU-driven motion to the background:
|
||||
* Adds GPU-driven motion and blur simulation to the background:
|
||||
* - Multi-sample blur (samples multiple nearby points)
|
||||
* - UV drift (slow wandering)
|
||||
* - Zoom oscillation (breathing effect)
|
||||
* - Color breathing (subtle brightness pulsing)
|
||||
*
|
||||
* All effects are controlled by u_intensity (0 = static, 1 = full motion).
|
||||
* All computation is GPU-side - no CPU per-frame work.
|
||||
* - Noise-based distortion to break up pixelation
|
||||
*/
|
||||
|
||||
precision mediump float;
|
||||
|
||||
// Input from vertex shader
|
||||
in vec2 v_texCoord;
|
||||
|
||||
// Output
|
||||
out vec4 fragColor;
|
||||
|
||||
// Uniforms
|
||||
uniform sampler2D u_texture;
|
||||
uniform float u_time; // Time in seconds
|
||||
uniform float u_intensity; // Motion intensity (0.0 - 1.0)
|
||||
uniform float u_time;
|
||||
uniform float u_intensity;
|
||||
|
||||
// Constants for motion parameters - made MORE visible
|
||||
const float DRIFT_SPEED_X = 0.15;
|
||||
const float DRIFT_SPEED_Y = 0.12;
|
||||
const float DRIFT_AMOUNT = 0.08; // 8% UV drift
|
||||
// Motion parameters
|
||||
const float DRIFT_SPEED_X = 0.12;
|
||||
const float DRIFT_SPEED_Y = 0.09;
|
||||
const float DRIFT_AMOUNT = 0.06;
|
||||
|
||||
const float ZOOM_SPEED = 0.1;
|
||||
const float ZOOM_AMOUNT = 0.05; // 5% zoom oscillation
|
||||
const float ZOOM_SPEED = 0.08;
|
||||
const float ZOOM_AMOUNT = 0.04;
|
||||
|
||||
const float BREATH_SPEED = 0.2;
|
||||
const float BREATH_AMOUNT = 0.12; // 12% brightness pulse
|
||||
const float BREATH_SPEED = 0.15;
|
||||
const float BREATH_AMOUNT = 0.08;
|
||||
|
||||
// Blur simulation parameters
|
||||
const float BLUR_RADIUS = 0.015; // UV space blur radius
|
||||
const int BLUR_SAMPLES = 12; // Number of samples for blur
|
||||
|
||||
// Simple pseudo-random function
|
||||
float random(vec2 st) {
|
||||
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
|
||||
}
|
||||
|
||||
// Smooth noise function
|
||||
float noise(vec2 st) {
|
||||
vec2 i = floor(st);
|
||||
vec2 f = fract(st);
|
||||
|
||||
float a = random(i);
|
||||
float b = random(i + vec2(1.0, 0.0));
|
||||
float c = random(i + vec2(0.0, 1.0));
|
||||
float d = random(i + vec2(1.0, 1.0));
|
||||
|
||||
vec2 u = f * f * (3.0 - 2.0 * f);
|
||||
|
||||
return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = v_texCoord;
|
||||
vec2 center = vec2(0.5);
|
||||
|
||||
// UV drift - slow wandering motion
|
||||
// UV drift
|
||||
float driftX = sin(u_time * DRIFT_SPEED_X) * DRIFT_AMOUNT * u_intensity;
|
||||
float driftY = cos(u_time * DRIFT_SPEED_Y * 1.3) * DRIFT_AMOUNT * u_intensity;
|
||||
uv += vec2(driftX, driftY);
|
||||
|
||||
// Zoom oscillation - subtle breathing
|
||||
// Zoom oscillation
|
||||
float zoom = 1.0 + sin(u_time * ZOOM_SPEED) * ZOOM_AMOUNT * u_intensity;
|
||||
uv = center + (uv - center) / zoom;
|
||||
|
||||
// Clamp UV to avoid edge artifacts
|
||||
uv = clamp(uv, 0.0, 1.0);
|
||||
// Add subtle noise-based distortion to break up pixelation
|
||||
float noiseScale = 8.0;
|
||||
float distortAmount = 0.008;
|
||||
float n1 = noise(uv * noiseScale + u_time * 0.1);
|
||||
float n2 = noise(uv * noiseScale + 100.0 + u_time * 0.1);
|
||||
uv += vec2(n1 - 0.5, n2 - 0.5) * distortAmount;
|
||||
|
||||
// Sample texture
|
||||
vec4 color = texture(u_texture, uv);
|
||||
// Multi-sample blur to smooth out the texture
|
||||
vec4 color = vec4(0.0);
|
||||
float totalWeight = 0.0;
|
||||
|
||||
// Color breathing - subtle brightness pulsing
|
||||
for (int i = 0; i < BLUR_SAMPLES; i++) {
|
||||
float angle = float(i) * 6.28318530718 / float(BLUR_SAMPLES);
|
||||
float r = BLUR_RADIUS * (0.5 + 0.5 * random(uv + float(i)));
|
||||
vec2 offset = vec2(cos(angle), sin(angle)) * r;
|
||||
|
||||
vec2 sampleUV = clamp(uv + offset, 0.0, 1.0);
|
||||
float weight = 1.0 - length(offset) / BLUR_RADIUS;
|
||||
|
||||
color += texture(u_texture, sampleUV) * weight;
|
||||
totalWeight += weight;
|
||||
}
|
||||
|
||||
// Add center sample with higher weight
|
||||
color += texture(u_texture, clamp(uv, 0.0, 1.0)) * 2.0;
|
||||
totalWeight += 2.0;
|
||||
|
||||
color /= totalWeight;
|
||||
|
||||
// Color breathing
|
||||
float breath = 1.0 + sin(u_time * BREATH_SPEED) * BREATH_AMOUNT * u_intensity;
|
||||
color.rgb *= breath;
|
||||
|
||||
|
||||
Reference in new issue
Block a user