Feature: pixelated projection screen
This commit is contained in:
parent
c98d4890eb
commit
eb8e74273d
@ -17,6 +17,7 @@ uniform sampler2D videoTexture;
|
|||||||
uniform float u_effect_type;
|
uniform float u_effect_type;
|
||||||
uniform float u_effect_strength;
|
uniform float u_effect_strength;
|
||||||
uniform float u_time;
|
uniform float u_time;
|
||||||
|
uniform float u_opacity;
|
||||||
varying vec2 vUv;
|
varying vec2 vUv;
|
||||||
|
|
||||||
float random(vec2 st) {
|
float random(vec2 st) {
|
||||||
@ -24,23 +25,36 @@ float random(vec2 st) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 uv = vUv;
|
// LED Grid Setup
|
||||||
vec4 color = texture2D(videoTexture, uv);
|
float ledCountX = 128.0;
|
||||||
|
float ledCountY = 72.0; // 16:9 Aspect Ratio
|
||||||
|
|
||||||
|
vec2 gridUV = vec2(vUv.x * ledCountX, vUv.y * ledCountY);
|
||||||
|
vec2 cell = fract(gridUV);
|
||||||
|
vec2 pixelatedUV = (floor(gridUV) + 0.5) / vec2(ledCountX, ledCountY);
|
||||||
|
|
||||||
|
vec4 color = texture2D(videoTexture, pixelatedUV);
|
||||||
|
|
||||||
// Effect 1: Static/Noise (Power On/Off)
|
// Effect 1: Static/Noise (Power On/Off)
|
||||||
if (u_effect_type > 0.0) {
|
if (u_effect_type > 0.0) {
|
||||||
float noise = random(uv + u_time);
|
float noise = random(pixelatedUV + u_time);
|
||||||
vec3 noiseColor = vec3(noise);
|
vec3 noiseColor = vec3(noise);
|
||||||
color.rgb = mix(color.rgb, noiseColor, u_effect_strength);
|
color.rgb = mix(color.rgb, noiseColor, u_effect_strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_FragColor = color;
|
float dist = distance(cell, vec2(0.5));
|
||||||
|
float mask = 1.0 - smoothstep(0.35, 0.45, dist);
|
||||||
|
float brightness = max(color.r, max(color.g, color.b));
|
||||||
|
float contentAlpha = smoothstep(0.05, 0.15, brightness);
|
||||||
|
|
||||||
|
gl_FragColor = vec4(color.rgb, contentAlpha * mask * u_opacity);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const visualizerFragmentShader = `
|
const visualizerFragmentShader = `
|
||||||
uniform float u_time;
|
uniform float u_time;
|
||||||
uniform float u_beat;
|
uniform float u_beat;
|
||||||
|
uniform float u_opacity;
|
||||||
varying vec2 vUv;
|
varying vec2 vUv;
|
||||||
|
|
||||||
vec3 hsv2rgb(vec3 c) {
|
vec3 hsv2rgb(vec3 c) {
|
||||||
@ -50,17 +64,27 @@ vec3 hsv2rgb(vec3 c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 uv = vUv;
|
float ledCountX = 128.0;
|
||||||
float dist = length(uv - 0.5);
|
float ledCountY = 72.0;
|
||||||
|
|
||||||
|
vec2 gridUV = vec2(vUv.x * ledCountX, vUv.y * ledCountY);
|
||||||
|
vec2 cell = fract(gridUV);
|
||||||
|
vec2 uv = (floor(gridUV) + 0.5) / vec2(ledCountX, ledCountY);
|
||||||
|
|
||||||
|
float dist = distance(cell, vec2(0.5));
|
||||||
|
float mask = 1.0 - smoothstep(0.35, 0.45, dist);
|
||||||
|
|
||||||
|
float d = length(uv - 0.5);
|
||||||
float angle = atan(uv.y - 0.5, uv.x - 0.5);
|
float angle = atan(uv.y - 0.5, uv.x - 0.5);
|
||||||
|
|
||||||
float wave = sin(dist * 20.0 - u_time * 2.0);
|
float wave = sin(d * 20.0 - u_time * 2.0);
|
||||||
float beatWave = sin(angle * 5.0 + u_time) * u_beat;
|
float beatWave = sin(angle * 5.0 + u_time) * u_beat;
|
||||||
|
|
||||||
float hue = fract(u_time * 0.1 + dist * 0.2);
|
float hue = fract(u_time * 0.1 + d * 0.2);
|
||||||
float val = 0.5 + 0.5 * sin(wave + beatWave);
|
float val = 0.5 + 0.5 * sin(wave + beatWave);
|
||||||
|
float contentAlpha = smoothstep(0.1, 0.3, val);
|
||||||
|
|
||||||
gl_FragColor = vec4(hsv2rgb(vec3(hue, 0.8, val)), 1.0);
|
gl_FragColor = vec4(hsv2rgb(vec3(hue, 0.8, val)), contentAlpha * mask * u_opacity);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -86,6 +110,7 @@ export class ProjectionScreen extends SceneFeature {
|
|||||||
onComplete: null
|
onComplete: null
|
||||||
};
|
};
|
||||||
state.originalScreenIntensity = 2.0;
|
state.originalScreenIntensity = 2.0;
|
||||||
|
state.screenOpacity = 1.0;
|
||||||
|
|
||||||
// Ensure video element exists
|
// Ensure video element exists
|
||||||
if (!state.videoElement) {
|
if (!state.videoElement) {
|
||||||
@ -161,11 +186,13 @@ export class ProjectionScreen extends SceneFeature {
|
|||||||
state.tvScreen.material = new THREE.ShaderMaterial({
|
state.tvScreen.material = new THREE.ShaderMaterial({
|
||||||
uniforms: {
|
uniforms: {
|
||||||
u_time: { value: 0.0 },
|
u_time: { value: 0.0 },
|
||||||
u_beat: { value: 0.0 }
|
u_beat: { value: 0.0 },
|
||||||
|
u_opacity: { value: state.screenOpacity }
|
||||||
},
|
},
|
||||||
vertexShader: screenVertexShader,
|
vertexShader: screenVertexShader,
|
||||||
fragmentShader: visualizerFragmentShader,
|
fragmentShader: visualizerFragmentShader,
|
||||||
side: THREE.DoubleSide
|
side: THREE.DoubleSide,
|
||||||
|
transparent: true
|
||||||
});
|
});
|
||||||
state.screenLight.intensity = state.originalScreenIntensity;
|
state.screenLight.intensity = state.originalScreenIntensity;
|
||||||
}
|
}
|
||||||
@ -194,10 +221,12 @@ export function turnTvScreenOn() {
|
|||||||
u_effect_type: { value: 0.0 },
|
u_effect_type: { value: 0.0 },
|
||||||
u_effect_strength: { value: 0.0 },
|
u_effect_strength: { value: 0.0 },
|
||||||
u_time: { value: 0.0 },
|
u_time: { value: 0.0 },
|
||||||
|
u_opacity: { value: state.screenOpacity !== undefined ? state.screenOpacity : 0.7 }
|
||||||
},
|
},
|
||||||
vertexShader: screenVertexShader,
|
vertexShader: screenVertexShader,
|
||||||
fragmentShader: screenFragmentShader,
|
fragmentShader: screenFragmentShader,
|
||||||
side: THREE.DoubleSide
|
side: THREE.DoubleSide,
|
||||||
|
transparent: true
|
||||||
});
|
});
|
||||||
|
|
||||||
state.tvScreen.material.needsUpdate = true;
|
state.tvScreen.material.needsUpdate = true;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user