Three.js: Setting clearColor to black doesn't work if sprites are in scene

Created on 14 Mar 2017  路  11Comments  路  Source: mrdoob/three.js

Description of the problem

If Sprites are in the scene, the clear color cannot be changed back to black

http://jsfiddle.net/ak35o645/7/

uncomment out the //scene.add( sprite ); to see bug

Three.js version
  • [ X ] Dev
  • [ X ] r84
Browser
  • [x] All of them
  • [ ] Chrome
  • [ ] Firefox
  • [ ] Internet Explorer
OS
  • [x] All of them
  • [ ] Windows
  • [ ] macOS
  • [ ] Linux
  • [ ] Android
  • [ ] iOS
Hardware Requirements (graphics card, VR Device, ...)
Bug

Most helpful comment

Nice find.

Simpler fiddle: http://jsfiddle.net/ak35o645/11/

SpritePlugin calls renderer.resetGLState() which calls state.reset() which does this:

currentColorClear.set( 0, 0, 0, 1 );

That prevents state.buffers.color.setClear( ) from working properly in the special case in which the desired color is black and the desired alpha is 1.

All 11 comments

Nice find.

Simpler fiddle: http://jsfiddle.net/ak35o645/11/

SpritePlugin calls renderer.resetGLState() which calls state.reset() which does this:

currentColorClear.set( 0, 0, 0, 1 );

That prevents state.buffers.color.setClear( ) from working properly in the special case in which the desired color is black and the desired alpha is 1.

Should Reset set the clearColor of GL state? or should reset not be called for the colorBuffer, in this situation?

I am not sure of a clean solution to this issue. There, indeed, may be more state changes going on than are needed.

As of r86, this is now also an issue even without sprites in the scene.

It looks like the following commit may have changed how the initial clear color state gets set (or, rather, doesn't get set), so it ends up in the default opaque-black state from the get go, without state.reset() even being called.

https://github.com/mrdoob/three.js/commit/9b260d8970dc68df2cd5cd48c50dfc2c3b792197#diff-c0e88b98497597a015ecf238e91ac3a0L328

It feels like WebGLState.ColorBuffer needs an internal variable state that means "currentColorClear has not been set", distinct from "currentColorClear has been set to opaque black".

PR for that referenced above.

An alternate approach might be to treat opaque black as the base state, but ensure that gl.clearColor( r, g, b, a ) is invoked both on initial startup and on reset().

What I did in my code base was this on reset:
currentColorClear.set( -1, -1, -1, -1 );

This is an invalid color, so hence it would set the glClearColor to the requested value for whatever state was running.

As of r86, this is now also an issue even without sprites in the scene.

@lojjic Can you demonstrate the issue with a fiddle?

Certainly, here go: https://jsfiddle.net/hdc3soqy/

I expect that can be fixed by just setting

var currentColorClear = new Vector4( 0, 0, 0, 0 );

and in reset()

currentColorClear.set( 0, 0, 0, 0 );

I think that will work because the initial clear color is all-zeros.

If not, then set both to ( - 1, 0, 0, 0 ).

@WestLangley Yes you're right, since 0,0,0,0 is the default clearColor value in WebGLRenderingContext, it makes sense to set that as the default. That will fix the new r86 issue.

Then, to prevent this ticket's original issue, the reset method should ensure gl.clearColor() is updated, so that currentColorClear and the GL context's clearColor are never out of sync.

If that sounds right to you, I'll issue another PR shortly.

@lojjic It is best to restrict the gl call to one place, and call it only when necessary. Thanks for bringing this issue to the forefront, though.

And thanks, @Neesnu.

Was this page helpful?
0 / 5 - 0 ratings