Skip to content
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

Stencil params getting out of sync. #28252

Open
DVLP opened this issue May 1, 2024 · 6 comments
Open

Stencil params getting out of sync. #28252

DVLP opened this issue May 1, 2024 · 6 comments

Comments

@DVLP
Copy link
Contributor

DVLP commented May 1, 2024

Description

Calls to stencil functions like gl.stencilFunc, gl.stencilOp or gl.stencilMask are ignored when gl.STENCIL_TEST is not enabled. That's how it works in webgl (Edit: no it doesn't, I was mislead by AI which lead me to a long state cache modifying misadventure and the real issue is in the comments). Regardless of that WebGLState.js is caching these values as current. preventing them from being set correctly when the stencil buffer is enabled afterwards and the value is the same as cached.

Reproduction steps

Rendering an empty scene should be enough to reproduce the issue.
Renderer clears the frame and calls this.state.buffers.stencil.setMask( 0xffffffff );

At this point the cached currentStencilMask will be set to 0xffffffff but the native call to gl.stencilMask is ignored because gl.STENCIL_TEST is not enabled. The state is now out of sync and subsequent calls with the same value will be ignored because currentStencilMask will match them.

  1. in WebglState.js under line currentStencilMask = stencilMask; add a new line console.log('Stencil mask cached correctly', gl.getParameter(gl.STENCIL_WRITEMASK) === currentStencilMask)
  2. Create a basic scene, run and look in the console

Code

Live example

No live example, requires core modification

Screenshots

No response

Version

164

Device

Desktop

Browser

Chrome

OS

Windows

@Mugen87
Copy link
Collaborator

Mugen87 commented May 3, 2024

Calls to stencil functions like gl.stencilFunc, gl.stencilOp or gl.stencilMask are ignored when gl.STENCIL_TEST is not enabled.

Why does the following fiddle work then though? Stencil test is disabled but using gl.stencilMask() is not ignored.

https://jsfiddle.net/aw8c3d2j/

@DVLP
Copy link
Contributor Author

DVLP commented May 3, 2024

I tried this code and indeed it worked. This is very interesting as I've been testing this with a debugger in a larger environment and gl.stencilMask was not persisting the setting. I'm working on a library to synchronize webgl context state with an ability to save and restore a snapshot. For one of the blocks of code GPT explained it requires enabling stencil test to set stencil parameters. Then I checked if that's the case, and it appeared it was. If I'll be able to reproduce this issue with gl.stencilMask not persisting the state and finding what's the cause I'll reopen.

  var stencilTestEnabled = gl.state.feats[gl.STENCIL_TEST]
  if (!stencilTestEnabled) gl.enable(gl.STENCIL_TEST)
  gl.stencilFunc(s.stencilFunc[0], s.stencilFunc[1], s.stencilFunc[2])
  gl.stencilOp(s.stencilOp[0], s.stencilOp[1], s.stencilOp[2])
  gl.stencilMask(s.stencilMask)
// ...
  if (!stencilTestEnabled) gl.disable(gl.STENCIL_TEST)

@DVLP DVLP closed this as completed May 3, 2024
@DVLP DVLP reopened this May 3, 2024
@DVLP
Copy link
Contributor Author

DVLP commented May 3, 2024

Ok I managed to reproduce the issue. It's not about stencil test being on or off but but Chrome not settnig the value as 0xFFFFFFFF (max 32 bit value) but changing it to 0x7FFFFFFF (max 31 bit value). It seems to be the highest value it accepts. When setting the value as 0x80000000 it also changes it to 0x7FFFFFFF. Could be a bug or limitation in Chrome or just how it works. Try in Firefox and then Chrome on Windows.
https://jsfiddle.net/d6fqme4t/

@Mugen87
Copy link
Collaborator

Mugen87 commented May 3, 2024

I can reproduce on macOS as well. When logging the values to the console, Firefox shows 4294967295 (decimal representation of 0xFFFFFFFF). Chrome (and Safari) log 2147483647 (decimal representation of 0x7FFFFFFF).

According to the spec, mask is a GLuint which has 32 bit. It's max value is 4294967295 so my first impression is the behavior in Chrome isn't spec conform.

Since we use 0xffffffff as a clear value in WebGLRenderer.clear(), that explains the root cause.

@DVLP
Copy link
Contributor Author

DVLP commented May 3, 2024

In this case it's not a Three issue but Chrome. Interesting stuff.

@Mugen87
Copy link
Collaborator

Mugen87 commented May 4, 2024

I have filed a Chromium bug: https://issues.chromium.org/issues/338634235

@Mugen87 Mugen87 changed the title Stencil params getting out of sync when stencil test is disabled Stencil params getting out of sync. May 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants