Skip to content

Sprite masks #10169

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
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

colinjneville
Copy link

Objective

Adds the ability to mask Sprites with other Images.
Implements #4210

masking

Solution

Usage

  • Spawn an Entity with Mask containing a handle to the Image. Most of the other fields work like the ones from Sprite.
  • Spawn a SpriteBundle(s) with Masked components taking the Entity with the Mask component.

A Mask will be applied to all rendered Masked Sprites pointing to it. A Sprite can only be affected by a single Mask.

Pipeline implementation

  • Masked sprites add 2 additional specialized pipelines for with and without threshold values.
  • The mask texture and sampler form uniform group(2), optional uniforms (i.e. just threshold currently) form group(3). Adds SIXTEEN_BYTE_ALIGNMENT define to align uniforms when targeting WebGL2.
  • Masked sprites use an alternative vertex buffer that also includes the mask's affine transformation.
  • Sprite batches are now delineated by a change in either the Sprite Image or Mask.

Shader implementation

  • In the vertex shader, for each Masked vertex, calculate the effective Mask uv coordinates at that point. (If the vertex is not contained within the Mask bounds, the UVs will be outside of the 0 to 1 range and use the sampler's AddressMode.)
  • In the fragment shader, sample the mask texture with these UVs, taking the red value1
  • If a threshold value is set, map this value to 0.0 if it is less than the threshold, otherwise 1.0.
  • Multiply the fragment output alpha by this value.

Design concerns

Sampler AddressModes

Changing the AddressMode of the mask's sampler is useful to set masking state outside of the mask bounds, or to create a repeating mask. Currently, setting the sampler can't be be done as a part of Image loading, it must be done after loading is complete #6893. The recent asset loading changes could make this easy to allow with ImageLoaderSettings, if ImageSampler were serializable.

Note, AddressMode::ClampToBorder is not currently supported by WebGPU (gpuweb/gpuweb#1305), though it can be replicated with ClampToEdge and adding a slight border to the mask.


Changelog

  • Added the Mask and Masked components. Sprites with Masked components will be masked by the linked Mask entity.

Migration Guide

  • Added fields to ExtractedSprite, ExtractedSprites, SpritePipeline, SpriteMeta, SpriteBatch, and ImageBindGroups.

Footnotes

  1. To allow single-channel grayscale masks

@github-actions
Copy link
Contributor

Welcome, new contributor!

Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨

@github-actions
Copy link
Contributor

The generated examples/README.md is out of sync with the example metadata in Cargo.toml or the example readme template. Please run cargo run -p build-templated-pages -- update examples to update it, and commit the file change.

@superdump
Copy link
Contributor

My first thought is that this should be implemented like alpha mask for 3D. But, if you want to do masking of transparent materials separate to its transparency, then a different method is needed indeed.

@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible A-Rendering Drawing game state to the screen labels Oct 18, 2023
@alice-i-cecile alice-i-cecile added this to the 0.13 milestone Oct 18, 2023
@alice-i-cecile
Copy link
Member

@colinjneville can you resolve merge conflicts? I'd like to wrangle review effort for 0.13

@alice-i-cecile alice-i-cecile modified the milestones: 0.13, 0.14 Feb 2, 2024
@alice-i-cecile alice-i-cecile added the M-Needs-Release-Note Work that should be called out in the blog due to impact label Feb 22, 2024
@BD103 BD103 added the S-Adopt-Me The original PR author has no intent to complete this work. Pick me up! label Apr 25, 2024
@BD103
Copy link
Member

BD103 commented Apr 25, 2024

Making this up for adoption, after some discussion on Discord.

@alice-i-cecile alice-i-cecile removed this from the 0.14 milestone May 13, 2024
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-Needs-Release-Note Work that should be called out in the blog due to impact S-Adopt-Me The original PR author has no intent to complete this work. Pick me up!
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

4 participants