-
-
Notifications
You must be signed in to change notification settings - Fork 36.1k
Add support for using BC5 and EAC_RG compressed textures as normal maps. #31695
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
Open
castano
wants to merge
13
commits into
mrdoob:dev
Choose a base branch
from
Ludicon:normalmap-projectz
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+80
−3
Open
Changes from 1 commit
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
6f87f91
Add NormalMapNode projectZ attribute.
castano 0426e41
Add unpack normal helpers to Packing.js
castano 6e7478a
Add normal packing mode constants to constants.js
castano 1a4e77f
Import normal packing mode constants.
castano dca8fc4
Rename projectZ to unpackNormal.
castano 31195ee
Material sets unpackNormal attribute based on normal map user data at…
castano 3d843f6
Fix lint errors.
castano 5413f13
Fix linter error.
castano 344bec8
Replace unpackNormal functions with reconstructZ.
castano 2e9e502
Merge branch 'dev' into normalmap-projectz
castano 0e25686
Apply suggested renaming.
castano cdcabdf
Rename unpackNormalZ and update invocation.
castano 407e673
Or better, keep unpackNormal function and rename attribute.
castano File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not rely on monkey-patched code here.
How about you introduce the property in the
CompressedTextureclass? Or is it also relevant forTexture?Alternatively, move the property into the
userDatafield ofnormalMapfor now.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When thinking about this: Why not checking for specific RG texture formats here and only then set the node property to
true? In this way we need no additional texture property and it would not be necessary to update loaders.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is most useful in
CompressedTexture, but in my particular application I'm using this withExternalTextureand it can also be useful with uncompressed textures, to reduce their size by storing only the RG components.I agree this should be done in some other way. A potential problem with this PR is that the attribute won't be cloned with the texture and that may cause issues. Adding it to the
userDatafield as you propose would solve that problem.I'm not sure enabling the Z reconstruction is the right thing to do for all RG texture formats. RG textures can be used for other purposes in addition to normal maps (heat distortion maps, 2d vector fields, chrominance values, etc). It may not cause any harm to just compute the Z component this way, but this won't extend to ASTC normal maps if we ever want to support that.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went with the
userDataapproach. Let me know if that looks good to you.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My idea was to only do this for specific map types. So for a normal map, a format like
bc5-rg-snorm(orSIGNED_RED_GREEN_RGTC2_Format) must hold packed RG data, otherwise it would be unusable for a normal map. This is something that could be implemented in the node classes so loaders don't have to worry about this detail.But it's true a separate property allows more flexibility than deriving from texture formats.
It would be interesting to hear the opinion of others about this PR. Would you be okay if we label this PR as a "Draft PR" for now? I have the feeling we need to discuss the API a bit more in the team/community before making a decision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@donmccurdy I'll ping you directly since you have done so much work in context of texture compression.
Similar to
Texture.colorSpace, what do you think about introducing a new propertyTexture.packingthat describes the packing strategy of a texture. The default would beNoPacking(as a pendant toNoColorSpace).Packing strategies usually apply on certain texture types so probably most of the new constants for
Texture.packingwould be quite specific (likeRGNormalPackingorGANormalPacking). But that is a similar situation like withTexture.colorSpacewhere certain constants only apply to color textures.So...what do you think about this approach? Do you have maybe alternatives in mind?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't be opposed to adding a
Texture#packingproperty, I think @bhouston had proposed something similar once? A few other thoughts:If we see
texture.format = THREE.RGFormat(or similar) assigned to a normal map slot, possibly that is enough in this case?In the newer TSL/NodeMaterial APIs with WebGPURenderer, is a property on THREE.Texture sure to be accessible? Or could the Texture instance have been wrapped in other nodes, obscuring the underlying Texture? If so, we could handle this by a new node to handle the unpacking, or a material property similar to
material.normalMapType, instead.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I've been looking at the possibility of enabling the RGNormalPacking mode automatically based on the texture format. It could be something along these lines:
Let me know if it's worth adding this. The default behavior could still be overridden with the user data attribute:
normalMap.userData.unpackNormal.Note, this only handles RG textures and BC5. I think there's no identifier for EAC_RG11 in three.js. If support for it is added in the future, this could be handled here as well.
We could also add support for signed RG textures and eliminate the
2*x-1unpacking in the normal map node, but barely anybody uses the signed formats, so I think it's not worth it.I'm ambivalent about adding a
Texture#packingproperty. I can experiment with that if you think that's the way to go.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect checking
.formatwould make sense for WebGLRenderer but not for TSL in WebGPURenderer. Since the focus of this PR is WebGPURenderer, we can skip that for now, but I wouldn't be opposed to adding this support in WebGLRenderer later.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should work with either renderer. The main caveats are that it requires the format attribute to be set (which may not be the case if it's an external texture), and it does not support EAC_RG, since that format is not natively supported in three.js.
Happy to include it for now if you think it makes sense to pave the way in that direction.