diff --git a/apps/www/components/LaunchWeek/14/TicketCanvas.tsx b/apps/www/components/LaunchWeek/14/TicketCanvas.tsx index 5ba6e4ed93b..56045f71918 100644 --- a/apps/www/components/LaunchWeek/14/TicketCanvas.tsx +++ b/apps/www/components/LaunchWeek/14/TicketCanvas.tsx @@ -1,261 +1,80 @@ -import * as THREE from 'three' import { cn } from 'ui' -import { createThreeSetup, useThreeJS, createTicketMesh } from './helpers' -import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' -import { useCallback, useRef, useState } from 'react' +import { useThreeJS } from './helpers' +import { useCallback, useRef } from 'react' +import SceneRenderer, { BaseScene } from './utils/SceneRenderer' +import TicketScene from './scenes/TicketScene' -const LwCanvas = ({ className }: { className?: string }) => { - const secretRef = useRef(false) +interface TicketCanvasProps { + secret?: boolean + platinum?: boolean + user: { + id?: string + name?: string + ticketNumber?: number + } + startDate: Date + playmodeRTChannel: unknown + className?: string + onUpgrade?: () => void +} - const setup = useCallback((container: HTMLElement) => { - // Create scene with postprocessing effects - const { - scene, - camera, - renderer, - composer, - resize, - crtPass, - glitchPass, - bloomPass, - stats, - debug, - orbitControls, - } = createThreeSetup(container, { - cameraPosition: new THREE.Vector3(0, 0, 5), - debug: false, - postprocessing: { - bloom: { - enabled: true, - strength: 0.25, - radius: 0.7, - threshold: 0.2, +const TicketCanvas = ({ + secret, + platinum, + user, + startDate, + playmodeRTChannel, + className, + onUpgrade, +}: TicketCanvasProps) => { + const sceneRef = useRef(null) + const setup = useCallback( + (container: HTMLElement) => { + let scene: BaseScene | null = null + + const sceneRenderer = new SceneRenderer(container) + + + sceneRef.current = new TicketScene({ + defaultSecret: secret, + defaultPlatinum: platinum, + user, + startDate, + onSeatChartButtonClicked: () => { + sceneRef.current?.showBackSide() + sceneRef.current?.upgradeToSecret() }, - glitch: { - enabled: true, - dtSize: 512, // Increase detail size for less frequent glitches - colS: 0, + onGoBackButtonClicked: () => { + sceneRef.current?.showFrontSide() }, - crt: { - enabled: true, - }, - }, - }) - - // Set renderer clear color to make background visible - renderer.setClearColor(0x000000, 0) - - // Add ambient light with increased intensity - const ambientLight = new THREE.AmbientLight(0xffffff, 1.0) - scene.add(ambientLight) - - // Add directional light - const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5) - directionalLight.position.set(5, 5, 5) - scene.add(directionalLight) - - // Add a point light to better illuminate the placeholder - const pointLight = new THREE.PointLight(0xffffff, 1.0) - pointLight.position.set(0, 0, 5) - scene.add(pointLight) - - // Create ticket mesh placeholder (will be replaced when texture loads) - - const planeGeometrySize = [12, 6] - const placeholderGeometry = new THREE.PlaneGeometry(...planeGeometrySize) - const placeholderMaterial = new THREE.MeshBasicMaterial({ - color: 0x000000, - transparent: true, - opacity: 1, - side: THREE.DoubleSide, - }) - // Use a more generic type for ticket to allow reassignment to either Mesh or Group - let ticket: THREE.Object3D = new THREE.Mesh(placeholderGeometry, placeholderMaterial) - - scene.add(ticket) - - // Ensure the ticket is visible in the camera's view - ticket.position.z = 0 - - // Load the ticket texture and create the actual ticket mesh - // Replace this URL with your actual ticket texture - const ticketScene = '/images/launchweek/14/supabase-ticket.glb' - const ticketStaticTexture = '/images/launchweek/14/supabase-static-ticket.png' - - createTicketMesh(ticketScene, { - width: planeGeometrySize[0], - height: planeGeometrySize[1], - ticketTextureSource: ticketStaticTexture, - debug, - }) - .then((ticketModel) => { - // Remove placeholder and add the actual ticket model - scene.remove(ticket) - scene.add(ticketModel) - - // Store reference to the new ticket for animation - if (ticket instanceof THREE.Mesh) { - ticket.geometry.dispose() - if (Array.isArray(ticket.material)) - ticket.material.forEach((material) => material.dispose()) - else ticket.material.dispose() - } - - // Update the ticket reference - ticket = ticketModel - }) - .catch((error) => { - console.error('Failed to load ticket texture:', error) }) - // Add window resize listener - window.addEventListener('resize', resize) + sceneRenderer.activateScene(sceneRef.current) - // Mouse movement tracking for glitch effect and ticket following - let lastMouseX = 0 - let lastMouseY = 0 - let mouseIntensity = 0 - let mouseIntensityDecay = 0.95 // How quickly the intensity decays + sceneRenderer.init() - // For mouse tracking of ticket - let mouseX = 0 - let mouseY = 0 - let targetX = 0 - let targetY = 0 - - const handleMouseMove = (event: MouseEvent) => { - // Calculate mouse movement distance for glitch effect - const dx = event.clientX - lastMouseX - const dy = event.clientY - lastMouseY - const distance = Math.sqrt(dx * dx + dy * dy) - - // Update intensity based on movement (clamped between 0 and 1) - mouseIntensity = Math.max(0, mouseIntensity + distance * 0.005) - - // Update last position - lastMouseX = event.clientX - lastMouseY = event.clientY - - // Update glitch intensity - if (glitchPass) { - glitchPass.setIntensity(mouseIntensity) - } - - // Calculate normalized mouse position for ticket following - // Convert from screen coordinates to normalized device coordinates (-1 to +1) - const rect = container.getBoundingClientRect() - mouseX = ((event.clientX - rect.left) / container.clientWidth) * 2 - 1 - mouseY = -((event.clientY - rect.top) / container.clientHeight) * 2 + 1 - - // Scale down the effect for subtle movement - targetX = mouseX * 0.5 - targetY = mouseY * 0.3 - } - - // Make the container element respond to pointer events - container.style.pointerEvents = 'auto' - - // Add mouse event listeners - container.addEventListener('mousemove', handleMouseMove) - - // Animation function - - const animate = (time?: number) => { - const currentTime = time || 0 - - // Update CRT shader time uniform for animation effects - if (crtPass) { - crtPass.uniforms.time.value = currentTime - crtPass.enabled = secretRef.current - } - - if(glitchPass) { - glitchPass.enabled = secretRef.current - } - - if(bloomPass) { - bloomPass.enabled = secretRef.current - } - - // Gradually decay mouse intensity when not moving - if (mouseIntensity > 0) { - mouseIntensity *= mouseIntensityDecay - if (mouseIntensity < 0.0000001) { - mouseIntensity = 0 - } - if (glitchPass) { - glitchPass.setIntensity(mouseIntensity) - } - } - - if (stats.instance) { - stats.instance.begin() - } - - if (orbitControls.instance) { - // Update controls in animation loop - orbitControls.instance.update() - } - - // Render with post-processing - composer.render() - - if (stats.instance) { - stats.instance.end() - } - } - - // Cleanup function - const cleanup = () => { - window.removeEventListener('resize', resize) - - // Your existing cleanup code... - orbitControls.instance?.dispose() // Dispose controls on cleanup - - // Dispose of all resources - scene.traverse((object) => { - if (object instanceof THREE.Mesh) { - if (object.geometry) object.geometry.dispose() - - if (object.material) { - if (Array.isArray(object.material)) { - object.material.forEach((material) => material.dispose()) - } else { - object.material.dispose() - } - } - } - }) - - renderer.dispose() - container.removeChild(renderer.domElement) - } - - return { cleanup, animate } - }, []) + return sceneRenderer + }, + [platinum, secret, startDate, user] + ) const { containerRef } = useThreeJS(setup) - - return ( - <> +
-
-
- - - + ref={containerRef} + className="w-full lg:h-full" + onClick={(e) => { + sceneRef.current?.click(e.nativeEvent) + }} + /> +
) } -export { LwCanvas } +export default TicketCanvas diff --git a/apps/www/components/LaunchWeek/14/TicketCanvas2.tsx b/apps/www/components/LaunchWeek/14/TicketCanvas2.tsx deleted file mode 100644 index 56045f71918..00000000000 --- a/apps/www/components/LaunchWeek/14/TicketCanvas2.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { cn } from 'ui' -import { useThreeJS } from './helpers' -import { useCallback, useRef } from 'react' -import SceneRenderer, { BaseScene } from './utils/SceneRenderer' -import TicketScene from './scenes/TicketScene' - -interface TicketCanvasProps { - secret?: boolean - platinum?: boolean - user: { - id?: string - name?: string - ticketNumber?: number - } - startDate: Date - playmodeRTChannel: unknown - className?: string - onUpgrade?: () => void -} - -const TicketCanvas = ({ - secret, - platinum, - user, - startDate, - playmodeRTChannel, - className, - onUpgrade, -}: TicketCanvasProps) => { - const sceneRef = useRef(null) - const setup = useCallback( - (container: HTMLElement) => { - let scene: BaseScene | null = null - - const sceneRenderer = new SceneRenderer(container) - - - sceneRef.current = new TicketScene({ - defaultSecret: secret, - defaultPlatinum: platinum, - user, - startDate, - onSeatChartButtonClicked: () => { - sceneRef.current?.showBackSide() - sceneRef.current?.upgradeToSecret() - }, - onGoBackButtonClicked: () => { - sceneRef.current?.showFrontSide() - }, - }) - - sceneRenderer.activateScene(sceneRef.current) - - sceneRenderer.init() - - return sceneRenderer - }, - [platinum, secret, startDate, user] - ) - - const { containerRef } = useThreeJS(setup) - return ( -
-
{ - sceneRef.current?.click(e.nativeEvent) - }} - /> -
- ) -} - -export default TicketCanvas diff --git a/apps/www/components/LaunchWeek/14/effects/AsciiEffect.ts b/apps/www/components/LaunchWeek/14/effects/AsciiEffect.ts deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/apps/www/components/LaunchWeek/14/effects/colored-texture-shader.ts b/apps/www/components/LaunchWeek/14/effects/colored-texture-shader.ts deleted file mode 100644 index 32f930759f9..00000000000 --- a/apps/www/components/LaunchWeek/14/effects/colored-texture-shader.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { ShaderMaterial } from "three/src/materials/ShaderMaterial"; -import { Color } from "three/src/math/Color"; - -// vertexShader.js -const vertexShader = ` - varying vec2 vUv; - - void main() { - // Pass UV coords to the fragment shader - vUv = uv; - - // Standard transform - gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); - } -`; - -// fragmentShader.js -const fragmentShader = ` - // A sampler2D to receive your texture - uniform sampler2D myTexture; - - // Base color, passed in as a uniform - uniform vec3 baseColor; - - // UV coords from the vertex shader - varying vec2 vUv; - - void main() { - // Fetch the texture color - vec4 texColor = texture2D(myTexture, vUv); - - // Simple alpha-based blend: - // The texture's alpha decides how strongly we blend it over the base color - vec3 blendedColor = mix(baseColor, texColor.rgb, texColor.a); - - // Output final color - gl_FragColor = vec4(blendedColor, 1.0); - } -`; - -export const coloredTextureMaterial = { - uniforms: { - myTexture: { value: null }, - // For example, a green base color - baseColor: { value: new Color(0xffffff) }, - }, - vertexShader, - fragmentShader, -}; diff --git a/apps/www/components/LaunchWeek/14/helpers.ts b/apps/www/components/LaunchWeek/14/helpers.ts index 27835dbc1a9..df3c1d07a41 100644 --- a/apps/www/components/LaunchWeek/14/helpers.ts +++ b/apps/www/components/LaunchWeek/14/helpers.ts @@ -1,16 +1,5 @@ import { useRef, useEffect } from 'react' -import * as THREE from 'three' -import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js' -import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js' -import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js' -import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js' import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js' -import { GlitchPass } from './effects/glitch' -import { CRTShader } from './effects/crt-shader' -import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js' -import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js' -import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' -import { coloredTextureMaterial } from './effects/colored-texture-shader' /** * Helper to simplifies controlling requestAnimationFrame @@ -42,169 +31,6 @@ export const createThreeAnimation = (callback: (time?: number) => void) => { return { start, stop } } -/** - * Helper function to create a Three.js setup with scene, camera, renderer, and post-processing - * @param container DOM element to render into - * @param options Configuration options - * @returns Object with scene, camera, renderer, composer, and resize function - */ -export const createThreeSetup = ( - container: HTMLElement, - options: { - cameraPosition?: THREE.Vector3 - postprocessing?: { - bloom?: { - enabled: boolean - strength?: number - radius?: number - threshold?: number - } - glitch?: { - enabled: boolean - dtSize?: number - colS?: number - } - crt?: { - enabled: boolean - } - } - debug?: boolean - } = {} -) => { - // Create scene - const scene = new THREE.Scene() - - if (options.debug) { - const axesHelper = new THREE.AxesHelper(5) - scene.add(axesHelper) - } - - // Create camera - const camera = new THREE.PerspectiveCamera( - 75, - container.clientWidth / container.clientHeight, - 0.1, - 1000 - ) - camera.position.copy(options.cameraPosition || new THREE.Vector3(0, 0, 5)) - - // Create renderer - const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }) - renderer.setSize(container.clientWidth, container.clientHeight) - renderer.setPixelRatio(window.devicePixelRatio) - container.appendChild(renderer.domElement) - - // Enable debug info if debug mode is enabled - if (options.debug) { - renderer.info.autoReset = false - console.log('Three.js Debug Mode Enabled') - } - - // Create composer for post-processing - const composer = new EffectComposer(renderer) - const renderPass = new RenderPass(scene, camera) - composer.addPass(renderPass) - - // Add bloom pass if enabled - let bloomPass: UnrealBloomPass | null = null - if (options.postprocessing?.bloom?.enabled) { - bloomPass = new UnrealBloomPass( - new THREE.Vector2(container.clientWidth, container.clientHeight), - options.postprocessing.bloom.strength || 1.5, - options.postprocessing.bloom.radius || 0.4, - options.postprocessing.bloom.threshold || 0.85 - ) - composer.addPass(bloomPass) - } - - // Add glitch pass if enabled - let glitchPass: GlitchPass | null = null - if (options.postprocessing?.glitch?.enabled) { - glitchPass = new GlitchPass(options.postprocessing.glitch.dtSize || 64) - 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.uniforms.resolution.value.set(container.clientWidth, container.clientHeight) - composer.addPass(crtPass) - } - - // Resize function - const resize = () => { - camera.aspect = container.clientWidth / container.clientHeight - camera.updateProjectionMatrix() - renderer.setSize(container.clientWidth, container.clientHeight) - composer.setSize(container.clientWidth, container.clientHeight) - - // Update resolution uniform for CRT shader - if (crtPass) { - crtPass.uniforms.resolution.value.set(container.clientWidth, container.clientHeight) - } - } - - // Add stats display if debug mode is enabled - let stats: { instance: Stats | null } = { instance: null } - let orbitControls: { instance: OrbitControls | null } = { instance: null } - if (options.debug) { - import('three/examples/jsm/libs/stats.module.js').then(({ default: Stats }) => { - const statsInstance = new Stats() - statsInstance.showPanel(0) // 0: fps, 1: ms, 2: mb, 3+: custom - statsInstance.dom.style.position = 'absolute' - statsInstance.dom.style.top = '0px' - statsInstance.dom.style.left = '0px' - container.appendChild(statsInstance.dom) - stats.instance = statsInstance - }) - - import('three/examples/jsm/controls/OrbitControls.js').then(({ OrbitControls }) => { - // Create OrbitControls after the setup - const controls = new OrbitControls(camera, renderer.domElement) - - // Configure controls as needed - controls.enableDamping = true // Add smooth damping - controls.dampingFactor = 0.05 - controls.enableZoom = true - controls.enablePan = true - orbitControls.instance = controls - }) - } - - return { - scene, - camera, - renderer, - composer, - resize, - bloomPass, - glitchPass, - crtPass, - stats, - orbitControls, - debug: options.debug || false, - } -} - -/** - * Helper function to load a texture - * @param url URL of the texture to load - * @returns Promise that resolves with the loaded texture - */ -export const loadTexture = (url: string): Promise => { - return new Promise((resolve, reject) => { - const textureLoader = new THREE.TextureLoader() - textureLoader.load( - url, - (texture) => resolve(texture), - undefined, - (error) => reject(error) - ) - }) -} - /** * Helper function to load a GLTF model * @param url URL of the GLTF model to load @@ -224,189 +50,6 @@ export const loadGLTFModel = (url: string) => { }) } -/** - * Helper function to create a flight ticket mesh - * @param source URL of the GLTF model or texture to use for the ticket - * @param options Configuration options for the ticket - * @returns Promise that resolves with the created model - */ -export const createTicketMesh = async ( - source: string, - options: { - ticketTextureSource?: string - width?: number - height?: number - enhanceEmissive?: boolean - debug?: boolean - materialOptions?: { - transparent?: boolean - emissiveColor?: THREE.Color | number - emissiveIntensity?: number - color?: THREE.Color | number - } - } = {} -): Promise => { - try { - const useTextureMode = !(source.endsWith('.glb') || source.endsWith('.gltf')) - - if (!useTextureMode) { - // Load the GLTF model - const model = (await loadGLTFModel(source)).scene - const ticketTexture = options.ticketTextureSource - ? await loadTexture(options.ticketTextureSource) - : null - - if (ticketTexture) { - const ticket = model.getObjectByName('ticket') - if (ticket instanceof THREE.Mesh) { - // Store the original material properties - const newMaterial = new THREE.ShaderMaterial(coloredTextureMaterial) - newMaterial.uniforms.myTexture.value = ticketTexture - - ticket.material = newMaterial - } - } - - const objectsNames = ['planet', 'name', 'time', 'date', 'spicies', 'number'] as const - const namedObjects = getNamedTextObjects(objectsNames, model) - const textures = {} as { - [key in (typeof objectsNames)[number]]?: ReturnType - } - - for (let i = 0; i < namedObjects.length; i++) { - const namedObject = namedObjects[i] - const objectName = objectsNames[i] - - if (!namedObject) { - console.error(`Named object ${objectsNames} not found`) - continue - } - - if (namedObject instanceof THREE.Mesh) { - // Spline exports some objects with additional invalid materials. Clean it up here - namedObject.material = new THREE.MeshBasicMaterial({}) - } - - let text = '' - switch (objectName) { - case 'planet': - text = 'Earth' - break - case 'name': - text = 'John Doe' - break - - case 'time': - text = '00:12:00' - break - - case 'date': - text = '03/24/2025' - break - - case 'spicies': - text = 'Modern human' - break - - case 'number': - text = 'A001' - break - - default: - objectName satisfies never - } - - const meshWithTexture = createTextureForObject(namedObject, text) - textures[objectName] = meshWithTexture - } - - // Calculate scale to fit the model within the specified width and height - const box = new THREE.Box3().setFromObject(model) - const size = box.getSize(new THREE.Vector3()) - - // Center the model - box.setFromObject(model) - const center = box.getCenter(new THREE.Vector3()) - model.position.sub(center) - - // Add debug helpers if debug mode is enabled - if (options.debug) { - // Add bounding box helper - const boxHelper = new THREE.BoxHelper(model, 0xff0000) - model.add(boxHelper) - - // Add wireframe helper for each mesh - model.traverse((child) => { - if (child instanceof THREE.Mesh) { - const wireframe = new THREE.WireframeGeometry(child.geometry) - const line = new THREE.LineSegments(wireframe) - line.material = new THREE.LineBasicMaterial({ color: 0x00ffff }) - - // Instead of adding to the model, add directly to the child mesh - // This prevents double transformation - child.add(line) - - // Reset position, rotation, and scale to match the parent mesh exactly - line.position.set(0, 0, 0) - line.rotation.set(0, 0, 0) - line.scale.set(1, 1, 1) - - if (!child.name) { - console.log('Debug: Mesh has no name', child) - } - - console.log('Debug: Added wireframe to mesh', child.name || 'unnamed') - } - }) - - console.log('Debug: Model dimensions', size) - console.log('Debug: Center position', center) - } - - // Only enhance emissive properties if explicitly requested - // This respects the original GLTF materials by default - if (options.enhanceEmissive) { - model.traverse((child) => { - if (child instanceof THREE.Mesh && child.material) { - if (Array.isArray(child.material)) { - child.material.forEach((mat) => { - if (mat instanceof THREE.MeshStandardMaterial) { - mat.emissive = options.materialOptions?.emissiveColor - ? new THREE.Color(options.materialOptions.emissiveColor) - : new THREE.Color(0xffffff) - mat.emissiveIntensity = options.materialOptions?.emissiveIntensity ?? 0.2 - } - }) - } else if (child.material instanceof THREE.MeshStandardMaterial) { - child.material.emissive = options.materialOptions?.emissiveColor - ? new THREE.Color(options.materialOptions.emissiveColor) - : new THREE.Color(0xffffff) - child.material.emissiveIntensity = options.materialOptions?.emissiveIntensity ?? 0.2 - } - } - }) - } - - return model - } - throw new Error(`Failed to load model from: ${source}`) - } catch (error) { - console.error('Error loading model/texture:', error) - - // Fallback to a simple plane with a default material if loading fails - const geometry = new THREE.PlaneGeometry(options.width || 4, options.height || 2) - const material = new THREE.MeshStandardMaterial({ - color: 0x00ff00, - transparent: true, - side: THREE.DoubleSide, - emissive: new THREE.Color(0xffffff), - emissiveIntensity: 0.2, - }) - - return new THREE.Mesh(geometry, material) - } -} - /** * Custom hook for Three.js setup and animation * @param setupCallback Callback function for setting up the scene @@ -440,94 +83,6 @@ export const useThreeJS = ( return { containerRef } } -function getNamedTextObjects( - names: TNamedObjects, - model: THREE.Group -): { [K in keyof TNamedObjects]: THREE.Object3D | null } { - let namedObjects = Array(names.length).fill(null) as (THREE.Object3D | null)[] - for (let i = 0; i < names.length; i++) { - const name = names[i] - const obj = model.getObjectByName(name) - if (obj) { - namedObjects[i] = obj - } - } - - return namedObjects as { [K in keyof TNamedObjects]: THREE.Object3D | null } -} - -function createTextureForObject(object: THREE.Object3D, text: string) { - // Update matrix in case object has moved - object.updateWorldMatrix(true, true) - - const localBox = new THREE.Box3().setFromObject(object) - const localSize = localBox.getSize(new THREE.Vector3()) - - // Get world scale - const worldScale = new THREE.Vector3() - object.matrixWorld.decompose(new THREE.Vector3(), new THREE.Quaternion(), worldScale) - - // Apply world scale to get world size. Spline by default exports models with 0.01 scale - const worldSize = new THREE.Vector3( - localSize.x / Math.abs(worldScale.x), - localSize.y / Math.abs(worldScale.y), - localSize.z / Math.abs(worldScale.z) - ) - - const canvas = document.createElement('canvas') - const canvasWidth = worldSize.x // Base canvas width - const canvasHeight = Math.floor(canvasWidth * (localSize.y / localSize.x)) // Maintain aspect ratio - - canvas.width = canvasWidth - canvas.height = canvasHeight - - // Get canvas context and set up text rendering - const context = canvas.getContext('2d') - - if (!context) { - throw new Error(`Could not get 2D context for text "${text}"`) - } - - // Clear canvas - context.clearRect(0, 0, canvas.width, canvas.height) - - // Set text properties - context.fillStyle = 'black' - - // Calculate font size based on canvas dimensions - // Adjust the divisor to control text size relative to canvas - const fontSize = Math.floor(canvasHeight) - context.font = `bold ${fontSize}px Arial` - - // Center text - context.textAlign = 'left' - context.textBaseline = 'middle' - context.fillText(text, 0, canvas.height / 2) - - // Create texture from canvas - const texture = new THREE.CanvasTexture(canvas) - texture.needsUpdate = true - - // Create a plane geometry sized to match the named object - const textPlane = new THREE.PlaneGeometry(worldSize.x, worldSize.y) - const textMaterial = new THREE.MeshBasicMaterial({ - map: texture, - transparent: true, - side: THREE.DoubleSide, - depthWrite: false, // Prevents z-fighting - }) - - const textMesh = new THREE.Mesh(textPlane, textMaterial) - - object.add(textMesh) - - // Position the text slightly in front of the object - // Adjust the z-offset as needed to prevent z-fighting - // Offset position to align top-left corner instead of center - textMesh.position.set(worldSize.x / 2, -worldSize.y / 2, 0.01) - - return textMesh -} export function colorObjToRgb(color: { rgb: number; alpha: number }) { return `rgb(${(color.rgb >> 16) & 255} ${(color.rgb >> 8) & 255} ${(color.rgb >> 0) & 255} / ${color.alpha})` diff --git a/apps/www/components/LaunchWeek/14/scenes/TicketScene.ts b/apps/www/components/LaunchWeek/14/scenes/TicketScene.ts index a987a19fff1..757b81c43e6 100644 --- a/apps/www/components/LaunchWeek/14/scenes/TicketScene.ts +++ b/apps/www/components/LaunchWeek/14/scenes/TicketScene.ts @@ -182,7 +182,7 @@ class TicketScene implements BaseScene { loadedTextureType: null as 'basic' | 'secret' | 'platinum' | null, effectsIntensity: 0, mouseIntensityDecay: 0.98, // How quickly the intensity decays - mouseIntensityGainRate: 0.005, + mouseIntensityGainRate: 0.003, } private _sceneConfig = { @@ -343,7 +343,7 @@ class TicketScene implements BaseScene { // Update glitch pass intensity if (this._glitchPass) { const glitchIntensity = this._internalState.mousePosition?.mouseIntensity ?? 1 - this._glitchPass.setIntensity(glitchIntensity * this._internalState.effectsIntensity * 6) + this._glitchPass.setIntensity(glitchIntensity * this._internalState.effectsIntensity * 4) } // Update CRT shader intensity diff --git a/apps/www/pages/launch-week/14/index.tsx b/apps/www/pages/launch-week/14/index.tsx index 2b57de77c80..518dc4328de 100644 --- a/apps/www/pages/launch-week/14/index.tsx +++ b/apps/www/pages/launch-week/14/index.tsx @@ -2,8 +2,7 @@ import { NextSeo } from 'next-seo' import { useRouter } from 'next/router' import { useState } from 'react' import { Session } from '@supabase/supabase-js' -import { LwCanvas } from '~/components/LaunchWeek/14/TicketCanvas' -import TicketCanvas from '~/components/LaunchWeek/14/TicketCanvas2' +import TicketCanvas from '~/components/LaunchWeek/14/TicketCanvas' import DefaultLayout from '~/components/Layouts/Default' import SectionContainer from '~/components/Layouts/SectionContainer' import { TicketState, ConfDataContext, UserData } from '~/components/LaunchWeek/hooks/use-conf-data'