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

[Merged by Bors] - bevy_pbr2: Add support for configurable shadow map sizes #2700

Conversation

superdump
Copy link
Contributor

Objective

Add support for configurable shadow map sizes

Solution

  • Add DirectionalLightShadowMap and PointLightShadowMap resources, which just have size members, to the app world, and add Extracted* counterparts to the render world
  • Use the configured sizes when rendering shadow maps
  • Default sizes remain the same - 4096 for directional light shadow maps, 1024 for point light shadow maps (which are cube maps so 6 faces at 1024x1024 per light)

@NiklasEi NiklasEi added A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible labels Aug 21, 2021
@cart
Copy link
Member

cart commented Aug 24, 2021

Is there a reason not to do this configuration per-light?

@superdump
Copy link
Contributor Author

Is there a reason not to do this configuration per-light?

We use array textures / cubemap array textures for directional and point lights. They require that dimensions of all textures are the same. I don’t know if we could simply use texture arrays (ie array<texture_2d<f32>>) and configure per-light. I can try it. I guess it will require reworking the shadow pass code a bit.

@superdump
Copy link
Contributor Author

Or I suppose what is also common is to use a shadow atlas. I think for point lights you would then need to stop using cubemaps though.

@superdump superdump force-pushed the pipelined-configurable-shadow-map-sizes branch from aa07be7 to e9d8834 Compare August 24, 2021 10:16
@superdump
Copy link
Contributor Author

superdump commented Aug 24, 2021

Is there a reason not to do this configuration per-light?

We use array textures / cubemap array textures for directional and point lights. They require that dimensions of all textures are the same. I don’t know if we could simply use texture arrays (ie array<texture_2d<f32>>) and configure per-light. I can try it. I guess it will require reworking the shadow pass code a bit.

I was wrong, it seems you can't do this. You can't bind a single uniform that is an array of textures. So then we would have to implement a texture atlas I think. That's a much more involved process, especially considering we'd have to manually reimplement cubemaps, which I wouldn't be opposed to doing. :) We can do it but it feels like we have more important things to do for now?

@superdump
Copy link
Contributor Author

Well, it seems there is one more approach that could be useful. We would probably only have a fairly small set of powers of 2 sizes for shadow maps. We could have a small set of array textures of different sizes, and draw into the appropriate one as necessary. Each array texture takes one texture slot and we can only bind a limited number of textures so we want to keep the number of options low. But it also brings the benefit of, say, point lights further away from the camera that cover far fewer texels on screen can use a lower resolution shadow map and we can move things around. A bit like cascades for directional lights but instead of increasing the size of the volume covered by the projection and keeping the resolution the same, we can keep the volume covered the same and decrease the resolution, if you see what I mean.

We would need to decide what resolutions to offer and then through implementation I expect it would become clearer how to limit what textures are allocated and bound or so. Unity has some formulae with maxima for this: https://docs.unity3d.com/Manual/shadow-mapping.html and Godot has a global directional shadow map size, and a global shadow atlas size: https://docs.godotengine.org/en/stable/tutorials/3d/lights_and_shadows.html

@superdump
Copy link
Contributor Author

Just for some kind of reference on the Unity formulae, I plotted them in graphtoy:
Screenshot 2021-08-24 at 21 11 13
The orange line is for directional lights, the yellow for spot lights, and the green for point lights. And I plotted it at the highest quality setting. The top step is 4096, the middle is 2048, then 1024, and so on. The horizontal axis is just the input parameter that they call 'shadowCustomResolution'. My main takeaway about directional and point light shadow maps is that directional is usual 1-2 powers of 2 higher resolution than the point light cubemaps, which I suppose makes sense if you want roughly equal size per light as a cubemap is 6 faces.

@cart
Copy link
Member

cart commented Aug 24, 2021

Ahhh right. Totally forgot about the arrays. We do have some atlas code already written, but it would need to be adapted to handle "gpu-side" textures. Probably makes sense to keep it simple / stick with globals for now and come back to this later when it is more of a priority. I agree that there are bigger fish to fry at the moment.

@superdump
Copy link
Contributor Author

Ahhh right. Totally forgot about the arrays. We do have some atlas code already written, but it would need to be adapted to handle "gpu-side" textures. Probably makes sense to keep it simple / stick with globals for now and come back to this later when it is more of a priority. I agree that there are bigger fish to fry at the moment.

I agree. And I was chatting with @StarArawn about the atlas code but using a shadow atlas has a bunch of its own problems to deal with like handling filtering at/across edges of tiles in the atlas, and reimplementing cube mapping. @StarArawn suggested using a few array textures at different resolutions instead, but I think even that could wait.

@cart
Copy link
Member

cart commented Aug 25, 2021

bors r+

bors bot pushed a commit that referenced this pull request Aug 25, 2021
# Objective

Add support for configurable shadow map sizes

## Solution

- Add `DirectionalLightShadowMap` and `PointLightShadowMap` resources, which just have size members, to the app world, and add `Extracted*` counterparts to the render world
- Use the configured sizes when rendering shadow maps
- Default sizes remain the same - 4096 for directional light shadow maps, 1024 for point light shadow maps (which are cube maps so 6 faces at 1024x1024 per light)
@bors
Copy link
Contributor

bors bot commented Aug 25, 2021

@bors bors bot changed the title bevy_pbr2: Add support for configurable shadow map sizes [Merged by Bors] - bevy_pbr2: Add support for configurable shadow map sizes Aug 25, 2021
@bors bors bot closed this Aug 25, 2021
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants