gl.clear would not clear render target if state mask is currently set (i.e. by previous material)
Can you please provide sufficient context so the issue can be reproduced? A live demo would be helpful.
Our case is a bit complex, but you can easily reproduce the issue in render-to-texture webgl example (code below).
We are using renderBufferDirect along with regular scene rendering to prepare some small stuff (lots of dynamic tiles) in the background and avoid scene graph traversal. The result is tile material override the masks and clear not working
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var cameraRTT, camera, sceneRTT, sceneScreen, scene, renderer, zmesh1, zmesh2;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var rtTexture, material, quad;
var delta = 0.01;
//n3d:
var noDepthMaterial = null
var noDepthGeometry = null
var noDepthMesh = null
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 100;
cameraRTT = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, -10000, 10000 );
cameraRTT.position.z = 100;
//
scene = new THREE.Scene();
sceneRTT = new THREE.Scene();
sceneScreen = new THREE.Scene();
var light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 0, 1 ).normalize();
sceneRTT.add( light );
light = new THREE.DirectionalLight( 0xffaaaa, 1.5 );
light.position.set( 0, 0, -1 ).normalize();
sceneRTT.add( light );
rtTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBFormat } );
material = new THREE.ShaderMaterial( {
uniforms: { time: { value: 0.0 } },
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragment_shader_pass_1' ).textContent
} );
var materialScreen = new THREE.ShaderMaterial( {
uniforms: { tDiffuse: { value: rtTexture.texture } },
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragment_shader_screen' ).textContent,
depthWrite: false
} );
var plane = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );
quad = new THREE.Mesh( plane, material );
quad.position.z = -100;
sceneRTT.add( quad );
var geometry = new THREE.TorusGeometry( 100, 25, 15, 30 );
var mat1 = new THREE.MeshPhongMaterial( { color: 0x555555, specular: 0xffaa00, shininess: 5 } );
var mat2 = new THREE.MeshPhongMaterial( { color: 0x550000, specular: 0xff2200, shininess: 5 } );
zmesh1 = new THREE.Mesh( geometry, mat1 );
zmesh1.position.set( 0, 0, 100 );
zmesh1.scale.set( 1.5, 1.5, 1.5 );
sceneRTT.add( zmesh1 );
zmesh2 = new THREE.Mesh( geometry, mat2 );
zmesh2.position.set( 0, 150, 100 );
zmesh2.scale.set( 0.75, 0.75, 0.75 );
sceneRTT.add( zmesh2 );
quad = new THREE.Mesh( plane, materialScreen );
quad.position.z = -100;
sceneScreen.add( quad );
var n = 5,
geometry = new THREE.SphereGeometry( 10, 64, 32 ),
material2 = new THREE.MeshBasicMaterial( { color: 0xffffff, map: rtTexture.texture } );
for( var j = 0; j < n; j ++ ) {
for( var i = 0; i < n; i ++ ) {
var mesh = new THREE.Mesh( geometry, material2 );
mesh.position.x = ( i - ( n - 1 ) / 2 ) * 20;
mesh.position.y = ( j - ( n - 1 ) / 2 ) * 20;
mesh.position.z = 0;
mesh.rotation.y = - Math.PI / 2;
scene.add( mesh );
}
}
//n3d:
var vertices = new Float32Array( [
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0
] );
noDepthGeometry = new THREE.BufferGeometry()
noDepthGeometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) )
noDepthMaterial = new THREE.MeshBasicMaterial( { color: 0xffffff } );
noDepthMaterial.depthWrite = false
noDepthMesh = new THREE.Mesh( noDepthGeometry, noDepthMaterial )
noDepthMesh.position.z = 10
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.autoClear = false;
document.body.appendChild( renderer.domElement );
stats = new Stats();
document.body.appendChild( stats.dom );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
}
function onDocumentMouseMove( event ) {
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY );
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
var time = Date.now() * 0.0015;
camera.position.x += ( mouseX - camera.position.x ) * .05;
camera.position.y += ( - mouseY - camera.position.y ) * .05;
camera.lookAt( scene.position );
if ( zmesh1 && zmesh2 ) {
zmesh1.rotation.y = - time;
zmesh2.rotation.y = - time + Math.PI / 2;
}
if ( material.uniforms.time.value > 1 || material.uniforms.time.value < 0 ) {
delta *= -1;
}
material.uniforms.time.value += delta;
renderer.clear();
// Render first scene into texture
renderer.render( sceneRTT, cameraRTT, rtTexture, true );
// Render full screen quad with generated texture
renderer.render( sceneScreen, cameraRTT );
//n3d:
scene.onAfterRender = () => {
renderer.renderBufferDirect( camera, null, noDepthGeometry, noDepthMaterial, noDepthMesh, null )
}
// Render second scene to screen
// (using first scene as regular texture)
renderer.render( scene, camera );
}
I've tried to create a fiddle of your code but i've realized you've missed to copy the corresponding vertex and fragment shader.
Please setup a live example so it's easier for us to analyze your problem: https://jsfiddle.net/f2Lommf5/
I revisited this issue and I think there is a bug in three.js. The problem is that the renderer executes Scene.onAfterRender() too late. If users performs rendering operations in the callback, they overwrite the final settings for the depth and color buffer (see comment):
The problem is the OP performs a rendering with a material where depthWrite is set to false and thus overwrites the setting. Subsequent clears do not work properly anymore. The solution is to execute Scene.onAfterRender() a little bit earlier.
@szhuchkov Sorry that it takes over a year to fix the issue 馃槄 . Better late than never^^!
Most helpful comment
Can you please provide sufficient context so the issue can be reproduced? A live demo would be helpful.