Claude Agent Skill · by Cloudai X

Threejs Postprocessing

Install Threejs Postprocessing skill for Claude Code from cloudai-x/threejs-skills.

Install
Terminal · npx
$npx skills add https://github.com/cloudai-x/threejs-skills --skill threejs-postprocessing
Works with Paperclip

How Threejs Postprocessing fits into a Paperclip company.

Threejs Postprocessing drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md602 lines
Expand
---name: threejs-postprocessingdescription: Three.js post-processing - EffectComposer, bloom, DOF, screen effects. Use when adding visual effects, color grading, blur, glow, or creating custom screen-space shaders.--- # Three.js Post-Processing ## Quick Start ```javascriptimport * as THREE from "three";import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";import { RenderPass } from "three/addons/postprocessing/RenderPass.js";import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js"; // Setup composerconst composer = new EffectComposer(renderer); // Render sceneconst renderPass = new RenderPass(scene, camera);composer.addPass(renderPass); // Add bloomconst bloomPass = new UnrealBloomPass(  new THREE.Vector2(window.innerWidth, window.innerHeight),  1.5, // strength  0.4, // radius  0.85, // threshold);composer.addPass(bloomPass); // Animation loop - use composer instead of rendererfunction animate() {  requestAnimationFrame(animate);  composer.render(); // NOT renderer.render()}``` ## EffectComposer Setup ```javascriptimport { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";import { RenderPass } from "three/addons/postprocessing/RenderPass.js"; const composer = new EffectComposer(renderer); // First pass: render sceneconst renderPass = new RenderPass(scene, camera);composer.addPass(renderPass); // Add more passes...composer.addPass(effectPass); // Last pass should render to screeneffectPass.renderToScreen = true; // Default for last pass // Handle resizefunction onResize() {  const width = window.innerWidth;  const height = window.innerHeight;   camera.aspect = width / height;  camera.updateProjectionMatrix();   renderer.setSize(width, height);  composer.setSize(width, height);}``` ## Common Effects ### Bloom (Glow) ```javascriptimport { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js"; const bloomPass = new UnrealBloomPass(  new THREE.Vector2(window.innerWidth, window.innerHeight),  1.5, // strength - intensity of glow  0.4, // radius - spread of glow  0.85, // threshold - brightness threshold); composer.addPass(bloomPass); // Adjust at runtimebloomPass.strength = 2.0;bloomPass.threshold = 0.5;bloomPass.radius = 0.8;``` ### Selective Bloom Apply bloom only to specific objects. ```javascriptimport { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js";import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js"; // Layer setupconst BLOOM_LAYER = 1;const bloomLayer = new THREE.Layers();bloomLayer.set(BLOOM_LAYER); // Mark objects to bloomglowingMesh.layers.enable(BLOOM_LAYER); // Dark material for non-blooming objectsconst darkMaterial = new THREE.MeshBasicMaterial({ color: 0x000000 });const materials = {}; function darkenNonBloomed(obj) {  if (obj.isMesh && !bloomLayer.test(obj.layers)) {    materials[obj.uuid] = obj.material;    obj.material = darkMaterial;  }} function restoreMaterial(obj) {  if (materials[obj.uuid]) {    obj.material = materials[obj.uuid];    delete materials[obj.uuid];  }} // Custom render loopfunction render() {  // Render bloom pass  scene.traverse(darkenNonBloomed);  composer.render();  scene.traverse(restoreMaterial);   // Render final scene over bloom  renderer.render(scene, camera);}``` ### FXAA (Anti-Aliasing) ```javascriptimport { ShaderPass } from "three/addons/postprocessing/ShaderPass.js";import { FXAAShader } from "three/addons/shaders/FXAAShader.js"; const fxaaPass = new ShaderPass(FXAAShader);fxaaPass.material.uniforms["resolution"].value.set(  1 / window.innerWidth,  1 / window.innerHeight,); composer.addPass(fxaaPass); // Update on resizefunction onResize() {  fxaaPass.material.uniforms["resolution"].value.set(    1 / window.innerWidth,    1 / window.innerHeight,  );}``` ### SMAA (Better Anti-Aliasing) ```javascriptimport { SMAAPass } from "three/addons/postprocessing/SMAAPass.js"; const smaaPass = new SMAAPass(  window.innerWidth * renderer.getPixelRatio(),  window.innerHeight * renderer.getPixelRatio(),); composer.addPass(smaaPass);``` ### SSAO (Ambient Occlusion) ```javascriptimport { SSAOPass } from "three/addons/postprocessing/SSAOPass.js"; const ssaoPass = new SSAOPass(  scene,  camera,  window.innerWidth,  window.innerHeight,);ssaoPass.kernelRadius = 16;ssaoPass.minDistance = 0.005;ssaoPass.maxDistance = 0.1; composer.addPass(ssaoPass); // Output modesssaoPass.output = SSAOPass.OUTPUT.Default;// SSAOPass.OUTPUT.Default - Final composited output// SSAOPass.OUTPUT.SSAO - Just the AO// SSAOPass.OUTPUT.Blur - Blurred AO// SSAOPass.OUTPUT.Depth - Depth buffer// SSAOPass.OUTPUT.Normal - Normal buffer``` ### Depth of Field (DOF) ```javascriptimport { BokehPass } from "three/addons/postprocessing/BokehPass.js"; const bokehPass = new BokehPass(scene, camera, {  focus: 10.0, // Focus distance  aperture: 0.025, // Aperture (smaller = more DOF)  maxblur: 0.01, // Max blur amount}); composer.addPass(bokehPass); // Update focus dynamicallybokehPass.uniforms["focus"].value = distanceToTarget;``` ### Film Grain ```javascriptimport { FilmPass } from "three/addons/postprocessing/FilmPass.js"; const filmPass = new FilmPass(  0.35, // noise intensity  0.5, // scanline intensity  648, // scanline count  false, // grayscale); composer.addPass(filmPass);``` ### Vignette ```javascriptimport { ShaderPass } from "three/addons/postprocessing/ShaderPass.js";import { VignetteShader } from "three/addons/shaders/VignetteShader.js"; const vignettePass = new ShaderPass(VignetteShader);vignettePass.uniforms["offset"].value = 1.0; // Vignette sizevignettePass.uniforms["darkness"].value = 1.0; // Vignette intensity composer.addPass(vignettePass);``` ### Color Correction ```javascriptimport { ShaderPass } from "three/addons/postprocessing/ShaderPass.js";import { ColorCorrectionShader } from "three/addons/shaders/ColorCorrectionShader.js"; const colorPass = new ShaderPass(ColorCorrectionShader);colorPass.uniforms["powRGB"].value = new THREE.Vector3(1.2, 1.2, 1.2); // PowercolorPass.uniforms["mulRGB"].value = new THREE.Vector3(1.0, 1.0, 1.0); // Multiply composer.addPass(colorPass);``` ### Gamma Correction ```javascriptimport { GammaCorrectionShader } from "three/addons/shaders/GammaCorrectionShader.js"; const gammaPass = new ShaderPass(GammaCorrectionShader);composer.addPass(gammaPass);``` ### Pixelation ```javascriptimport { RenderPixelatedPass } from "three/addons/postprocessing/RenderPixelatedPass.js"; const pixelPass = new RenderPixelatedPass(6, scene, camera); // 6 = pixel size composer.addPass(pixelPass);``` ### Glitch Effect ```javascriptimport { GlitchPass } from "three/addons/postprocessing/GlitchPass.js"; const glitchPass = new GlitchPass();glitchPass.goWild = false; // Continuous glitching composer.addPass(glitchPass);``` ### Halftone ```javascriptimport { HalftonePass } from "three/addons/postprocessing/HalftonePass.js"; const halftonePass = new HalftonePass(window.innerWidth, window.innerHeight, {  shape: 1, // 1 = dot, 2 = ellipse, 3 = line, 4 = square  radius: 4, // Dot size  rotateR: Math.PI / 12,  rotateB: (Math.PI / 12) * 2,  rotateG: (Math.PI / 12) * 3,  scatter: 0,  blending: 1,  blendingMode: 1,  greyscale: false,}); composer.addPass(halftonePass);``` ### Outline ```javascriptimport { OutlinePass } from "three/addons/postprocessing/OutlinePass.js"; const outlinePass = new OutlinePass(  new THREE.Vector2(window.innerWidth, window.innerHeight),  scene,  camera,); outlinePass.edgeStrength = 3;outlinePass.edgeGlow = 0;outlinePass.edgeThickness = 1;outlinePass.pulsePeriod = 0;outlinePass.visibleEdgeColor.set(0xffffff);outlinePass.hiddenEdgeColor.set(0x190a05); // Select objects to outlineoutlinePass.selectedObjects = [mesh1, mesh2]; composer.addPass(outlinePass);``` ## Custom ShaderPass Create your own post-processing effects. ```javascriptimport { ShaderPass } from "three/addons/postprocessing/ShaderPass.js"; const CustomShader = {  uniforms: {    tDiffuse: { value: null }, // Required: input texture    time: { value: 0 },    intensity: { value: 1.0 },  },  vertexShader: `    varying vec2 vUv;     void main() {      vUv = uv;      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);    }  `,  fragmentShader: `    uniform sampler2D tDiffuse;    uniform float time;    uniform float intensity;    varying vec2 vUv;     void main() {      vec2 uv = vUv;       // Wave distortion      uv.x += sin(uv.y * 10.0 + time) * 0.01 * intensity;       vec4 color = texture2D(tDiffuse, uv);      gl_FragColor = color;    }  `,}; const customPass = new ShaderPass(CustomShader);composer.addPass(customPass); // Update in animation loopcustomPass.uniforms.time.value = clock.getElapsedTime();``` ### Invert Colors Shader ```javascriptconst InvertShader = {  uniforms: {    tDiffuse: { value: null },  },  vertexShader: `    varying vec2 vUv;    void main() {      vUv = uv;      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);    }  `,  fragmentShader: `    uniform sampler2D tDiffuse;    varying vec2 vUv;     void main() {      vec4 color = texture2D(tDiffuse, vUv);      gl_FragColor = vec4(1.0 - color.rgb, color.a);    }  `,};``` ### Chromatic Aberration ```javascriptconst ChromaticAberrationShader = {  uniforms: {    tDiffuse: { value: null },    amount: { value: 0.005 },  },  vertexShader: `    varying vec2 vUv;    void main() {      vUv = uv;      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);    }  `,  fragmentShader: `    uniform sampler2D tDiffuse;    uniform float amount;    varying vec2 vUv;     void main() {      vec2 dir = vUv - 0.5;      float dist = length(dir);       float r = texture2D(tDiffuse, vUv - dir * amount * dist).r;      float g = texture2D(tDiffuse, vUv).g;      float b = texture2D(tDiffuse, vUv + dir * amount * dist).b;       gl_FragColor = vec4(r, g, b, 1.0);    }  `,};``` ## Combining Multiple Effects ```javascriptimport { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";import { RenderPass } from "three/addons/postprocessing/RenderPass.js";import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js";import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js";import { FXAAShader } from "three/addons/shaders/FXAAShader.js";import { VignetteShader } from "three/addons/shaders/VignetteShader.js";import { GammaCorrectionShader } from "three/addons/shaders/GammaCorrectionShader.js"; const composer = new EffectComposer(renderer); // 1. Render scenecomposer.addPass(new RenderPass(scene, camera)); // 2. Bloomconst bloomPass = new UnrealBloomPass(  new THREE.Vector2(window.innerWidth, window.innerHeight),  0.5,  0.4,  0.85,);composer.addPass(bloomPass); // 3. Vignetteconst vignettePass = new ShaderPass(VignetteShader);vignettePass.uniforms["offset"].value = 0.95;vignettePass.uniforms["darkness"].value = 1.0;composer.addPass(vignettePass); // 4. Gamma correctioncomposer.addPass(new ShaderPass(GammaCorrectionShader)); // 5. Anti-aliasing (always last before output)const fxaaPass = new ShaderPass(FXAAShader);fxaaPass.uniforms["resolution"].value.set(  1 / window.innerWidth,  1 / window.innerHeight,);composer.addPass(fxaaPass);``` ## Render to Texture ```javascript// Create render targetconst renderTarget = new THREE.WebGLRenderTarget(512, 512); // Render scene to targetrenderer.setRenderTarget(renderTarget);renderer.render(scene, camera);renderer.setRenderTarget(null); // Use textureconst texture = renderTarget.texture;otherMaterial.map = texture;``` ## Multi-Pass Rendering ```javascript// Multiple composers for different scenes/layersconst bgComposer = new EffectComposer(renderer);bgComposer.addPass(new RenderPass(bgScene, camera)); const fgComposer = new EffectComposer(renderer);fgComposer.addPass(new RenderPass(fgScene, camera));fgComposer.addPass(bloomPass); // Combine in render loopfunction animate() {  // Render background without clearing  renderer.autoClear = false;  renderer.clear();   bgComposer.render();   // Render foreground over it  renderer.clearDepth();  fgComposer.render();}``` ## WebGPU Post-Processing (Three.js r150+) ```javascriptimport { postProcessing } from "three/addons/nodes/Nodes.js";import { pass, bloom, dof } from "three/addons/nodes/Nodes.js"; // Using node-based systemconst scenePass = pass(scene, camera);const bloomNode = bloom(scenePass, 0.5, 0.4, 0.85); const postProcessing = new THREE.PostProcessing(renderer);postProcessing.outputNode = bloomNode; // Renderfunction animate() {  postProcessing.render();}``` ## Performance Tips 1. **Limit passes**: Each pass adds a full-screen render2. **Lower resolution**: Use smaller render targets for blur passes3. **Disable unused effects**: Toggle passes on/off4. **Use FXAA over MSAA**: Less expensive anti-aliasing5. **Profile with DevTools**: Check GPU usage ```javascript// Disable passbloomPass.enabled = false; // Reduce bloom resolutionconst bloomPass = new UnrealBloomPass(  new THREE.Vector2(window.innerWidth / 2, window.innerHeight / 2),  strength,  radius,  threshold,); // Only apply effects in high-performance scenariosconst isMobile = /iPhone|iPad|Android/i.test(navigator.userAgent);if (!isMobile) {  composer.addPass(expensivePass);}``` ## Handle Resize ```javascriptfunction onWindowResize() {  const width = window.innerWidth;  const height = window.innerHeight;  const pixelRatio = renderer.getPixelRatio();   camera.aspect = width / height;  camera.updateProjectionMatrix();   renderer.setSize(width, height);  composer.setSize(width, height);   // Update pass-specific resolutions  if (fxaaPass) {    fxaaPass.material.uniforms["resolution"].value.set(      1 / (width * pixelRatio),      1 / (height * pixelRatio),    );  }   if (bloomPass) {    bloomPass.resolution.set(width, height);  }} window.addEventListener("resize", onWindowResize);``` ## See Also - `threejs-shaders` - Custom shader development- `threejs-textures` - Render targets- `threejs-fundamentals` - Renderer setup