You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js技术问询:如何在鼠标区域周边应用着色器效果(参考activetheory.net首页)

Recreating Mouse-Reactive Shader Effects in Three.js (Like activetheory.net)

Hey there! I’ve spent some time digging into effects like the one on activetheory.net, and here’s a step-by-step breakdown of how to build something similar with Three.js.

Core Concept

The effect you’re seeing is a post-processing shader—it takes the entire rendered scene, applies a dynamic filter based on your mouse position, and outputs the final frame. The key pieces are:

  • Tracking mouse position and passing it to the shader
  • Calculating the distance from each pixel to the mouse in the fragment shader
  • Applying a localized effect (blur, color shift, distortion) that fades out as you move away from the mouse

Step-by-Step Implementation

1. Set Up the Basic Three.js Scene

First, get your core scene, camera, and renderer running. Nothing fancy here—just the foundation:

import * as THREE from 'three';
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';

// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Add some test content (replace with your own scene)
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;

2. Configure Post-Processing Pipeline

This is where the magic happens. We’ll use EffectComposer to chain render passes:

// Create composer and render pass (renders scene to a texture)
const composer = new EffectComposer(renderer);
const renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);

// Custom shader pass for mouse effect
const mouseEffectShader = {
  uniforms: {
    tDiffuse: { value: null }, // The rendered scene texture
    mouse: { value: new THREE.Vector2(0, 0) }, // Mouse position in NDC (-1 to 1)
    effectRadius: { value: 0.3 }, // Size of the effect area
    effectStrength: { value: 2.0 } // Intensity of the effect
  },
  vertexShader: `
    varying vec2 vUv;
    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
  fragmentShader: `
    uniform sampler2D tDiffuse;
    uniform vec2 mouse;
    uniform float effectRadius;
    uniform float effectStrength;
    varying vec2 vUv;

    void main() {
      // Calculate distance from current pixel to mouse
      float distance = length(vUv - mouse);
      // Smoothly fade the effect based on distance
      float strength = smoothstep(effectRadius, 0.0, distance) * effectStrength;

      // Example effect: Blur + color shift
      vec2 offset = (vUv - mouse) * strength * 0.01;
      vec4 color = texture2D(tDiffuse, vUv);
      vec4 blur1 = texture2D(tDiffuse, vUv + offset);
      vec4 blur2 = texture2D(tDiffuse, vUv - offset);
      vec4 finalColor = mix(color, (blur1 + blur2) * 0.5, strength);

      // Optional: Add a color tint to the effect area
      finalColor.r += strength * 0.1;
      finalColor.b -= strength * 0.05;

      gl_FragColor = finalColor;
    }
  `
};

const mouseEffectPass = new ShaderPass(mouseEffectShader);
composer.addPass(mouseEffectPass);

3. Track Mouse Position (Convert to NDC)

Screen coordinates (pixels) need to be converted to Normalized Device Coordinates (range: -1 to 1 for both axes) so the shader can use them correctly:

let mouse = new THREE.Vector2(0, 0);

window.addEventListener('mousemove', (event) => {
  // Convert screen position to NDC
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  // Update the shader uniform
  mouseEffectPass.uniforms.mouse.value = mouse;
});

4. Update the Render Loop

Instead of rendering directly with renderer.render(), use the composer to handle post-processing:

function animate() {
  requestAnimationFrame(animate);
  // Rotate cube for test motion
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  // Render with post-processing
  composer.render();
}
animate();

// Handle window resizing
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  composer.setSize(window.innerWidth, window.innerHeight);
});

Extra Tips for Polish

  • Mouse Easing: Add smooth interpolation to the mouse position so the effect follows the mouse more naturally (instead of jumping instantly). Example:
    let targetMouse = new THREE.Vector2(0, 0);
    let currentMouse = new THREE.Vector2(0, 0);
    
    window.addEventListener('mousemove', (event) => {
      targetMouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      targetMouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    });
    
    // In animate loop:
    currentMouse.lerp(targetMouse, 0.1); // 0.1 = easing speed
    mouseEffectPass.uniforms.mouse.value = currentMouse;
    
  • Adjust Effect Parameters: Play with effectRadius and effectStrength to match the feel you want. You can even add GUI controls to tweak these in real-time.
  • Advanced Effects: For the exact activetheory.net look, experiment with:
    • Gaussian blur (more samples for smoother blur)
    • Chromatic aberration (split RGB channels based on distance)
    • Distortion (warp the texture around the mouse)

Troubleshooting

  • If the effect isn’t showing up, double-check that you’re using the latest Three.js post-processing addons (they’re in three/addons/postprocessing/ now).
  • Make sure your shader uniforms are being updated correctly—console log the mouse values to verify.

内容的提问来源于stack exchange,提问作者Michaël

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:44:24