Files
2026-03-28 13:57:54 +08:00

277 lines
6.2 KiB
JavaScript

/**
* 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 };