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

Unreal Bloom and Renderer Transparency issue #14104

Open
fire67 opened this Issue May 21, 2018 · 20 comments

Comments

Projects
None yet
7 participants
@fire67

fire67 commented May 21, 2018

Description of the problem

I am currently using the Unreal Bloom post with a transparent renderer.

renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor(0xFF0000, 0);

Unfortunately, the Unreal Bloom pass doesn't seem to take in account the alpha channel of the coming texture when doing the blur and it apparently comes from getSeperableBlurMaterial in js\postprocessing\UnrealBloomPass.js.

The fragment's alpha channel is always set to 1.0 which results in a complete removal of the previous alpha values when doing the additive blending at the end.

This is happening in the latest version of Three.js r92 and you can experiment about this issue using the Unreal Bloom example

@WestLangley

This comment has been minimized.

Collaborator

WestLangley commented May 21, 2018

In getSeperableBlurMaterial()you can try a work-around:

gl_FragColor = vec4( diffuseSum / weightSum, 0.1 );\n\

Remember, it is an example, so you are free to modify it.

@fire67

This comment has been minimized.

fire67 commented May 21, 2018

Thanks for the answer @WestLangley !
Yeah this would help keeping the transparency but would destroy the bloom effect (which is really cool btw) around the object. I think a more cleaner solution would be to apply weight on alpha channel too.

Any solution would help me a lot :)

@WestLangley

This comment has been minimized.

Collaborator

WestLangley commented May 21, 2018

@fire67

This comment has been minimized.

fire67 commented May 22, 2018

I achieved to find a solution for this but I would like to know your opinion @spidersharma03 and @WestLangley.

void main()
{
	vec2 invSize = 1.0 / texSize;
	float fSigma = float(SIGMA);
	float weightSum = gaussianPdf(0.0, fSigma);
	float alphaSum = 0.0;
	vec3 diffuseSum = texture2D(colorTexture, vUv).rgb * weightSum;
	for( int i = 1; i < KERNEL_RADIUS; i ++ )
	{
		float x = float(i);
		float weight = gaussianPdf(x, fSigma);
		vec2 uvOffset = direction * invSize * x;
		
		vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);
		float weightAlpha = sample1.a * weight;
		diffuseSum += sample1.rgb * weightAlpha;
		alphaSum += weightAlpha;
		weightSum += weight;
		
		vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);
		weightAlpha = sample2.a * weight;
		diffuseSum += sample2.rgb * weightAlpha;
		alphaSum += weightAlpha;
		weightSum += weight;
		
	}
	alphaSum /= weightSum;
	diffuseSum /= alphaSum; // Should apply discard here if alphaSum is 0
	gl_FragColor = vec4(diffuseSum.rgb, alphaSum);
}

@mrdoob mrdoob added this to the r94 milestone May 22, 2018

@WestLangley

This comment has been minimized.

Collaborator

WestLangley commented May 22, 2018

Sorry, I have no opinion on this.

@spidersharma03

This comment has been minimized.

Contributor

spidersharma03 commented May 27, 2018

Sorry @fire67 , was away for a few days. Yeah, what you have done seems correct. I didn't handle the transparency.

@fire67

This comment has been minimized.

fire67 commented May 28, 2018

No problem, thank you for the answer @spidersharma03 !
While testing the effect I noticed a visual difference when pushing some values very high.

Do you have any idea where does this comes from ?

bloom

@spidersharma03

This comment has been minimized.

Contributor

spidersharma03 commented May 29, 2018

@fire67 , Not sure actually. Do you have the changed code in some branch? I will try to take a look.
Thanks!

@fire67

This comment has been minimized.

fire67 commented May 30, 2018

@spidersharma03 No, unfortunately the code is not available on a branch. Do you want me to do it ?
Just to let you know, there's nothing more than the main function in the previous post.

@mrdoob mrdoob modified the milestones: r94, r95 Jun 27, 2018

@jcyuan

This comment has been minimized.

jcyuan commented Jul 8, 2018

@fire67 @spidersharma03 hi, I tried to use your main() code to replace the old one in example but all bloom effect gone although the background takes effect it's transparent.

this.renderer = new THREE.WebGLRenderer({
        canvas: view,
        alpha:true
});

//and pass
this.$unrealBloom = new UnrealBloomPass(new THREE.Vector2(this.app.stageWidth, this.app.stageHeight), 3.2, .6, 0.7 );
this.$composer.addPass(this.$unrealBloom);

this.$blurPass = new ShaderPass(HorizontalBlurShader);
this.$blurPass.uniforms['h'].value = 0;
this.$composer.addPass(this.$blurPass);

this.$blurPass.renderToScreen = true;

please help, thanks.

@jcyuan

This comment has been minimized.

jcyuan commented Jul 13, 2018

ok so the problem is caused by my setting:
this.$renderer.context.enable(this.$renderer.context.SAMPLE_ALPHA_TO_COVERAGE);
the alpha channel of user RTT will not be handled by lowlevel for A2C in WebGL1.0 (it does in WebGl2.0)

the changed shader works well actually, thank you very much @fire67

@mrdoob mrdoob modified the milestones: r95, r96 Jul 31, 2018

@mrdoob mrdoob modified the milestones: r96, r97 Aug 29, 2018

@shokunin000

This comment was marked as off-topic.

shokunin000 commented Sep 6, 2018

Is it possible to increase bloom based on emissive values? Trying to utilize those values to increase strength on glowing objects but this shader code is bit above my head! Any help would be much appreciated

@mrdoob mrdoob modified the milestones: r97, r98 Sep 25, 2018

@robhawkes

This comment has been minimized.

robhawkes commented Oct 12, 2018

@fire67 Did you manage to get this working with the bloom keeping the colour of the object? As soon as I try to use the changed shader the bloom just goes pure white, rather than taking the object colour as before.

I also tried disabling rendering.alpha but the bloom was still pure white.

Any ideas?

void main() {\n\
  vec2 invSize = 1.0 / texSize;\
  float fSigma = float(SIGMA);\
  float weightSum = gaussianPdf(0.0, fSigma);\
  float alphaSum = 0.0;\
  vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;\
  for( int i = 1; i < KERNEL_RADIUS; i ++ ) {\
    float x = float(i);\
    float weight = gaussianPdf(x, fSigma);\
    vec2 uvOffset = direction * invSize * x;\
    vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);\
    float weightAlpha = sample1.a * weight;\
    diffuseSum += sample1.rgb * weightAlpha;\
    alphaSum += weightAlpha;\
    weightSum += weight;\
    vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);\
    weightAlpha = sample2.a * weight;\
    diffuseSum += sample2.rgb * weightAlpha;\
    alphaSum += weightAlpha;\
    weightSum += weight;\
  }\
  alphaSum /= weightSum;\
  diffuseSum /= alphaSum;\
  gl_FragColor = vec4(diffuseSum.rgb, alphaSum);\n\
}

Before:
image

After:
image

@robhawkes

This comment has been minimized.

robhawkes commented Oct 14, 2018

I've been mulling this over for the past few days and decided to attempt a slightly different approach that takes the original (non-transparent) colour calculations, leaves them unmodified and then adds on top the new alpha calculations from @fire67 with a couple of minor tweaks to utilise the same weights as the colour calculations. I don't know if this is the right way to do it, and the calculations could probably be tidied up, but it works.

void main() {\n\
  vec2 invSize = 1.0 / texSize;\
  float fSigma = float(SIGMA);\
  float weightSum = gaussianPdf(0.0, fSigma);\
  float alphaSum = 0.0;\
  vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;\
  for( int i = 1; i < KERNEL_RADIUS; i ++ ) {\
    float x = float(i);\
    float w = gaussianPdf(x, fSigma);\
    vec2 uvOffset = direction * invSize * x;\
    vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);\
    vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);\
    diffuseSum += (sample1.rgb + sample2.rgb) * w;\
    weightSum += 2.0 * w;\
    float weightAlpha = sample1.a * w;\
    alphaSum += weightAlpha;\
    weightAlpha = sample2.a * w;\
    alphaSum += weightAlpha;\
  }\
  gl_FragColor = vec4(diffuseSum/weightSum, alphaSum/weightSum);\n\
}

Previous approach (posted earlier in this issue):

New approach combining original logic with updated logic posted earlier in the issue:

image

@robhawkes

This comment has been minimized.

robhawkes commented Oct 14, 2018

Tidy things up a bit and it seems to work just as well:

void main() {\n\
  vec2 invSize = 1.0 / texSize;\
  float fSigma = float(SIGMA);\
  float weightSum = gaussianPdf(0.0, fSigma);\
  float alphaSum = 0.0;\
  vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;\
  for( int i = 1; i < KERNEL_RADIUS; i ++ ) {\
    float x = float(i);\
    float w = gaussianPdf(x, fSigma);\
    vec2 uvOffset = direction * invSize * x;\
    vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);\
    vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);\
    diffuseSum += (sample1.rgb + sample2.rgb) * w;\
    alphaSum += (sample1.a + sample2.a) * w;\
    weightSum += 2.0 * w;\
  }\
  gl_FragColor = vec4(diffuseSum/weightSum, alphaSum/weightSum);\n\
}

I've noticed some little (single pixel) artefacts that appear once in a while but seem to be random or based on something that only occurs on some frames as they disappear on the next frame. Not sure if it's caused by the changes I made or something unrelated to this issue.

@robhawkes

This comment has been minimized.

robhawkes commented Oct 15, 2018

I've done some more testing and can confirm that the artefacts that I was seeing are unrelated to Three.js and the changes that I made to the bloom shader, so that's good.

@mrdoob

This comment has been minimized.

Owner

mrdoob commented Oct 15, 2018

@spidersharma03

This comment has been minimized.

Contributor

spidersharma03 commented Oct 22, 2018

I will see the results with a colored scene and come back.

@spidersharma03

This comment has been minimized.

Contributor

spidersharma03 commented Oct 22, 2018

@robhawkes , I see that you initialize the alphaSum to 0. Did you simply try making something like this::

vec4 diffuseSum = texture2D( colorTexture, vUv)* weightSum;\ ... ... diffuseSum /= weightSum;

@spidersharma03

This comment has been minimized.

Contributor

spidersharma03 commented Oct 22, 2018

@robhawkes , basically something like this::

                                    float fSigma = float(SIGMA);
				float weightSum = gaussianPdf(0.0, fSigma);
				vec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum;
				for( int i = 1; i < KERNEL_RADIUS; i ++ ) {
					float x = float(i);
					float w = gaussianPdf(x, fSigma);
					vec2 uvOffset = direction * invSize * x;
					vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);
					vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);
					diffuseSum += (sample1 + sample2) * w;
					weightSum += 2.0 * w;
				}
				gl_FragColor = vec4(diffuseSum/weightSum);

I need to test it though

@mrdoob mrdoob removed this from the r98 milestone Oct 31, 2018

@mrdoob mrdoob added this to the r99 milestone Oct 31, 2018

@mrdoob mrdoob modified the milestones: r99, r100 Nov 29, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment