移动skill位置
This commit is contained in:
170
.codex/skills/webgpu-threejs-tsl/examples/custom-material.js
Normal file
170
.codex/skills/webgpu-threejs-tsl/examples/custom-material.js
Normal file
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Custom TSL Material Example
|
||||
*
|
||||
* Demonstrates creating custom shader effects using TSL:
|
||||
* - Fresnel rim lighting
|
||||
* - Animated patterns
|
||||
* - Dynamic displacement
|
||||
*
|
||||
* Based on Three.js examples (MIT License)
|
||||
* https://github.com/mrdoob/three.js
|
||||
*/
|
||||
|
||||
import * as THREE from 'three/webgpu';
|
||||
import {
|
||||
Fn,
|
||||
color,
|
||||
float,
|
||||
vec2,
|
||||
vec3,
|
||||
uniform,
|
||||
texture,
|
||||
uv,
|
||||
time,
|
||||
mix,
|
||||
smoothstep,
|
||||
sin,
|
||||
cos,
|
||||
positionLocal,
|
||||
positionWorld,
|
||||
normalLocal,
|
||||
normalWorld,
|
||||
cameraPosition
|
||||
} from 'three/tsl';
|
||||
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
||||
|
||||
let camera, scene, renderer, controls;
|
||||
let rimColor, patternScale, displacementStrength;
|
||||
|
||||
async function init() {
|
||||
// Setup
|
||||
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 100);
|
||||
camera.position.z = 3;
|
||||
|
||||
scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color(0x000000);
|
||||
|
||||
// Uniforms for runtime control
|
||||
rimColor = uniform(new THREE.Color(0x00ffff));
|
||||
patternScale = uniform(5.0);
|
||||
displacementStrength = uniform(0.1);
|
||||
|
||||
// Create custom material
|
||||
const material = createCustomMaterial();
|
||||
|
||||
// Mesh
|
||||
const geometry = new THREE.IcosahedronGeometry(1, 64);
|
||||
const mesh = new THREE.Mesh(geometry, material);
|
||||
scene.add(mesh);
|
||||
|
||||
// Renderer
|
||||
renderer = new THREE.WebGPURenderer({ antialias: true });
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
document.body.appendChild(renderer.domElement);
|
||||
await renderer.init();
|
||||
|
||||
// Controls
|
||||
controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.enableDamping = true;
|
||||
|
||||
// Events
|
||||
window.addEventListener('resize', onWindowResize);
|
||||
|
||||
// GUI (optional - requires lil-gui)
|
||||
setupGUI();
|
||||
|
||||
renderer.setAnimationLoop(animate);
|
||||
}
|
||||
|
||||
function createCustomMaterial() {
|
||||
const material = new THREE.MeshStandardNodeMaterial();
|
||||
|
||||
// --- Fresnel Rim Effect ---
|
||||
const fresnel = Fn(() => {
|
||||
const viewDir = cameraPosition.sub(positionWorld).normalize();
|
||||
const nDotV = normalWorld.dot(viewDir).saturate();
|
||||
return float(1.0).sub(nDotV).pow(3.0);
|
||||
});
|
||||
|
||||
// --- Animated Pattern ---
|
||||
const animatedPattern = Fn(() => {
|
||||
const uvCoord = uv().mul(patternScale);
|
||||
const t = time.mul(0.5);
|
||||
|
||||
// Create animated wave pattern
|
||||
const wave1 = sin(uvCoord.x.mul(10.0).add(t)).mul(0.5).add(0.5);
|
||||
const wave2 = sin(uvCoord.y.mul(10.0).sub(t.mul(1.3))).mul(0.5).add(0.5);
|
||||
const wave3 = sin(uvCoord.x.add(uvCoord.y).mul(7.0).add(t.mul(0.7))).mul(0.5).add(0.5);
|
||||
|
||||
return wave1.mul(wave2).mul(wave3);
|
||||
});
|
||||
|
||||
// --- Displacement ---
|
||||
const displacement = Fn(() => {
|
||||
const pattern = animatedPattern();
|
||||
return normalLocal.mul(pattern.mul(displacementStrength));
|
||||
});
|
||||
|
||||
// Apply displacement
|
||||
material.positionNode = positionLocal.add(displacement());
|
||||
|
||||
// --- Color ---
|
||||
const baseColor = color(0x222244);
|
||||
const highlightColor = color(0x4444ff);
|
||||
|
||||
// Mix colors based on pattern
|
||||
const pattern = animatedPattern();
|
||||
const surfaceColor = mix(baseColor, highlightColor, pattern);
|
||||
|
||||
material.colorNode = surfaceColor;
|
||||
|
||||
// --- Rim lighting ---
|
||||
material.emissiveNode = rimColor.mul(fresnel());
|
||||
|
||||
// --- PBR properties ---
|
||||
material.roughnessNode = float(0.3).add(pattern.mul(0.4));
|
||||
material.metalnessNode = float(0.1);
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
function setupGUI() {
|
||||
// Only setup if lil-gui is available
|
||||
if (typeof window.GUI === 'undefined') {
|
||||
console.log('Add lil-gui for interactive controls');
|
||||
return;
|
||||
}
|
||||
|
||||
const gui = new GUI();
|
||||
const params = {
|
||||
rimColor: '#00ffff',
|
||||
patternScale: 5.0,
|
||||
displacementStrength: 0.1
|
||||
};
|
||||
|
||||
gui.addColor(params, 'rimColor').onChange((value) => {
|
||||
rimColor.value.set(value);
|
||||
});
|
||||
|
||||
gui.add(params, 'patternScale', 1, 20).onChange((value) => {
|
||||
patternScale.value = value;
|
||||
});
|
||||
|
||||
gui.add(params, 'displacementStrength', 0, 0.5).onChange((value) => {
|
||||
displacementStrength.value = value;
|
||||
});
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
}
|
||||
|
||||
function animate() {
|
||||
controls.update();
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
init();
|
||||
Reference in New Issue
Block a user