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

WebGLMultisampleRenderTarget not support DepthTexture ? #18876

Closed
2 of 7 tasks
yj7810520113 opened this issue Mar 12, 2020 · 7 comments · Fixed by #18904
Closed
2 of 7 tasks

WebGLMultisampleRenderTarget not support DepthTexture ? #18876

yj7810520113 opened this issue Mar 12, 2020 · 7 comments · Fixed by #18904

Comments

@yj7810520113
Copy link

yj7810520113 commented Mar 12, 2020

code
var depthTexture = new THREE.DepthTexture();

var parameters = {
    format: THREE.RGBFormat,
    stencilBuffer: false,
    depthBuffer: true,
    depthTexture: depthTexture
};

var size = renderer.getDrawingBufferSize( new THREE.Vector2() );

var renderTarget = new THREE.WebGLMultisampleRenderTarget( size.width, size.height, parameters );
output error:
[.WebGL-0x7fcad880e800]GL ERROR :GL_INVALID_OPERATION : glBufferData: <- error from previous GL command

webgl2_multisampled_renderbuffers.html:1 [.WebGL-0x7fcad880e800]GL ERROR :GL_INVALID_OPERATION : glTexImage2D: <- error from previous GL command

254[.WebGL-0x7fcad880e800]GL ERROR :GL_INVALID_OPERATION : glFramebufferTexture2D: <- error from previous GL command
Three.js version
  • Dev
  • r114
  • ...
Browser
  • All of them
  • Chrome
  • Firefox
  • Internet Explorer
@Mugen87
Copy link
Collaborator

Mugen87 commented Mar 12, 2020

@kenrussell Is it actually possible to use multisampled FBOs and depth textures at the same time?

We can already use multisampled rendertargets as demonstrated by this demo. But when I try to modify our depth texture demo to use a WebGLMultisampleRenderTarget, things start to break.

Live demo: https://jsfiddle.net/j1c9hurp/1/

I've searched the web for quite a while now but I could not find a resource that shows a setup with plain WebGL.

@kenrussell
Copy link

The number of samples has to match among all framebuffer attachments. So if the color buffer is multisampled, the depth and/or stencil buffer has to be multisampled, too. Here's a portion of the WebGL 2.0 conformance suite which tests this:

https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/deqp/functional/gles3/es3fMultisampleTests.js#L533

@Mugen87
Copy link
Collaborator

Mugen87 commented Mar 12, 2020

So if the color buffer is multisampled, the depth and/or stencil buffer has to be multisampled, too.

AFAIK, three.js is already ensuring this. But there seems to be problems when a depth texture is attached to the draw framebuffer. Meaning the frambuffer which is the target of the blitFramebuffer call.

@kenrussell
Copy link

The example creates a "WebGLMultisampleRenderTarget" but then explicitly assigns its depth buffer to a new "DepthTexture". I'm not sure what Three.js is doing internally, but unless that depth texture is actually being allocated as a multisampled renderbuffer, then it's not multisampled. This would likely be causing a mismatch between the color buffer (which I assume is a multisampled renderbuffer) and the depth buffer.

@Mugen87
Copy link
Collaborator

Mugen87 commented Mar 13, 2020

Okay, I've created a live example with plain WebGL that reproduces the issue. I hope this makes it easier to analyze the issue:

https://windy-rocket.glitch.me/

The interesting code section is:

// multisample FBO
frameBufferMultiSample = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBufferMultiSample);

var renderBufferColorMultiSample = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, renderBufferColorMultiSample);
gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, gl.viewportWidth, gl.viewportHeight);
gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderBufferColorMultiSample );

var renderBufferDepthMultiSample = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, renderBufferDepthMultiSample);
gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.DEPTH_COMPONENT16, gl.viewportWidth, gl.viewportHeight);
gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderBufferDepthMultiSample );

// resolve FBO
frameBuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);

// create color texture
colorTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, colorTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, gl.viewportWidth, gl.viewportHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

// create depth texture
depthTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, depthTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT16, gl.viewportWidth, gl.viewportHeight, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

// assign color and depth texture to framebuffer
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTexture, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTexture, 0 );

// reset
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

For code editing, use: https://glitch.com/~windy-rocket

kvholm added a commit to kvholm/three.js that referenced this issue Mar 13, 2020
@Mugen87
Copy link
Collaborator

Mugen87 commented Mar 15, 2020

Okay, I've studied the issue more closely. Using a depth texture with WebGL 2 works without issue. However, as soon as WebGLMultisampleRenderTarget is used, it seems it's not possible to use THREE.UnsignedShortType for the depth texture's type. When I change the type to UnsignedIntType or FloatType, things work again. However, this requires minor additions to WebGLTexture.

It would be good to know why using gl.UNSIGNED_SHORT is problematic in context of multisampled FBOs.

@kenrussell
Copy link

Thanks for the report and test case. It was necessary to reduce it further:
https://glitch.com/edit/#!/equable-unleashed-grouse

but yes, it looks like there's a bug in Chrome in the handling of DEPTH_COMPONENT16 renderbuffers or textures in conjunction with blitFramebuffer. Firefox works fine with the test case.

Have filed this as http://crbug.com/1062887 . We'll investigate it.

Using DEPTH_COMPONENT24 seems to be a workable workaround. Please let me know, or ideally comment on the Chromium bug, if not; that could motivate making it higher priority.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants