three.js的masking场景遮罩

新接到一个项目,让我做两个场景的遮罩,如下所示

可以控制参数,动态显示被遮罩的场景大小。

利用THREE.shaderPass自定义着色器写的,代码如下

<div id="container" style="width:100vw;height:100vh;">
	<div id="three"></div>
</div>
<script src='http://cdnjs.cloudflare.com/ajax/libs/three.js/r80/three.min.js'></script>
<script src='http://wow.techbrood.com/uploads/161101/three_post.js'></script>
<script>
	var mainContainer = document.querySelector('#container');
	var viewWidth = mainContainer.clientWidth;
	var viewHeight = mainContainer.clientHeight;
	
	var renderer = new THREE.WebGLRenderer({
		alpha: true
	});
	renderer.setSize(viewWidth, viewHeight);
	renderer.setPixelRatio(window.devicePixelRatio);
	renderer.setClearColor(0x3d3d38);
	renderer.autoClear = false;
	document.querySelector('#three').appendChild(renderer.domElement);
//创建第一个场景
	var scene = new THREE.Scene();
	var camera = new THREE.PerspectiveCamera(60, viewWidth / viewHeight, 1, 10000);
	camera.position.set(1.25, 0, 10);
	
	var box = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2));
	box.position.x = 1.5;
	scene.add(box);
	var circleTexture = new THREE.TextureLoader().load("neibu.png");
	var circle = new THREE.Mesh(new THREE.CircleGeometry(25, 64),new THREE.MeshBasicMaterial({map:circleTexture}));
	circle.position.x = 5;
	circle.position.z = -15;
	scene.add(circle);

//创建第二个场景
	var secondScene = new THREE.Scene();
	var secondGroup = new THREE.Group();
	var planeTexture = new THREE.TextureLoader().load("room.png");
	var planeGeometry = new THREE.PlaneGeometry(192, 102);
	var planeMaterial = new THREE.MeshBasicMaterial({
		map: planeTexture,
		side: THREE.DoubleSide,
		transparent: true,
		opacity: 1,
		depthTest: false
	});
	var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
	secondGroup.add(planeMesh);
	secondScene.add(secondGroup);
	secondScene.position.z = -10;
	
	var renderTargetParameters = {
		minFilter: THREE.LinearFilter,
		magFilter: THREE.LinearFilter,
		format: THREE.RGBFormat,
		stencilBuffer: false
	};
	secondScene.fbo = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, renderTargetParameters);
	scene.fbo = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, renderTargetParameters);
	//创建EffectComposer(效果组合器)对象,在该对象上,我们可以增加后期处理通道
	var compWidth = viewWidth * window.devicePixelRatio;
	var compHeight = viewHeight * window.devicePixelRatio;
	var composer = new THREE.EffectComposer(renderer, new THREE.WebGLRenderTarget(compWidth, compHeight, {
		minFilter: THREE.LinearFilter,
		magFilter: THREE.LinearFilter,
		format: THREE.RGBAFormat,
		stencilBuffer: false
	}));

	var renderPass = new THREE.RenderPass(scene, camera);
	var maskPass = new THREE.ShaderPass({
		//统一值,可以向你的着色器发信息。同样的信息会发到每一个顶点和片段
		uniforms: {
			"tDiffuse1": {
				value: null
			},
			"tDiffuse2": {
				value: null
			}
		},
		//顶点着色器,允许你修改每一个传入的顶点的位置
		vertexShader: [
			"varying vec2 vUv;",
			"void main() {",
			"vUv = uv;",
			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
			"}"

		].join("\n"),
		//像素着色器,定义的是每个传入的像素的颜色
		fragmentShader: [
			"uniform sampler2D tDiffuse1;",
			"uniform sampler2D tDiffuse2;",
			"varying vec2 vUv;",
			"void main() {",
			"vec4 texel1 = texture2D( tDiffuse1, vUv );",
			"vec4 texel2 = texture2D( tDiffuse2, vUv );",
			"if (vUv.x >0.33 && vUv.x <  0.66 && vUv.y >0.33 && vUv.y <  0.66) {",
				"gl_FragColor = texel1;",
			"} else {",
				"gl_FragColor = texel2;",
			"}",
			"}"
		].join("\n")
	});
	composer.addPass(renderPass);
	composer.addPass(maskPass);
	maskPass.renderToScreen = true;//将渲染结果输出到屏幕上
	
//给渲染器传递tDiffuse1的参数,使我们想要的纹理贴到渲染通道上面
	function render() {
		renderer.render(scene, this.camera, scene.fbo, true);
		maskPass.uniforms.tDiffuse1.value = scene.fbo.texture;
		renderer.render(secondScene, this.camera, secondScene.fbo, true);
		maskPass.uniforms.tDiffuse2.value = secondScene.fbo.texture;
		composer.render();
	}

	function tick() {
		render();
		requestAnimationFrame(tick);
	}
	tick();
</script>

欢迎转载,转载需带着文章出处链接~~

 

 

 

 

发表评论

邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据