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

[Feature] Allow translucent rendering of volumes behind meshes #3167

Open
dstansby opened this issue Nov 4, 2024 · 4 comments
Open

[Feature] Allow translucent rendering of volumes behind meshes #3167

dstansby opened this issue Nov 4, 2024 · 4 comments
Labels
module: rendering General rendering issues module: webgl Issues related to WebGL type: feature request 💡 Desired capabilities / enhancements

Comments

@dstansby
Copy link

dstansby commented Nov 4, 2024

Motivation

When rendering a mesh, it blocks any volume images behind it. It would be great if meshes could be made transparent so that image data "shows" through them. In the first screenshot you can see some cylinder sources I've added to the scene, which block the volume data behind them. Even when the opacity is turned right down (second image), the volume data is blocked.

Detailed Description

Screenshot 2024-11-04 at 22 17 58

Screenshot 2024-11-04 at 22 17 36

@dstansby dstansby added the type: feature request 💡 Desired capabilities / enhancements label Nov 4, 2024
@finetjul finetjul added module: rendering General rendering issues module: webgl Issues related to WebGL labels Nov 5, 2024
@finetjul
Copy link
Member

finetjul commented Nov 5, 2024

@sankhesh do you know why translucent polydata write into depth buffer ?

if (
((model.opaqueActorCount > 0 || model.translucentActorCount > 0) &&
model.volumeCount > 0) ||
model.depthRequested
) {
const size = viewNode.getFramebufferSize();
// make sure the framebuffer is setup
if (model.framebuffer === null) {
model.framebuffer = vtkOpenGLFramebuffer.newInstance();
}
model.framebuffer.setOpenGLRenderWindow(viewNode);
model.framebuffer.saveCurrentBindingsAndBuffers();
const fbSize = model.framebuffer.getSize();
if (
fbSize === null ||
fbSize[0] !== size[0] ||
fbSize[1] !== size[1]
) {
model.framebuffer.create(size[0], size[1]);
model.framebuffer.populateFramebuffer();
}
model.framebuffer.bind();
// opaqueZBufferPass only renders opaque actors
// zBufferPass renders both translucent and opaque actors
// we want to be able to pick translucent actors
publicAPI.setCurrentOperation('zBufferPass');
renNode.traverse(publicAPI);
model.framebuffer.restorePreviousBindingsAndBuffers();
// reset now that we have done it
model.depthRequested = false;
}

@finetjul
Copy link
Member

finetjul commented Nov 5, 2024

This is actually a recent behavior:

ec4ec2f

I'm not sure it is intentional...
@bruyeret ?

@sankhesh
Copy link
Collaborator

sankhesh commented Nov 5, 2024

@sankhesh do you know why translucent polydata write into depth buffer ?

if (
((model.opaqueActorCount > 0 || model.translucentActorCount > 0) &&
model.volumeCount > 0) ||
model.depthRequested
) {
const size = viewNode.getFramebufferSize();
// make sure the framebuffer is setup
if (model.framebuffer === null) {
model.framebuffer = vtkOpenGLFramebuffer.newInstance();
}
model.framebuffer.setOpenGLRenderWindow(viewNode);
model.framebuffer.saveCurrentBindingsAndBuffers();
const fbSize = model.framebuffer.getSize();
if (
fbSize === null ||
fbSize[0] !== size[0] ||
fbSize[1] !== size[1]
) {
model.framebuffer.create(size[0], size[1]);
model.framebuffer.populateFramebuffer();
}
model.framebuffer.bind();
// opaqueZBufferPass only renders opaque actors
// zBufferPass renders both translucent and opaque actors
// we want to be able to pick translucent actors
publicAPI.setCurrentOperation('zBufferPass');
renNode.traverse(publicAPI);
model.framebuffer.restorePreviousBindingsAndBuffers();
// reset now that we have done it
model.depthRequested = false;
}

To sort order with multiple translucent actors only when picking. It shouldn't be written when the current frame is not a pick frame. See

model.context.depthMask(
model._openGLRenderer.getSelector() &&
model.renderable.getNestedPickable()
);

@bruyeret
Copy link
Contributor

bruyeret commented Nov 5, 2024

From what I remember, the zbuffer is needed when rendering both volumes and polydatas:
If a polydata is in front of a volume, we need the zbuffer to know when to stop the volume raycasting
You can test if it is really needed by removing this zbuffer pass and rendering this example (a polydata in front of a volume)

A solution is to discard fragments that are completely transparent in the polydata mapper fragment shader during the zbuffer pass

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
module: rendering General rendering issues module: webgl Issues related to WebGL type: feature request 💡 Desired capabilities / enhancements
Projects
None yet
Development

No branches or pull requests

4 participants