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

Examples: Port advanced postprocessing sample to WebGPU #28962

Draft
wants to merge 7 commits into
base: dev
Choose a base branch
from

Conversation

cmhhelgeson
Copy link
Contributor

@cmhhelgeson cmhhelgeson commented Jul 24, 2024

Related issue:

Description

Long-term goal to port over webgl_postprocessing_advanced and its relevant shaders over to a WebGPURenderer version. We can also determine whether some of these smaller shaders warrant being included with the build or should be relegated to the examples

@donmccurdy
Copy link
Collaborator

Gamma Correction Node

I would be inclined not to bring a GammaCorrectionNode into the WebGPU renderer and TSL, as we already have ColorSpaceNode.

@Mugen87
Copy link
Collaborator

Mugen87 commented Jul 25, 2024

Vertical and Horizontal Blur Node (possibly just use GaussianBlurNode )

Yes, no need for separate nodes.

Vignette Node

@sunag already wrote code for that in another example. It is so simple that I don't think we need a separate node.

const vignet = viewportTopLeft.distance( .5 ).mul( 1.35 ).clamp().oneMinus();

@Mugen87
Copy link
Collaborator

Mugen87 commented Jul 25, 2024

Mask and Clear Mask Node ( including necessary stencil operations )

It might make more sense to port https://threejs.org/examples/webgl_postprocessing_masking first before thinking about the advanced example.

I'm also not sure yet if we want to use the same masking approach as before. The design maybe needs to be revisited.

@sunag
Copy link
Collaborator

sunag commented Jul 25, 2024

I'm also not sure yet if we want to use the same masking approach as before. The design maybe needs to be revisited.

I agree. There are several ways to do this with MRT, it could be something like webgpu_mrt_mask or per object, just registering the color through the id.

@Mugen87
Copy link
Collaborator

Mugen87 commented Jul 25, 2024

Yeah, I was hoping we can get a solution without the stencil buffer. The related handling was always a bit inconvenient.

@cmhhelgeson
Copy link
Contributor Author

cmhhelgeson commented Jul 25, 2024

Yeah, I was hoping we can get a solution without the stencil buffer. The related handling was always a bit inconvenient.

Not having to manage setting and clearing masks with the stencil sounds good to me, especially for a simple post step.

@cmhhelgeson
Copy link
Contributor Author

cmhhelgeson commented Jul 26, 2024

Question for @sunag: In the mrt_mask example, when the mrtNode of the scenePass is set to vec4(0), but the mrtNode of the mesh material is set to output, would this generally mean that the alpha of every pixel outside of the mesh itself is 0, while every alpha of the pixel within the mesh is 1? Seems like alpha blending would be the solution here ( especially for post-processing), but need a better understanding of how the mrt system works.

@sunag
Copy link
Collaborator

sunag commented Jul 26, 2024

Question for @sunag: In the mrt_mask example, when the mrtNode of the scenePass is set to vec4(0), but the mrtNode of the mesh material is set to output, would this generally mean that the alpha of every pixel outside of the mesh itself is 0, while every alpha of the pixel within the mesh is 1? Seems like alpha blending would be the solution here ( especially for post-processing), but need a better understanding of how the mrt system works.

A MRT used in pass() will be the default value for all render-pass materials, if you use any material with material.mrtNode it will replace the default values of pass() with that of material.mrtNode if defined.

For example in webgpu_postprocessing_bloom_selective:

// global
const scenePass = pass( scene, camera );
scenePass.setMRT( mrt( {
	output,
	bloomIntensity: float( 0 ) // default bloom intensity
} ) );

// define a custom bloom intensity in some material
material.mrtNode = mrt( {
	bloomIntensity: float( 1.0 ) // it could be: output.a 
} );

Note that alpha is not considered in the output of bloomItensity, you could build a structure for this just using output.a.

@cmhhelgeson
Copy link
Contributor Author

If alpha is not considered in the output of a pass, then how could I get the alpha output of a scene?

@sunag
Copy link
Collaborator

sunag commented Jul 28, 2024

how could I get the alpha output of a scene?

I assume you want to transfer the alpha output of scene to an individual texture using MRT:

scenePass.setMRT( mrt( {
	output,
	sceneAlpha: output.a
} ) );

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 13, 2024

What is missing to complete this PR?

@cmhhelgeson
Copy link
Contributor Author

What is missing to complete this PR?

Sorry I didn't have time to respond earlier. I think just a colorify implementation and then implementing the sample. I was having some issues creating multiple postProcessing objects that only apply to a specific subsection of the screen, but I'll have to check if that's still a problem.

Copy link

github-actions bot commented Sep 5, 2024

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 685.18
169.62
685.18
169.62
+0 B
+0 B
WebGPU 825.96
221.44
826.09
221.46
+133 B
+25 B
WebGPU Nodes 825.54
221.34
825.67
221.37
+133 B
+23 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Before After Diff
WebGL 461.96
111.46
461.96
111.46
+0 B
+0 B
WebGPU 525.27
141.52
525.27
141.52
+0 B
+0 B
WebGPU Nodes 481.93
131.34
481.93
131.34
+0 B
+0 B

@Makio64
Copy link
Contributor

Makio64 commented Sep 16, 2024

Vertical and Horizontal Blur Node (possibly just use GaussianBlurNode )

Yes, no need for separate nodes.

Vignette Node

@sunag already wrote code for that in another example. It is so simple that I don't think we need a separate node.

const vignet = viewportTopLeft.distance( .5 ).mul( 1.35 ).clamp().oneMinus();

I agree it's super simple but it's nice to have also"basic node" part of threejs, it make the postprocessing super easy to setup in a new project without having to dive into TSL and redo the wheel, Vignette is one of the must use pass i saw in almost all project a bit cinematic.

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.

5 participants