Skip to content

Conversation

@JMS55
Copy link
Contributor

@JMS55 JMS55 commented Dec 2, 2024

Objective

Solution

Testing

  • Ran the new decal example.

Showcase

image

Changelog

  • Added ForwardDecal and associated types
  • Added MaterialExtension::alpha_mode()

@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible A-Rendering Drawing game state to the screen M-Release-Note Work that should be called out in the blog due to impact S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Dec 2, 2024
@JMS55 JMS55 requested a review from pcwalton January 11, 2025 18:32
///
/// Decreasing this value will cause the decal to blend only to surfaces closer to it.
///
/// Units are in meters.
Copy link
Contributor Author

@JMS55 JMS55 Jan 11, 2025

Choose a reason for hiding this comment

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

Units are in meters.

I think?

pcwalton added a commit to pcwalton/bevy that referenced this pull request Jan 11, 2025
This commit adds support for *decal projectors* to Bevy, allowing for
textures to be projected on top of geometry. Decal projectors are
clusterable objects, just as punctual lights and light probes are. This
means that decals are only evaluated for objects within the conservative
bounds of the projector, and they don't require a second pass.

These clustered decals require support for bindless textures and as such
currently don't work on WebGL 2, WebGPU, macOS, or iOS. For an
alternative that doesn't require bindless, see PR bevyengine#16600. I believe that
both contact projective decals in bevyengine#16600 and clustered decals are
desirable to have in Bevy. Contact projective decals offer broader
hardware and driver support, while clustered decals don't require the
creation of bounding geometry.

A new example, `decal_projectors`, has been added, which demonstrates
multiple decals on a rotating object. The decal projectors can be scaled
and rotated with the mouse.

There are several limitations of this initial patch that can be
addressed in follow-ups:

1. There's no way to specify the Z-index of decals. That is, the order
   in which multiple decals are blended on top of one another is
   arbitrary. A follow-up could introduce some sort of Z-index field so
   that artists can specify that some decals should be blended on top of
   others.

2. Decals don't take the normal of the surface they're projected onto
   into account. Most decal implementations in other engines have a
   feature whereby the angle between the decal projector and the normal
   of the surface must be within some threshold for the decal to appear.
   Often, artists can specify a fade-off range for a smooth transition
   between oblique surfaces and aligned surfaces.

3. There's no distance-based fadeoff toward the end of the projector
   range. Many decal implementations have this.
Copy link
Contributor

@pcwalton pcwalton left a comment

Choose a reason for hiding this comment

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

I got:

2025-01-12T01:11:09.471156Z ERROR bevy_render::render_resource::pipeline_cache: failed to process shader:
error: failed to build a valid final module: Function [74] 'bevy_pbr::decal::forward::get_forward_decal_info' is invalid
   ┌─ crates\bevy_pbr\src\decal\forward_decal.wgsl:22:1
   │
22 │ ╭   fn get_forward_decal_info(in: bevy_pbr::forward_io::VertexOutput) -> ForwardDecalInformation {
23 │ │       let world_from_local = bevy_pbr::mesh_functions::get_world_from_local(in.instance_index);
24 │ │       let scale = (world_from_local * vec4(1.0, 1.0, 1.0, 0.0)).xyz;
25 │ │       let scaled_tangent = vec4(in.world_tangent.xyz / scale, in.world_tangent.w);
   · │
44 │ │       let uv = bevy_pbr::parallax_mapping::parallaxed_uv(
   │ │ ╭──────────────^
45 │ │ │         normal_depth,
46 │ │ │         1.0,
47 │ │ │         0u,
48 │ │ │         in.uv,
49 │ │ │         Vt,
   │ │ ╰──────────^ invalid function call
   · │ │
54 │ │
55 │ │       return ForwardDecalInformation(world_position, uv, alpha);
   │ ╰────────────────────────────────────────────────────────────────^ naga::Function [74]
   │
   = Call to [72] is invalid
   = Requires 6 arguments, but 5 are provided

wasm = true

[[example]]
name = "decal"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think perhaps we should either rename this to forward_decal, or else add support for toggling between forward decals and decal projectors from #17315 to this example..


fn alpha_mode(&self) -> crate::AlphaMode {
B::alpha_mode(&self.base)
fn alpha_mode(&self) -> AlphaMode {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is technically a breaking change and should be documented as such.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's not a breaking change, because E::alpha_mode() did not exist until now.

@JMS55
Copy link
Contributor Author

JMS55 commented Jan 12, 2025

Updated the PR, but I don't know why bevy_contact_projective_decals is calling parallaxed_uv() which samples the material's depth map, which for custom materials won't exist, and for standard material will probably be a placeholder.

@JMS55 JMS55 marked this pull request as ready for review January 13, 2025 01:06
@JMS55 JMS55 requested a review from pcwalton January 13, 2025 01:06
base_color_texture: Some(asset_server.load("textures/uv_checker_bw.png")),
..default()
},
extension: ForwardDecalMaterialExt {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
extension: ForwardDecalMaterialExt {
// The decal material is implemented as an extended material
// The default implementation extends the StandardMaterial so decals are rendered using PBR
extension: ForwardDecalMaterialExt {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ehh don't think this is quite accurate. I left some pretty detailed docs on the decal extension stuff, I'd rather people read that.

It's more like you can use ~any material, but you need to wrap it in the extension for CPU-side stuff, and also make some changes in the shader that StandardMaterial already has setup.

@IceSentry
Copy link
Contributor

I suggested a few comments for the example. They don't need to be used verbatim, but a few comments like those would be nice.

@IceSentry
Copy link
Contributor

Not sure if it's related to this PR, but a few examples are broken when running this PR https://pixel-eagle.com/project/B25A040A-A980-4602-B90C-D480AB84076D?filter=PR-16600

@JMS55
Copy link
Contributor Author

JMS55 commented Jan 14, 2025

I doubt it's related, probably just non-deterministic examples.

JMS55 and others added 6 commits January 14, 2025 17:37
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
@JMS55 JMS55 added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Jan 15, 2025
@JMS55 JMS55 requested a review from alice-i-cecile January 15, 2025 01:41
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Jan 15, 2025
Merged via the queue into bevyengine:main with commit e8e2426 Jan 15, 2025
33 checks passed
github-merge-queue bot pushed a commit that referenced this pull request Jan 26, 2025
This commit adds support for *decal projectors* to Bevy, allowing for
textures to be projected on top of geometry. Decal projectors are
clusterable objects, just as punctual lights and light probes are. This
means that decals are only evaluated for objects within the conservative
bounds of the projector, and they don't require a second pass.

These clustered decals require support for bindless textures and as such
currently don't work on WebGL 2, WebGPU, macOS, or iOS. For an
alternative that doesn't require bindless, see PR #16600. I believe that
both contact projective decals in #16600 and clustered decals are
desirable to have in Bevy. Contact projective decals offer broader
hardware and driver support, while clustered decals don't require the
creation of bounding geometry.

A new example, `decal_projectors`, has been added, which demonstrates
multiple decals on a rotating object. The decal projectors can be scaled
and rotated with the mouse.

There are several limitations of this initial patch that can be
addressed in follow-ups:

1. There's no way to specify the Z-index of decals. That is, the order
in which multiple decals are blended on top of one another is arbitrary.
A follow-up could introduce some sort of Z-index field so that artists
can specify that some decals should be blended on top of others.

2. Decals don't take the normal of the surface they're projected onto
into account. Most decal implementations in other engines have a feature
whereby the angle between the decal projector and the normal of the
surface must be within some threshold for the decal to appear. Often,
artists can specify a fade-off range for a smooth transition between
oblique surfaces and aligned surfaces.

3. There's no distance-based fadeoff toward the end of the projector
range. Many decal implementations have this.

This addresses #2401.
 
## Showcase

![Screenshot 2025-01-11
052913](https://github.com/user-attachments/assets/8fabbafc-60fb-461d-b715-d7977e10fe1f)
mrchantey pushed a commit to mrchantey/bevy that referenced this pull request Feb 4, 2025
…6600)

# Objective

- Implement ForwardDecal as outlined in
bevyengine#2401

## Solution

- Port https://github.com/naasblod/bevy_contact_projective_decals, and
cleanup the API a little.

## Testing

- Ran the new decal example.

---

## Showcase


![image](https://github.com/user-attachments/assets/72134af0-724f-4df9-a11f-b0888819a791)

## Changelog
* Added ForwardDecal and associated types
* Added MaterialExtension::alpha_mode()

---------

Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
mrchantey pushed a commit to mrchantey/bevy that referenced this pull request Feb 4, 2025
This commit adds support for *decal projectors* to Bevy, allowing for
textures to be projected on top of geometry. Decal projectors are
clusterable objects, just as punctual lights and light probes are. This
means that decals are only evaluated for objects within the conservative
bounds of the projector, and they don't require a second pass.

These clustered decals require support for bindless textures and as such
currently don't work on WebGL 2, WebGPU, macOS, or iOS. For an
alternative that doesn't require bindless, see PR bevyengine#16600. I believe that
both contact projective decals in bevyengine#16600 and clustered decals are
desirable to have in Bevy. Contact projective decals offer broader
hardware and driver support, while clustered decals don't require the
creation of bounding geometry.

A new example, `decal_projectors`, has been added, which demonstrates
multiple decals on a rotating object. The decal projectors can be scaled
and rotated with the mouse.

There are several limitations of this initial patch that can be
addressed in follow-ups:

1. There's no way to specify the Z-index of decals. That is, the order
in which multiple decals are blended on top of one another is arbitrary.
A follow-up could introduce some sort of Z-index field so that artists
can specify that some decals should be blended on top of others.

2. Decals don't take the normal of the surface they're projected onto
into account. Most decal implementations in other engines have a feature
whereby the angle between the decal projector and the normal of the
surface must be within some threshold for the decal to appear. Often,
artists can specify a fade-off range for a smooth transition between
oblique surfaces and aligned surfaces.

3. There's no distance-based fadeoff toward the end of the projector
range. Many decal implementations have this.

This addresses bevyengine#2401.
 
## Showcase

![Screenshot 2025-01-11
052913](https://github.com/user-attachments/assets/8fabbafc-60fb-461d-b715-d7977e10fe1f)
@alice-i-cecile
Copy link
Member

Thank you to everyone involved with the authoring or reviewing of this PR! This work is relatively important and needs release notes! Head over to bevyengine/bevy-website#1980 if you'd like to help out.

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

Labels

A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible M-Release-Note Work that should be called out in the blog due to impact S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants