Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # 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.

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

Successfully merging a pull request may close this issue.

3 participants