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

bevy_pbr2: Add support for most of the StandardMaterial textures #4

Merged
merged 24 commits into from
Jun 27, 2021

Conversation

superdump
Copy link

Normal maps are not included here as they require tangents in a vertex attribute.

Normal maps are not included here as they require tangents in a vertex attribute.
@superdump
Copy link
Author

This is not ready to merge. I thought it was as I thought I ran texture_pipelined one time and saw the same as texture, but now I think I just ran texture and didn't notice my mistake. :) It's almost there though I think. My current problem is:

cargo run --release --example texture_pipelined

...

     Running `target/release/examples/texture_pipelined`
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', pipelined/bevy_pbr2/src/render/mod.rs:174:91
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

@superdump
Copy link
Author

Still more to fix, but making some progress:
Screenshot 2021-06-20 at 00 43 12

I need to figure out a good way of mapping from view space z (where -z goes away from the camera in front of it) to some fixed number of bits of unsigned integer to fit into a sort key.

From 'fintelia' on the Bevy Render Rework Round 2 discussion:

"My understanding is that GPUs these days never use the "execute both branches
and select the result" strategy. Rather, what they do is evaluate the branch
condition on all threads of a warp, and jump over it if all of them evaluate to
false. If even a single thread needs to execute the if statement body, however,
then the remaining threads are paused until that is completed."
@superdump
Copy link
Author

Now supporting unlit, double-sided, and optional texture fetches using uniform control flow: Screenshot 2021-06-20 at 14 36 06

@superdump
Copy link
Author

I think this is ready for review.

I think the sorting should be solved separately rather than doing it in this PR. There is shadow acne too and we should add some configurable biases for this but it felt like a rabbit hole we can go down another time, I just did enough for the pbr_pipelined example to not have all spheres in shadow because the light projection's z_far was hard-coded to 20.0 which was not far enough. I've set the light projection's z_far to light.range, and I increased the FOV to 90 as I guess we will do cube maps or something.

The projection member of PointLight in pbr.frag was holding the light's view projection matrix, so I renamed that. Our 'point lights' have a radius, so I renamed them to OmniLight.

@superdump
Copy link
Author

superdump commented Jun 25, 2021

This is in theory (and kind of practice) working on top of the updated pipelined-rendering with wgpu types and whatnot. Unfortunately on macOS no image is displayed in the bevy window, neither on this PR nor on pipelined-rendering. But if I run it through Xcode's GPU frame debugger, I can see that everything is being drawn correctly.
Screenshot 2021-06-25 at 14 35 53

let mesh_z = view_row_2.dot(mesh.transform.col(3));
// FIXME: Switch from usize to u64 for portability and use sort key encoding
// similar to https://realtimecollisiondetection.net/blog/?p=86 as appropriate
// FIXME: What is the best way to map from view space z to a number of bits of unsigned integer?
Copy link
Owner

Choose a reason for hiding this comment

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

I think the real answer is that we shouldn't do that :)

If we make Drawable generic, we can make sort_key whatever type we want

Copy link
Owner

Choose a reason for hiding this comment

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

We just need to make sure that the type we choose for a given phase is suitable for all possible things in that phase

Copy link
Author

Choose a reason for hiding this comment

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

Are we concerned about performance of not encoding into a directly comparable data type like usize or u64 or so? Depending on the sorting algorithm, a lot of comparisons could be made and if we’re doing something like A.a < B.a || A.b < B.b || … then it could result in a lot more comparison operations in practice. @mtsr raised this point to me earlier.

Copy link
Owner

Choose a reason for hiding this comment

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

I think its worth benchmarking when we make the switch.

@cart
Copy link
Owner

cart commented Jun 27, 2021

This looks good to me in general. Pushed a few small tweaks that probably won't be contentious. textured_pipelined doesn't draw the texture for me though 😄

image

@cart
Copy link
Owner

cart commented Jun 27, 2021

The bound color texture is the 1x1 white texture:

image

@cart
Copy link
Owner

cart commented Jun 27, 2021

Fixed! The problem was that we were extracting and drawing meshes even when their materials' textures haven't loaded yet. This resulted in the creation (and caching) of bind groups with empty white textures. The fix is to check the load state of each mesh's material's textures prior to extracting.

@cart
Copy link
Owner

cart commented Jun 27, 2021

We can optimize this by pre-computing material texture load state somewhere instead of checking for each entity. We should think about the best way to do this. I'm not a huge fan of hard coding a cache for this use case, as "sub asset load status" seems like a reasonable thing to keep track of.

We do this for asset server managed assets, but we don't do it for assets directly added to Assets collections.

@cart
Copy link
Owner

cart commented Jun 27, 2021

I'm gonna merge this as is to keep the ball rolling. Feel free to follow up if you have alternative ideas.

@cart cart merged commit b3e2fab into cart:pipelined-rendering Jun 27, 2021
@superdump
Copy link
Author

Fixed! The problem was that we were extracting and drawing meshes even when their materials' textures haven't loaded yet. This resulted in the creation (and caching) of bind groups with empty white textures. The fix is to check the load state of each mesh's material's textures prior to extracting.

I'd forgotten to test that example after updating for the bing group caching. Thanks for fixing it!

We can optimize this by pre-computing material texture load state somewhere instead of checking for each entity. We should think about the best way to do this. I'm not a huge fan of hard coding a cache for this use case, as "sub asset load status" seems like a reasonable thing to keep track of.

We do this for asset server managed assets, but we don't do it for assets directly added to Assets collections.

It's a bit unclear from what you've written what you mean the solution should be. I'm not 100% on what the problem is either. If the material's textures haven't loaded yet then bind groups were being created that use the dummy white texture and were not being updated once the texture loaded. You fixed that to not extract the mesh if any of its material textures were not yet loaded. But you're saying that this approach of checking if the texture has loaded is inefficient and we should use some other approach? Is it specifically because it is per-entity?

cart added a commit that referenced this pull request Jul 24, 2021
* bevy_pbr2: Add support for most of the StandardMaterial textures

Normal maps are not included here as they require tangents in a vertex attribute.

* bevy_pbr2: Ensure RenderCommandQueue is ready for PbrShaders init

* texture_pipelined: Add a light to the scene so we can see stuff

* WIP bevy_pbr2: back to front sorting hack

* bevy_pbr2: Uniform control flow for texture sampling in pbr.frag

From 'fintelia' on the Bevy Render Rework Round 2 discussion:

"My understanding is that GPUs these days never use the "execute both branches
and select the result" strategy. Rather, what they do is evaluate the branch
condition on all threads of a warp, and jump over it if all of them evaluate to
false. If even a single thread needs to execute the if statement body, however,
then the remaining threads are paused until that is completed."

* bevy_pbr2: Simplify texture and sampler names

The StandardMaterial_ prefix is no longer needed

* bevy_pbr2: Match default 'AmbientColor' of current bevy_pbr for now

* bevy_pbr2: Convert from non-linear to linear sRGB for the color uniform

* bevy_pbr2: Add pbr_pipelined example

* Fix view vector in pbr frag to work in ortho

* bevy_pbr2: Use a 90 degree y fov and light range projection for lights

* bevy_pbr2: Add AmbientLight resource

* bevy_pbr2: Convert PointLight color to linear sRGB for use in fragment shader

* bevy_pbr2: pbr.frag: Rename PointLight.projection to view_projection

The uniform contains the view_projection matrix so this was incorrect.

* bevy_pbr2: PointLight is an OmniLight as it has a radius

* bevy_pbr2: Factoring out duplicated code

* bevy_pbr2: Implement RenderAsset for StandardMaterial

* Remove unnecessary texture and sampler clones

* fix comment formatting

* remove redundant Buffer:from

* Don't extract meshes when their material textures aren't ready

* make missing textures in the queue step an error

Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
cart added a commit that referenced this pull request Jul 24, 2021
* bevy_pbr2: Add support for most of the StandardMaterial textures

Normal maps are not included here as they require tangents in a vertex attribute.

* bevy_pbr2: Ensure RenderCommandQueue is ready for PbrShaders init

* texture_pipelined: Add a light to the scene so we can see stuff

* WIP bevy_pbr2: back to front sorting hack

* bevy_pbr2: Uniform control flow for texture sampling in pbr.frag

From 'fintelia' on the Bevy Render Rework Round 2 discussion:

"My understanding is that GPUs these days never use the "execute both branches
and select the result" strategy. Rather, what they do is evaluate the branch
condition on all threads of a warp, and jump over it if all of them evaluate to
false. If even a single thread needs to execute the if statement body, however,
then the remaining threads are paused until that is completed."

* bevy_pbr2: Simplify texture and sampler names

The StandardMaterial_ prefix is no longer needed

* bevy_pbr2: Match default 'AmbientColor' of current bevy_pbr for now

* bevy_pbr2: Convert from non-linear to linear sRGB for the color uniform

* bevy_pbr2: Add pbr_pipelined example

* Fix view vector in pbr frag to work in ortho

* bevy_pbr2: Use a 90 degree y fov and light range projection for lights

* bevy_pbr2: Add AmbientLight resource

* bevy_pbr2: Convert PointLight color to linear sRGB for use in fragment shader

* bevy_pbr2: pbr.frag: Rename PointLight.projection to view_projection

The uniform contains the view_projection matrix so this was incorrect.

* bevy_pbr2: PointLight is an OmniLight as it has a radius

* bevy_pbr2: Factoring out duplicated code

* bevy_pbr2: Implement RenderAsset for StandardMaterial

* Remove unnecessary texture and sampler clones

* fix comment formatting

* remove redundant Buffer:from

* Don't extract meshes when their material textures aren't ready

* make missing textures in the queue step an error

Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants