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

Quad shadows #1882

Merged
merged 9 commits into from
Jan 20, 2024
Merged

Quad shadows #1882

merged 9 commits into from
Jan 20, 2024

Conversation

nicksenger
Copy link
Contributor

@nicksenger nicksenger commented May 29, 2023

This PR adds the options of specifying a Shadow for quads having some color, offset and softness:

pub struct Shadow {
  color: Color,
  offset: Vector,
  softness: f32
}

The custom quad example is updated to have a shadow:

Screen Shot 2023-05-28 at 10 46 35 PM

Some things don't work yet:

  • Quads with gradient backgrounds can't have shadows: trying to do so results in vertex buffer stride exceeds limit on WASM builds. Maybe there is a straightforward way to increase this limit but I couldn't find it (not that familiar with wgpu)
  • Mixing isn't correct with translucent quads: ideally the shadow would be visible through the translucent background, and the shadow should be lighter to accommodate translucency of the background. Also the border may have different translucency from the background which currently isn't accounted for. I'm not sure how common this use-case is, but in a pinch it could probably be simulated through layering of multiple quads
  • No shadows on the software renderer: haven't looked into it

@bungoboingo
Copy link
Contributor

bungoboingo commented May 29, 2023

Quads with gradient backgrounds can't have shadows: trying to do so results in vertex buffer stride exceeds limit on WASM builds. Maybe there is a straightforward way to increase this limit but I couldn't find it (not that familiar with wgpu)

I got a good suggestion this morning which will allow us to pack the gradient data tighter, I can do a PR with it soon. Should allow for shadow data easy peasy. The absolute max is 16 shader locations which we are hitting now, 32 bits per location.

wgpu/src/shader/quad.wgsl Outdated Show resolved Hide resolved
wgpu/src/shader/quad.wgsl Outdated Show resolved Hide resolved
@hecrj hecrj added feature New feature or request rendering styling labels May 29, 2023
@nicksenger
Copy link
Contributor Author

Quads with gradient backgrounds can't have shadows: trying to do so results in vertex buffer stride exceeds limit on WASM builds. Maybe there is a straightforward way to increase this limit but I couldn't find it (not that familiar with wgpu)

I got a good suggestion this morning which will allow us to pack the gradient data tighter, I can do a PR with it soon. Should allow for shadow data easy peasy. The absolute max is 16 shader locations which we are hitting now, 32 bits per location.

Ah cool, that explains it then! No rush, I know you are working on some related things so don't want to distract from that. My main motive for looking into this was to compare the performance in browsers against CSS shadows, flutter's CanvasKit renderer, etc, since shadows and motion seem to have made a comeback in UI.

@nicksenger
Copy link
Contributor Author

We could also save some space here by assuming the shadow color is always black and only exposing its opacity. It doesn't seem like colored shadows would be a common use-case.

@bungoboingo
Copy link
Contributor

After #1885 is merged should have plenty of space in the gradient attribute to add whatever you need for this PR 👍

core/src/shadow.rs Outdated Show resolved Hide resolved
@hecrj hecrj added this to the 0.10.0 milestone Jun 26, 2023
@hecrj hecrj marked this pull request as ready for review July 12, 2023 02:32
@hecrj hecrj modified the milestones: 0.10.0, 0.11.0 Jul 12, 2023
@nicksenger
Copy link
Contributor Author

nicksenger commented Jul 17, 2023

Ok I think this should be good to review now. I added some sliders for the shadow properties in the custom quad example and updated the software renderer to also support quad shadows using essentially the same sdf approach. I'm not sure if this strategy of iterating through each pixel is acceptable from a performance standpoint, but I didn't notice much difference with my slow machine- the software renderer dev build still drops frames but not the release build.

There were a couple odd things I noticed (likely my own oversights as it's my first time working with tiny-skia 😅 ):

  • When specifying a colored shadow, the red and blue channels on the tiny-skia colors used to build the pixmap appear to be flipped! Maybe there is some weird endianness thing happening here when going to bytes? I couldn't figure it out.
  • Despite my best efforts there seems to be some deviation in the smoothstep function between the 2 implementations: doubling the provided lower bound in the software one gives the closest match to the shadow produced by wgpu. All the resources I looked at suggested this formula for smoothstep, so it's hard to believe that function is the issue 🤔

@hecrj
Copy link
Member

hecrj commented Jul 18, 2023

@nicksenger Thanks! Will take a look soon!

  • The red and blue channels are indeed flipped! This is because our presentation layer (softbuffer) needs the bytes in BGRA order. You can use the into_color helper:

fn into_color(color: Color) -> tiny_skia::Color {
tiny_skia::Color::from_rgba(color.b, color.g, color.r, color.a)
.expect("Convert color from iced to tiny_skia")
}

  • tiny-skia blends colors using sRGB as if it were a linear color space (see https://webcolorisstillbroken.com/). By default, iced_wgpu transforms colors into linear RGB before blending. You can enable the web-colors feature in iced to make iced_wgpu behave like tiny-skia.

@nicksenger
Copy link
Contributor Author

Ah thanks @hecrj , the difference I was seeing was due to the blending mode 👍 I removed the compensatory adjustments in the tiny-skia implementation and now the shadows look pretty much exactly the same when using the web-colors feature with wgpu.

Copy link
Member

@hecrj hecrj left a comment

Choose a reason for hiding this comment

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

Awesome! Thank you!

I made some changes here and there to introduce a new Border struct analogous to Shadow for consistency.

I think we can ship this! 🚢

@hecrj hecrj merged commit 545cc90 into iced-rs:master Jan 20, 2024
13 checks passed
@nicksenger
Copy link
Contributor Author

Woah awesome! Thanks for doing the rebase and making those changes, they make sense to me 👍

@hecrj hecrj added the addition label Jan 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants