feat: add better bloom

This commit is contained in:
Piotr Goszczyński committed 2025-03-17 19:46:11 +01:00
1 parent d50b6c8cf5
commit 072cc3ff37
3 files changed
+88 -83

No files matched your search

+9 -9
View File
@@ -11,10 +11,10 @@ const LwCanvas = ({ className }: { className?: string }) => {
cameraPosition: new THREE.Vector3(0, 0, 5),
postprocessing: {
bloom: {
enabled: false,
strength: 0.1,
radius: 0.8,
threshold: 0.1,
enabled: true,
strength: 0.25,
radius: 0.7,
threshold: 0.2,
},
glitch: {
enabled: true,
@@ -151,18 +151,18 @@ const LwCanvas = ({ className }: { className?: string }) => {
if (ticket) {
// Add very subtle floating animation with reduced amplitude
const floatingX = Math.sin(currentTime * 0.0003) * 0.01
// const floatingX = Math.sin(currentTime * 0.0003) * 0.01
const floatingY = Math.sin(currentTime * 0.0005) * 0.005
// Smoothly interpolate current position toward target (mouse) position
const lerpFactor = 0.05 // Lower value = smoother/slower follow
// Combine floating animation with mouse following
ticket.rotation.y = floatingX + (targetX * 0.2)
ticket.rotation.x = floatingY + (targetY * -0.2)
// // Combine floating animation with mouse following
// ticket.rotation.y = floatingX + (targetX * 0.2)
// ticket.rotation.x = floatingY + (targetY * -0.2)
// Smoothly move ticket position toward target with easing
ticket.position.x += (targetX - ticket.position.x) * lerpFactor
// ticket.position.x += (targetX - ticket.position.x) * lerpFactor
ticket.position.y += (targetY - ticket.position.y) * lerpFactor + (Math.sin(currentTime * 0.0007) * 0.02)
}
+76 -71
View File
@@ -2,81 +2,81 @@ import { useRef, useEffect } from 'react'
import * as THREE from 'three'
// CRT Scanline shader
// export const CRTShader = {
// uniforms: {
// tDiffuse: { value: null },
// resolution: { value: new THREE.Vector2(1, 1) },
// scanlineIntensity: { value: 0.30 },
// scanlineCount: { value: 320 },
// vignetteIntensity: { value: 0.5 },
// time: { value: 0 },
// noise: { value: 0.08 },
// flickerIntensity: { value: 0.03 },
// },
// vertexShader: `
// varying vec2 vUv;
// void main() {
// vUv = uv;
// gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
// }
// `,
// fragmentShader: `
// uniform sampler2D tDiffuse;
// uniform vec2 resolution;
// uniform float scanlineIntensity;
// uniform float scanlineCount;
// uniform float vignetteIntensity;
// uniform float time;
// uniform float noise;
// uniform float flickerIntensity;
// varying vec2 vUv;
//
// float random(vec2 p) {
// vec2 k1 = vec2(23.14069263277926, 2.665144142690225);
// return fract(cos(dot(p, k1)) * 12345.6789);
// }
//
// void main() {
// // Get the original color
// vec4 color = texture2D(tDiffuse, vUv);
//
// // Scanlines
// float scanline = sin(vUv.y * scanlineCount * 3.14159) * 0.5 + 0.5;
// scanline = pow(scanline, 1.0) * scanlineIntensity;
// color.rgb -= scanline;
//
// // Vignette effect
// float vignette = distance(vUv, vec2(0.5));
// vignette = smoothstep(0.4, 0.75, vignette) * vignetteIntensity;
// color.rgb -= vignette;
//
// // Noise
// float noiseVal = random(vUv + vec2(time * 0.001)) * noise;
// color.rgb += noiseVal - (noise * 0.5);
//
// // Flicker
// float flicker = random(vec2(time * 0.001, 0.0)) * flickerIntensity;
// color.rgb += flicker - (flickerIntensity * 0.5);
//
// // RGB shift
// float rgbShift = 0.003;
// color.r += texture2D(tDiffuse, vUv + vec2(rgbShift, 0.0)).r * 0.1;
// color.b += texture2D(tDiffuse, vUv - vec2(rgbShift, 0.0)).b * 0.1;
//
// gl_FragColor = color;
// }
// `
// };
export const CRTShader = {
uniforms: {
tDiffuse: { value: null },
resolution: { value: new THREE.Vector2(1, 1) },
scanlineIntensity: { value: 0.30 },
scanlineCount: { value: 320 },
vignetteIntensity: { value: 0.8 },
time: { value: 0 },
noise: { value: 0.3 },
flickerIntensity: { value: 0.08 },
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform sampler2D tDiffuse;
uniform vec2 resolution;
uniform float scanlineIntensity;
uniform float scanlineCount;
uniform float vignetteIntensity;
uniform float time;
uniform float noise;
uniform float flickerIntensity;
varying vec2 vUv;
float random(vec2 p) {
vec2 k1 = vec2(23.14069263277926, 2.665144142690225);
return fract(cos(dot(p, k1)) * 12345.6789);
}
void main() {
// Get the original color
vec4 color = texture2D(tDiffuse, vUv);
// Scanlines
float scanline = sin(vUv.y * scanlineCount * 3.14159) * 0.5 + 0.5;
scanline = pow(scanline, 1.0) * scanlineIntensity;
color.rgb -= scanline;
// Vignette effect
float vignette = distance(vUv, vec2(0.5));
vignette = smoothstep(0.4, 0.75, vignette) * vignetteIntensity;
color.rgb -= vignette;
// Noise
float noiseVal = random(vUv + vec2(time * 0.001)) * noise;
color.rgb += noiseVal - (noise * 0.5);
// Flicker
float flicker = random(vec2(time * 0.001, 0.0)) * flickerIntensity;
color.rgb += flicker - (flickerIntensity * 0.5);
// RGB shift
float rgbShift = 0.003;
color.r += texture2D(tDiffuse, vUv + vec2(rgbShift, 0.0)).r * 0.1;
color.b += texture2D(tDiffuse, vUv - vec2(rgbShift, 0.0)).b * 0.1;
gl_FragColor = color;
}
`
};
export const CRTShader2 = {
uniforms: {
tDiffuse: { value: null },
time: { value: 0 },
resolution: { value: new THREE.Vector2(1, 1) },
scanlineIntensity: { value: 0.5 },
scanlineCount: { value: 320 },
vignetteIntensity: { value: 0.2 },
noiseIntensity: { value: 0.1 },
vignetteIntensity: { value: 0.5 },
noiseIntensity: { value: 0.3 },
flickerIntensity: { value: 0.03 },
rgbShiftAmount: { value: 0.0015 },
},
@@ -123,7 +123,7 @@ export const CRTShader = {
// Vignette effect
vec2 center = vec2(0.5, 0.5);
float dist = distance(vUv, center);
float vignette = smoothstep(0.5, 0.2, dist) * vignetteIntensity;
float vignette = smoothstep(0.4, 0.75, dist) * vignetteIntensity;
// Noise
float noise = random(vUv + time * 0.001) * noiseIntensity;
@@ -131,11 +131,16 @@ export const CRTShader = {
// Flicker
float flicker = random(vec2(time * 0.001, 0.0)) * flickerIntensity;
// Combine effects
vec4 finalColor = shiftedColor;
finalColor.rgb *= (1.0 - scanline);
// Apply vignette (darkens edges, not center)
finalColor.rgb *= (1.0 - vignette);
finalColor.rgb += noise;
// Apply noise properly - add noise but keep it centered around zero
finalColor.rgb += noise - (noiseIntensity * 0.5);
// Apply flicker
finalColor.rgb *= (1.0 - flicker);
gl_FragColor = finalColor;
+3 -3
View File
@@ -6,7 +6,7 @@ import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPa
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { GlitchPass } from './glitch'
import { CRTShader } from './crt-shader'
import { CRTShader, CRTShader2 } from './crt-shader'
// // CRT Shader implementation
// const CRTShader = {
@@ -181,14 +181,14 @@ export const createThreeSetup = (
let glitchPass: GlitchPass | null = null
if (options.postprocessing?.glitch?.enabled) {
glitchPass = new GlitchPass(options.postprocessing.glitch.dtSize || 64)
glitchPass.setIntensity(options.postprocessing.glitch.colS || 0)
glitchPass.uniforms.col_s.value = options.postprocessing.glitch.colS || 0
composer.addPass(glitchPass)
}
// Add CRT pass if enabled
let crtPass: ShaderPass | null = null
if (options.postprocessing?.crt?.enabled) {
crtPass = new ShaderPass(CRTShader)
crtPass = new ShaderPass(CRTShader2)
crtPass.uniforms.resolution.value.set(container.clientWidth, container.clientHeight)
composer.addPass(crtPass)
}