
Threejs Postprocessing
Add EffectComposer passes such as bloom, DOF, and custom screen-space shaders to a Three.js scene.
Overview
Threejs-postprocessing is an agent skill for the Build phase that adds Three.js EffectComposer post-processing such as bloom, DOF, and custom screen-space effects.
Install
npx skills add https://github.com/cloudai-x/threejs-skills --skill threejs-postprocessingWhat is this skill?
- EffectComposer setup with RenderPass as the first pass and composer.render() in the animate loop
- UnrealBloomPass recipe with strength, radius, and threshold parameters
- Guidance for bloom, depth-of-field, blur, glow, and color-grading style effects
- Screen-space and custom shader extension patterns on top of three/addons postprocessing
- Explicit warning to render via composer instead of renderer alone when passes are stacked
Adoption & trust: 3.5k installs on skills.sh; 2.3k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Three.js scene renders correctly but you lack a clear pattern for EffectComposer, pass ordering, and glow or grading effects.
Who is it for?
Indie devs and solo builders already using Three.js who need bloom, blur, glow, or custom screen shaders quickly.
Skip if: Projects not using Three.js/WebGL, or teams that only need 2D CSS effects with no 3D pipeline.
When should I use this skill?
Adding visual effects, color grading, blur, glow, or creating custom screen-space shaders in Three.js.
What do I get? / Deliverables
You wire composer.addPass flows, tune passes like UnrealBloomPass, and ship an animation loop that renders through the composer for the visual effect you wanted.
- EffectComposer and RenderPass integration code
- Configured effect passes (e.g. UnrealBloomPass) in the render loop
Recommended Skills
Journey fit
Build is where visual polish and rendering pipelines are implemented in the product, not where you measure launch SEO or run production monitoring. Frontend covers WebGL/Three.js rendering loops and composer integration that replace raw renderer.render() in the animation loop.
How it compares
A procedural Three.js recipe skill—not an MCP server or a full render-farm deployment guide.
Common Questions / FAQ
Who is threejs-postprocessing for?
Solo builders and small teams implementing browser 3D who want copy-paste-correct EffectComposer patterns from three/addons postprocessing.
When should I use threejs-postprocessing?
During Build frontend work when adding visual effects, color grading, blur, glow, or custom screen-space shaders to an existing Three.js scene and renderer.
Is threejs-postprocessing safe to install?
It is documentation-style procedural guidance with no mandated network or secret access; still review the Security Audits panel on this page before adding any skill to your agent.
SKILL.md
READMESKILL.md - Threejs Postprocessing
# Three.js Post-Processing ## Quick Start ```javascript import * 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 composer const composer = new EffectComposer(renderer); // Render scene const renderPass = new RenderPass(scene, camera); composer.addPass(renderPass); // Add bloom const 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 renderer function animate() { requestAnimationFrame(animate); composer.render(); // NOT renderer.render() } ``` ## EffectComposer Setup ```javascript import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js"; import { RenderPass } from "three/addons/postprocessing/RenderPass.js"; const composer = new EffectComposer(renderer); // First pass: render scene const renderPass = new RenderPass(scene, camera); composer.addPass(renderPass); // Add more passes... composer.addPass(effectPass); // Last pass should render to screen effectPass.renderToScreen = true; // Default for last pass // Handle resize function 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) ```javascript import { 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 runtime bloomPass.strength = 2.0; bloomPass.threshold = 0.5; bloomPass.radius = 0.8; ``` ### Selective Bloom Apply bloom only to specific objects. ```javascript import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js"; import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js"; // Layer setup const BLOOM_LAYER = 1; const bloomLayer = new THREE.Layers(); bloomLayer.set(BLOOM_LAYER); // Mark objects to bloom glowingMesh.layers.enable(BLOOM_LAYER); // Dark material for non-blooming objects const 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 loop function render() { // Render bloom pass scene.traverse(darkenNonBloomed); composer.render(); scene.traverse(restoreMaterial); // Render final scene over bloom renderer.render(scene, camera); } ``` ### FXAA (Anti-Aliasing) ```javascript import { 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 resize function onResize() { fxaaPass.material.uniforms["resolution"].value.set( 1 / window.innerWidth, 1 / window.innerHeight, ); } ``` ### SMAA (Better Anti-Aliasing) ```javascript import { SMAAPass } from "three/addo