- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 36.1k
WebGLRenderer: deprecated renderTarget and forceClear from render() #15571
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…d forceClear from WebGLRenderer.render()
| I only vote to merge the PR if the codebase (examples/docs) is also changed. Otherwise there are a lot of warnings all over the repository. | 
| Makes sense. I'm on it. | 
| Ok everything should be updated. The docs in englisch I changed as well but unfortunately I don't know Chinese... | 
| Is there anything that I need to change for this to be merged? | 
| Thanks! | 
| Ops! Seems like we overlooked something and this PR broke many examples. https://raw.githack.com/mrdoob/three.js/dev/examples/#webgl_animation_cloth Do you mind taking a look? | 
| Sure! | 
| Turns out I somehow forgot to restore the render target after the shadow map was rendered. Sorry about that! | 
| Updated the migration guide^^ https://github.com/mrdoob/three.js/wiki/Migration-Guide#r101--r102 | 
| 
 No worries! | 
| I have tested all examples in  https://raw.githack.com/mrdoob/three.js/dev/examples/webgl_effects_anaglyph.html black screen and the following warning: [.WebGL-0x7f9b460c1c00]GL ERROR :GL_INVALID_OPERATION : glDrawElements: Source and destination textures of the draw are the same. https://raw.githack.com/mrdoob/three.js/dev/examples/webgl_materials_cubemap_dynamic.html black screen and the following warning: [.WebGL-0x7ffabc003800]RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering. https://raw.githack.com/mrdoob/three.js/dev/examples/webgl2_multisampled_renderbuffers.html black screen on the left and no warning https://raw.githack.com/mrdoob/three.js/dev/examples/webgldeferred_animation.html black screen and no warnings All three examples work with the previous commit in  @maccesch Can you please have a look at these? | 
| Sure, on it. | 
| Updated the list... | 
| The box selection works for me without any errors. Just to make sure: Did you rebuild first? | 
| 
 | 
| I think you have to ensure that render targets are at certain points unset. For example here: three.js/examples/js/effects/AnaglyphEffect.js Lines 145 to 148 in efe122c 
 The second call of  renderer.setRenderTarget( _renderTargetR );
renderer.clear();
renderer.render( scene, _stereo.cameraR );
renderer.setRenderTarget( null ); // FIX
renderer.render( _scene, _camera );I guess the other demos needs similar fixes. | 
| @mrdoob @WestLangley I guess we were not aware of this side effect. Problems like mentioned in my previous post will break app code. | 
| I was aware of it. See #15420 (comment). | 
| Who is responsible for updating the typescript files when the API is changed? | 
| 
 I would say the one who is doing the change. But for this one, see #15783 In any event, let me update the migration guide to make things more clear. | 
| This one is also broken: https://raw.githack.com/mrdoob/three.js/dev/examples/webgl_furnace_test.html The spheres should not be visible. | 
| @mrdoob What is the pattern you want users to use? In other words, what is the convention we are adopting? renderer.setRenderTarget( null ); // always set prior to each render call
renderer.render( scene, camera );or renderer.getRenderTarget( previousRenderTarget );
renderer.setRenderTarget( newRenderTarget );
renderer.render( scene, camera );
renderer.setRenderTarget( previousRenderTarget ); // always restore to previous render target | 
| 
 That's correct, yes. About the other point: It's more about implementing a policy like previously mentioned here: #15571 (comment). I would save/restore the render target at the place where it is actually changed. Along other properties like clear alpha or clear color. | 
| Sorry to bug in, but this seems like a weird change. Having the  instead of just writing 2 lines: Especially if I do not want to think about the state-machine with the  I see the issue this entire thing started from. That this way it was confusing to clear a render target without calling  Having a state-machine in the library does not have to mean that the users must also use the library as a state-machine. Just like WebGL is a state-machine, but Three.js abstracts it away for the user. | 
| Sorry for the delay and thanks for the patience and discourse guys! In my eyes, the actual issue here is  The  this.update = function ( renderer, scene ) {
    if ( this.parent === null ) this.updateMatrixWorld();
    var currentRenderTarget = renderer.getRenderTarget();
    var renderTarget = this.renderTarget;
    var generateMipmaps = renderTarget.texture.generateMipmaps;
    renderTarget.texture.generateMipmaps = false;
    renderer.setRenderTarget( renderTarget, 0 );
    renderer.render( scene, cameraPX );
    renderer.setRenderTarget( renderTarget, 1 );
    renderer.render( scene, cameraNX );
    renderer.setRenderTarget( renderTarget, 2 );
    renderer.render( scene, cameraPY );
    renderer.setRenderTarget( renderTarget, 3 );
    renderer.render( scene, cameraNY );
    renderer.setRenderTarget( renderTarget, 4 );
    renderer.render( scene, cameraPZ );
    renderTarget.texture.generateMipmaps = generateMipmaps;
    renderer.setRenderTarget( renderTarget, 5 );
    renderer.render( scene, cameraNZ );
    renderer.setRenderTarget( currentRenderTarget );
}; | 
| 
 That's a fair point. Should we introduce  | 
