Three.js:无法将背景通道与轮廓通道相结合
Posted
技术标签:
【中文标题】Three.js:无法将背景通道与轮廓通道相结合【英文标题】:Three.js: Not able to combine background pass with outline pass 【发布时间】:2020-07-06 21:31:49 【问题描述】:我想将网格渲染到背景场景中,这样我就可以使用更强大的着色器(渐变、特殊效果……)自定义背景。当用户将鼠标悬停在主场景网格上时,我还想使用outlinePass 效果。
我不确定它是否不可行,或者我尝试清除渲染器的方式是否有问题。
这是目前的代码 (jsfiddle demo):
var container, stats;
var camera, scene, renderer, controls, backgroundScene, backgroundCamera;
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var selectedObjects = [];
var composer, effectFXAA, outlinePass;
function init()
backgroundCamera = new THREE.OrthographicCamera(
-1, 1, 1, -1, -1, 0);
backgroundScene = new THREE.Scene()
const fragmentShader = `
void main()
gl_FragColor = vec4(0.7, 0, 0, 1.);
`
backgroundScene.add(new THREE.Mesh(
new THREE.PlaneBufferGeometry(2, 2),
new THREE.ShaderMaterial(
fragmentShader
)));
container = document.createElement( 'div' );
document.body.appendChild( container );
var width = window.innerWidth;
var height = window.innerHeight;
renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.setSize( width, height );
renderer.autoClear = false
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, width / height, 0.1, 100 );
camera.position.set( 0, 0, 8 );
controls = new THREE.OrbitControls( camera, renderer.domElement );
scene.add( new THREE.AmbientLight( 0xaaaaaa, 0.2 ) );
var light = new THREE.DirectionalLight( 0xddffdd, 0.6 );
light.position.set( 1, 1, 1 );
scene.add( light );
var geometry = new THREE.TorusBufferGeometry( 1, 0.3, 16, 100 );
var material = new THREE.MeshPhongMaterial( color: 0xffaaff );
var torus = new THREE.Mesh( geometry, material );
torus.position.z = - 4;
scene.add( torus );
composer = new THREE.EffectComposer( renderer );
var backgroundPass = new THREE.RenderPass(
backgroundScene,
backgroundCamera);
composer.addPass( backgroundPass );
backgroundPass.clear = false
var renderPass = new THREE.RenderPass( scene, camera );
composer.addPass( renderPass );
renderPass.clear = false
outlinePass = new THREE.OutlinePass(
new THREE.Vector2(
window.innerWidth, window.innerHeight ), scene, camera );
outlinePass.clear = false
composer.addPass( outlinePass );
window.addEventListener( 'resize', onWindowResize, false );
window.addEventListener( 'mousemove', onTouchMove );
var outputPass = new THREE.ShaderPass( THREE.CopyShader );
outputPass.renderToScreen = true;
outputPass.clear = true
composer.addPass( outputPass );
function onTouchMove( event )
var x, y;
if ( event.changedTouches )
x = event.changedTouches[ 0 ].pageX;
y = event.changedTouches[ 0 ].pageY;
else
x = event.clientX;
y = event.clientY;
mouse.x = ( x / window.innerWidth ) * 2 - 1;
mouse.y = - ( y / window.innerHeight ) * 2 + 1;
checkIntersection();
function checkIntersection()
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects([scene], true);
outlinePass.selectedObjects = intersects.length
? [intersects[ 0 ].object]
: []
function onWindowResize()
var width = window.innerWidth;
var height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
composer.setSize( width, height );
function renderLoop()
requestAnimationFrame(renderLoop);
controls.update();
renderer.clear()
composer.render();
init()
renderLoop()
结果看起来像是一个缓冲区清除问题,但不知道我应该如何解决它。
【问题讨论】:
【参考方案1】:你在正确的轨道上。您唯一需要更改的是:
-
摆脱
renderer.autoClear = false;
摆脱所有xxPass.clear = false;
。您唯一需要保留的是renderPass.clear = false
,这样它就不会覆盖红色着色器输出。
以下是修改后的结果:
https://jsfiddle.net/marquizzo/mwazr0yd/
(我注意到还有一点,您的outputPass
没有向渲染结果添加任何内容。您可以摆脱这个额外的步骤,只需使用outlinePass.renderToScreen = true;
将outlinePass 渲染到屏幕上)
【讨论】:
感谢这解决了演示中的问题,不幸的是我的应用程序仍然有问题。正如我最初在那个问题中提到的那样:discourse.threejs.org/t/…。添加轮廓通道将完全遮蔽场景。任何见解可能有什么问题?以上是关于Three.js:无法将背景通道与轮廓通道相结合的主要内容,如果未能解决你的问题,请参考以下文章
使用vue学习three.js之渲染后期处理-简单的后期处理通道FilmPass(类似电视效果)DotScreenPass(将场景输出成点集)GlitchPass(电磁风暴效果)
使用vue学习three.js之渲染后期处理-使用UnrealBloomPass通道在场景中添加泛光效果,三维物体表面发光效果