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

Auto shader output definitions for MRT #27808

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

Conversation

vanruesc
Copy link
Contributor

@vanruesc vanruesc commented Feb 22, 2024

Description

This PR aims to make Multiple Render Targets (MRT) easier to use by implementing automatic shader output definitions for built-in materials and ShaderMaterial.

// Example output definitions:
layout(location = 0) out lowp vec4 out_FragData0;
#define out_Color out_FragData0
layout(location = 1) out mediump vec4 out_FragData1;
#define out_Normal out_FragData1

Context

For MRT workflows it's up to the user to define what data should be written to the respective textures. The MRT example promotes the use of RawShaderMaterial to achieve this. However, MRT is most useful for rendering out additional pixel data during the main render pass. In most situations the main scene will consist of meshes that use built-in materials like MeshStandardMaterial, but those materials are currently difficult to use with MRT.

Improving compatibility

It's possible to use onBeforeCompile on every object in a scene to modify built-in materials, but this has some downsides:

  • An object's material may already have an onBeforeCompile hook, so care must be taken to preserve it.
  • All objects need to be tracked to avoid assigning onBeforeCompile hooks multiple times.
  • Objects and materials may be added or removed at runtime which requires additional scene processing to ensure that all materials have the required onBeforeCompile hooks.

If it wasn't necessary to define shader outputs, we could avoid using onBeforeCompile altogether and modify the ShaderChunk library instead (example). But at the moment there's no way around onBeforeCompile.

Meeting halfway

With the changes in this PR, three can define shader outputs automatically based on the current render target. To avoid breakage, this is only done for built-in materials and for ShaderMaterial if the shader doesn't already define shader outputs. This implementation also uses the names of the MRT textures to define macros of the form out_${name} for convenience which allows for conditional MRT code like the following:

#ifdef out_Normal

	out_Normal = vec4(normal, 1.0);

#endif

I've considered using the texture names as-is but opted for a prefix approach to reduce the risk of name conflicts.

Open issue

This PR is in draft mode because the material/program doesn't get updated after switching the render target. I've tried modifying WebGLPrograms.getProgramCacheKey to account for the render target, but that didn't work out. Setting material.needsUpdate to true also didn't trigger a program update.

It would be great if someone could help with this, provided there's interest in this PR.

Copy link

github-actions bot commented Feb 22, 2024

📦 Bundle size

Full ESM build, minified and gzipped.

Filesize dev Filesize PR Diff
671.2 kB (166.4 kB) 672 kB (166.7 kB) +754 B

🌳 Bundle size after tree-shaking

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

Filesize dev Filesize PR Diff
451.1 kB (109 kB) 451.9 kB (109.3 kB) +792 B

@@ -82,7 +40,7 @@
return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );
}

layout(location = 0) out vec4 pc_FragColor;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw: does anyone know what "pc" stands for? 🤔

@puxiao
Copy link
Contributor

puxiao commented Feb 24, 2024

Some checks were not successful

DeepScan:1 new and 1 fixed issues

Local variable 'xr' is not used.

editor/js/Viewport.js

....

@vanruesc This issue has been fixed, you need to pull the code again.


Solution:

git checkout auto-shader-outputs
git remote add upstream https://github.com/threejs/three.js.git
git fetch upstream
git merge upstream/dev

... All checks have passed ...

@Mugen87 Mugen87 added this to the r??? milestone Feb 26, 2024
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.

None yet

3 participants