| 
 It was indeed convenient, but it also confused users. As per brevity of code, I'm hoping we'll eventually create something like what I proposed here. So your 2 lines of code will be even shorter: renderTarget.render( scene, camera );
renderer.render( scene, camera ); | 
| 
 But that is even more confusing. In that case both the  var screen = new THREE.WebGLScreen(...);
screen.render(scene, camera);
var target = new THREE.WebGLRenderTarget(...);
target.render(scene, camera);Even in that case it seems weird. Does a target or a screen really should have functionality to render? They both seem rather like containers for the end result, rather than the objects that actually know how to call the pipeline and render. The final example in your post does keep the idea that renderers render, but it still mixes apples and oranges. Like then there should also be a  In both cases I don't currently see how does the current  I hope it all works out somehow, but currently it seems difficult to see the logic behind this. | 
| I also find it a bit off semantically if my renderTarget would have to render itself. It's a target for a renderer, not a renderer itself. I would assume that the renderer would do the rendering, and I would tell it -what- to render, explicitly. Relying on some other function that had been called previously, maybe even by a different component/class, could be a source of confusion. Has there been any thoughts into using a parameter object instead of hardcoded parameters like there is with Mesh's etc? No set parameter order, allows for future expansion, is explicit, and doesn't rely on multiple function calls in specific order. Render thyself Render something else using optional property object or if you want to get fancy and replace into a one liner, it could take a target array and render them in order ;)  | 
| Okay, we'll cross that bridge when we come to it. | 
| After debugging for a while now I think I know why  In a scenario like this, things are going to break: renderer.autoClearDepth = false;
renderer.autoClearStencil = false;
renderer.clear(); // clears everything
renderer.render( scene, camera, renderTarget, forceClear ); // only clears colorIn context of  if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );But this solutions seems a hack from my point of view. Maybe  | 
| To sum it up: Just calling  | 
| 
 I actually wanted to vote for the following style. It's just a more safe approach when users copy code. var previousRenderTarget = renderer.getRenderTarget();
renderer.setRenderTarget( newRenderTarget );
renderer.render( scene, camera );
renderer.setRenderTarget( previousRenderTarget ); | 
| Thanks for investigating this @Mugen87. It's great to be aware of that breakage, but it gets to show how fragile the current design was. I think the new approach will make the code more clear. | 
| In this case we should remove  An other option might be to change the way of how  renderer.setClearState( true, false, false ); // only clear color but not the depth and stencil buffer
renderer.clear();This would be closer to the "state machine" concept. The former parameters of  | 
| @Mugen87 Thanks for that insight on  Do you think that instead of having just a broad  | 
| I think a quick fix like this would be okay: This approach is also used at other places like: 
 The code could be added in  
 
 | 
| It looks like this PR introduced references to  | 
| Can you please elaborate in more detail what you mean? | 
| sure. the use of  | 
| @Mugen87 Should we then maybe add the arguments back but as  | 
| @gfodor I'm afraid we have to process the deprecated parameters in some way, otherwise a lot of code will break. User should still be able to pass  Um, this issue is an unfortunate side effect nobody was aware of. 
 This is the only solution I can think of right now, too. It will clutter the method signature but at least the memory allocation is gone. And we don't have to document these parameters. @mrdoob What do you think? | 
| Does anyone here know if the modern JIT compilers still allocate memory every frame for  If they still allocate, I would like to suggest to avoid it. For example we might simply remove the checking  | 
| @takahirox removing these sounds good to me 👍 | 
resolves #15420