/** * WebGPU Three.js Project Template * * A complete starter template with: * - WebGPU renderer setup * - TSL material example * - Post-processing ready * - Responsive design * - Animation loop * * Usage: * 1. Copy this file to your project * 2. Install Three.js: npm install three * 3. Replace placeholder content with your scene */ import * as THREE from 'three/webgpu'; import { // Types float, vec2, vec3, vec4, color, uniform, // Geometry positionLocal, positionWorld, normalLocal, normalWorld, uv, // Camera cameraPosition, // Time time, deltaTime, // Math mix, smoothstep, clamp, sin, cos, // Texture texture, // Functions Fn, If, Loop, // Post-processing pass } from 'three/tsl'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; // ============================================ // CONFIGURATION // ============================================ const CONFIG = { // Renderer antialias: true, pixelRatio: Math.min(window.devicePixelRatio, 2), // Camera fov: 60, near: 0.1, far: 1000, position: new THREE.Vector3(0, 2, 5), // Scene backgroundColor: 0x111111, // Controls enableDamping: true, dampingFactor: 0.05 }; // ============================================ // GLOBALS // ============================================ let camera, scene, renderer, controls; let clock; // Add your uniforms here const uniforms = { // Example: myColor: uniform(new THREE.Color(0xff0000)) }; // ============================================ // INITIALIZATION // ============================================ async function init() { // Clock clock = new THREE.Clock(); // Scene scene = new THREE.Scene(); scene.background = new THREE.Color(CONFIG.backgroundColor); // Camera camera = new THREE.PerspectiveCamera( CONFIG.fov, window.innerWidth / window.innerHeight, CONFIG.near, CONFIG.far ); camera.position.copy(CONFIG.position); // Renderer renderer = new THREE.WebGPURenderer({ antialias: CONFIG.antialias }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(CONFIG.pixelRatio); document.body.appendChild(renderer.domElement); // Initialize WebGPU await renderer.init(); // Controls controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = CONFIG.enableDamping; controls.dampingFactor = CONFIG.dampingFactor; // Setup scene content setupLights(); setupScene(); // Optional: Setup post-processing // setupPostProcessing(); // Events window.addEventListener('resize', onWindowResize); // Start animation loop renderer.setAnimationLoop(animate); } // ============================================ // SCENE SETUP // ============================================ function setupLights() { // Ambient light const ambientLight = new THREE.AmbientLight(0x404040, 0.5); scene.add(ambientLight); // Directional light const directionalLight = new THREE.DirectionalLight(0xffffff, 1); directionalLight.position.set(5, 10, 5); directionalLight.castShadow = true; scene.add(directionalLight); // Add more lights as needed } function setupScene() { // ======================================== // ADD YOUR SCENE CONTENT HERE // ======================================== // Example: Create a mesh with TSL material const geometry = new THREE.BoxGeometry(1, 1, 1); const material = createExampleMaterial(); const mesh = new THREE.Mesh(geometry, material); scene.add(mesh); // Example: Add a floor const floorGeometry = new THREE.PlaneGeometry(10, 10); const floorMaterial = new THREE.MeshStandardNodeMaterial({ color: 0x333333 }); const floor = new THREE.Mesh(floorGeometry, floorMaterial); floor.rotation.x = -Math.PI / 2; floor.position.y = -0.5; scene.add(floor); } function createExampleMaterial() { const material = new THREE.MeshStandardNodeMaterial(); // ======================================== // CUSTOMIZE YOUR MATERIAL HERE // ======================================== // Example: Animated color material.colorNode = Fn(() => { const t = time.mul(0.5).sin().mul(0.5).add(0.5); return mix(color(0x0066ff), color(0xff6600), t); })(); // Example: PBR properties material.roughnessNode = float(0.5); material.metalnessNode = float(0.0); // Example: Simple fresnel rim material.emissiveNode = Fn(() => { const viewDir = cameraPosition.sub(positionWorld).normalize(); const fresnel = float(1.0).sub(normalWorld.dot(viewDir).saturate()).pow(3.0); return color(0x00ffff).mul(fresnel).mul(0.5); })(); return material; } // ============================================ // POST-PROCESSING (Optional) // ============================================ let postProcessing; function setupPostProcessing() { // Uncomment and customize as needed // postProcessing = new THREE.PostProcessing(renderer); // const scenePass = pass(scene, camera); // const sceneColor = scenePass.getTextureNode('output'); // // // Add effects here // postProcessing.outputNode = sceneColor; } // ============================================ // ANIMATION LOOP // ============================================ function animate() { const delta = clock.getDelta(); const elapsed = clock.getElapsedTime(); // ======================================== // UPDATE YOUR SCENE HERE // ======================================== // Example: Rotate mesh const mesh = scene.children.find((child) => child.type === 'Mesh'); if (mesh) { mesh.rotation.y += delta * 0.5; } // Update controls controls.update(); // Render if (postProcessing) { postProcessing.render(); } else { renderer.render(scene, camera); } } // ============================================ // EVENT HANDLERS // ============================================ function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } // ============================================ // START // ============================================ init().catch(console.error); // Export for external access if needed export { scene, camera, renderer, uniforms };