Three.js - 如何在鼠标区域周围应用着色器效果?

时间:2018-01-28 14:27:53

标签: javascript three.js webgl

我想知道如何使用Three.js在鼠标区域周围应用着色器效果 就像在本网站的主页上一样:https://activetheory.net/

我很想找到一些线索或例子。非常感谢你

1 个答案:

答案 0 :(得分:4)

您可以编写自己的后处理着色器,跟踪鼠标。

基于模糊后处理着色器的一个非常粗略的示例:



var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 15);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

var cubes = [];

for (let i = 0; i < 500; i++) {
  let cube = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({
    color: Math.random() * 0x777777 + 0x777777,
    wireframe: true
  }));
  cube.position.set(THREE.Math.randFloatSpread(10), THREE.Math.randFloatSpread(10), THREE.Math.randFloatSpread(10));
  scene.add(cube);
  cubes.push(cube);
}

var composer = new THREE.EffectComposer(renderer);
composer.addPass(new THREE.RenderPass(scene, camera));

var hblur = new THREE.ShaderPass(THREE.HorizontalBlurShader);
composer.addPass(hblur);

var vblur = new THREE.ShaderPass(THREE.VerticalBlurShader);
console.log(vblur);
vblur.renderToScreen = true;
composer.addPass(vblur);

var mouse = new THREE.Vector2();

window.addEventListener("mousemove", function(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}, false)

render();

function render() {
  requestAnimationFrame(render);
  cubes.forEach((cube, index) => {
    cube.rotation.x += 0.0001 * index;
    cube.rotation.y += 0.0001 * index;
    cube.rotation.z += 0.0001 * index;
  });
  hblur.uniforms.mouse.value.copy(mouse);
  vblur.uniforms.mouse.value.copy(mouse);
  composer.render(scene, camera);
}
&#13;
body {
  overflow: hidden;
  margin: 0;
}
&#13;
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

<script src="https://threejs.org/examples/js/shaders/CopyShader.js"></script>
<script>
  THREE.HorizontalBlurShader = {

    uniforms: {

      "tDiffuse": {
        value: null
      },
      "h": {
        value: 1.0 / 256.0
      },
      "mouse": {
        value: new THREE.Vector2()
      },
      "ratio": {
        value: window.innerWidth / window.innerHeight
      }
    },

    vertexShader: `
    varying vec2 vUv;
    
		void main() {
			vUv = uv;
			gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    }`,
    fragmentShader: `
		uniform sampler2D tDiffuse;
		uniform float h;
    uniform vec2 mouse;
    uniform float ratio;
		varying vec2 vUv;

	  void main() {
      vec2 uv = vUv;
      uv = -1. + 2. * uv;
      uv -= mouse;
      uv.x *= ratio;
      if ( length(uv) > 0.25 ) {
        gl_FragColor = texture2D(tDiffuse, vUv);
      } 
      else{

        vec4 sum = vec4( 0.0 );

        sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;
        sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;
        sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;
        sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;
        sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;
        sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;
        sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;
        sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;
        sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;

        gl_FragColor = sum;
      }

		}`
  };
</script>
<script>
  THREE.VerticalBlurShader = {

    uniforms: {

      "tDiffuse": {
        value: null
      },
      "v": {
        value: 1.0 / 256.0
      },
      "mouse": {
        value: new THREE.Vector2()
      },
      "ratio": {
        value: window.innerWidth / window.innerHeight
      }

    },

    vertexShader: `
    varying vec2 vUv;
    
		void main() {
			vUv = uv;
			gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    }`,

    fragmentShader: `

		uniform sampler2D tDiffuse;
		uniform float v;
    uniform vec2 mouse;
    uniform float ratio;
		varying vec2 vUv;

	  void main() {
      vec2 uv = vUv;
      uv = -1. + 2. * uv;
      uv -= mouse;
      uv.x *= ratio;
      if ( length(uv) > 0.25 ) {
        gl_FragColor = texture2D(tDiffuse, vUv);
      } 
      else{
        vec4 sum = vec4( 0.0 );

        sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;
        sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;
        sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;
        sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;
        sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;
        sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;
        sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;
        sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;
        sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;

        gl_FragColor = sum;
      }

		}`
  };
</script>

<script src="https://threejs.org/examples/js/postprocessing/EffectComposer.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/RenderPass.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/MaskPass.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/ShaderPass.js"></script>
&#13;
&#13;
&#13;