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

changing additive blending mechanism #671

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

fcollman
Copy link
Contributor

I think that the way additive blending is implemented now is not quite right.. or i don't know how to get it to work the way that i would expect, and if we are going to use layers to blend the colors we need this to work properly.

Take this link for example
the image looks like this
image

but with this PR I get an image that looks like this, if i make the first layer 'default" and the extra layers as "additive". Note the colors are brighter and red and green make yellow.. rather than it 'mixing' from red to green.

image

@jbms
Copy link
Collaborator

jbms commented Nov 26, 2024

I think the only issue is that the "Opacity (slice)" setting affects additive blending also (it impacts the SRC_ALPHA in the blendFunc) and therefore to get the expected result you need to set it to 1.

FUNC_ADD is the default blendEquation setting so this PR effectively just leaves the blendFunc unset which means it will depend on the precise order in which things are rendered.

@fcollman
Copy link
Contributor Author

I see that in current PR that things get closer when i put the opacity of the slice to 1.

but i still can't get things to add up right (red + green = yellow).

I did notice that I had to set the order of the layer corrects (with the bottom layer set to default blending).

Is there some way to make it order independent and get the additive effect?

@jbms
Copy link
Collaborator

jbms commented Nov 26, 2024

For the cross-section view, the problems seem to be due to your shader, which sets a varying alpha value (which then gets multiplied by the color during blending). Changing it to always emit alpha=1 fixes the issue for the cross-section view.

However, for volume rendering, blending works differently. It might be necessary to use if (VOLUME_RENDERING) {} in the shader to make it work for both cross sections and volume rendering.

@fcollman
Copy link
Contributor Author

ah.. okay.. yes, this makes sense now. So if we want to allow for volume rendering (which requires alpha emission) and additive blending in cross section views we need a different blending strategy.

What if we use

gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE, gl.ONE, gl.ONE);

When the initial destination layer is RGB = 0,0,0 then this would add the color portion proportional to the alpha values, which i assume is the cross section opacity * the data alpha, but the alpha values would just add up without getting a second alpha factor, which is what was happening before when we were emitting RGBA values.

@jbms
Copy link
Collaborator

jbms commented Nov 27, 2024

I think that would still have the same problem --- multiplying the color by the alpha, if the alpha is equal to max(r, g, b), will still make the color darker than expected --- e.g. if previously we had RGB=(0.5, 0, 0) then max(r, g, b) = 0.5 and we end up adding 0.5 * 0.5 = 0.25.

I'm not sure how to achieve the best results for volume rendering with the shader, but there isn't a need to emit the same thing for the cross-section views and volume rendering views --- I made the VOLUME_RENDERING constant available to the shader because I figured it would generally be necessary to emit different values.

@fcollman
Copy link
Contributor Author

I see so a reasonable default shader is then this..

#uicontrol invlerp channel0_lut (range=[1,255],window=[0,255]);
#uicontrol vec3 channel0_color color(default="green");
vec3 channel0 = vec3(0);
void main() {
  float val = channel0_lut(getDataValue());
  vec3 rgb = channel0_color * val;
  
  if (VOLUME_RENDERING){
    vec4 rgba = vec4(rgb, val);
  	emitRGBA(rgba);
  }
  else{
    emitRGB(rgb);
  }
}

The max projection doesn't seem to be additive across layers in the right way..

image

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 this pull request may close these issues.

2 participants