-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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] - Add 2d meshes and materials #3460
Conversation
This fixes #3326 so it's part of the 0.6 milestone For bevy_prototype_lyon, it's using its own shaders / pipeline so probably not related to this one |
This PR is what will allow people to use their own shaders/pipelines in 2d along the new sprite pipeline. This implementation has an important difference with how it worked in 0.5 with |
The default orthographic camera is set to render 1 world unit as 1 pixel. If we change this to be 1-1 with world units then the default 2d camera (and sprite scaling) should also be changed, right? For the record I much prefer keeping the meshes in world unit scale and adjusting the camera projection scale to correctly display the target pixels per unit. However, that is not what the default is set up for right now. May be better to keep it consistent with sprites (scale by size/pixels) and leave the alternative for a separate pr/poc. |
Attempted to port Is that possible as-is with a custom pipeline / shader, or would something like #3120 be required? I suppose it could generate a separate mesh for stroke and fill, but that doesn't seem ideal.
|
I'm not planning on touching sprite or camera scaling, that stays the same. The difference only applies for people that used a
It's already possible to define the vertex buffer as you need if you use a custom pipeline and shader, I think #3120's goal it to make it less involved.
It sounds like a good temporary hack until #3120 is merged.
The UI rendering is basically a copy of the sprite rendering already. When we reach a consensus on how 2d meshes and materials should work, I should be able to either clone it into bevy_ui, or maybe add a generic parameter somewhere to reuse it. |
I understand, what I'm trying to say is it could be confusing to have opposite default scaling behavior between a custom 2d mesh and a 2d sprite (scaling by world units vs scaling by pixels). They should stay the same, and if we're going to change one we should change both in my opinion. In other words if someone makes a Mesh2dBundle with a unit sized quad for a mesh, wouldn't it make intuitive sense for it to render identically to a sprite when using the default orthographic camera? |
In that case, why are they not using a sprite? 2d meshes are for a different use case IMO. Also, the texture is optional in ColorMaterial, how would it scale when it's not set? |
In my case I am building a single mesh made up of unit sized squares (a tilemap basically). I'm not using individual sprites because every tile in my grid is built from the same texture and my shader reads unique data to render each tile from the mesh verts. Of course I have no issue adjusting if the default scaling is changed, just saying it's a case where I intuitively expect it to work similar to a sprite, but maybe my use case is outside the norm. If the handle doesn't point to a texture I would expect it to default to world scaling. |
Actually nevermind, now that I'm thinking about it I'm having to manually scale each "tile" anyways otherwise they would all be the size of the entire texture. I think changing the default does make sense. You were right in the first place, sorry about that. |
No problem, thanks for testing the PR and giving feedback 😄 |
I wasn't happy with the previous solution to break sprite batching. It simply allowed other kinds of 2d items to add their depth in Pros:
Cons:
In order for batching to work for all 2d pipelines, it needs to work directly on the render phase, after all items have been added. Pros:
Cons:
The performance comparison is not exactly fair, it was worse at first so I did an optimization pass (but that could be backported to the previous batching solution). Also, the extract function is now more than twice as fast, which will make actual pipelining even more desirable. The new solution introduces a Other changes:
|
Silly question maybe but I still don't understand why 2D and 3D are that much separated. And now, as the PR description details, we're cloning even more functionality from 3D into 2D to be on parity. Why can't there be a single path for both 2D and 3D meshes? Isn't a 2D mesh just a corner case of a 3D one? Is there any other engine going to that length to separate 2D and 3D? We have already some optimizations for 2D cases, like the layered distance calculation (Z-based instead of Euclidian). What else is so specific that it cannot be made generic over 2D and 3D? |
The performance of bevymark on my computer has a lot of variation (even over time for a single run), so it's difficult to give a precise number. I kept 15% as a higher bound to be safe, but on average it seems closer to your numbers.
I tested it works by adding a few items to the
That's great 😄 |
It didn't seem like a super interesting example from a user's perspective to me, and it's pretty much just a mashup of Seemed like a useful thing to have in the commentary section of this PR though. Maybe a simpler example than Happy to work on any of the above if it helps this PR through. edit: Cleaned up that gist a bit just in case. |
I can't seem to get Renders nothing for me. |
Seems to fix it. |
Ahh yup, that did it. The new version of Sprites take the direct image handle so that's how I got mixed up, thank you! Edit: Updated my gist to a working version with comments if you're interested in including a ColorMaterial example |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! I think this is probably good to go for now after the one comment is resolved.
Part of me wishes we waited to implement generic batch merging: the sprite perf loss is regrettable (~100k at 60fps to ~90k). We've already lost a bit of perf as the renderer expanded, so losing even more "hurts". And I'm worried that in practice this impl won't batch across z-levels as much as it could:
[A(z = 1), B(z = 2), A(z=2)]
We could technically batch A, but because B got arbitrarily sorted in front of A, the batches will remain split. Handling that case properly would probably require moving batching back to being more local, then somehow checking if something somewhere would split the batch. That would have the benefit of allowing us to do arbitrary batch logic per-context (and maybe regain some sprite batching perf). But that would require some synchronized "is there something else on this z-level" operation. Not sure doing that work would be a net win on average, but its worth discussing.
If the old "non-generic" version is still available somewhere, id like to see it (github doesnt show the old version). But I wouldn't block on that.
That's an option too, we could bench it. I'm more partial to a generic solution that also accounts for the on-screen overlap to really maximize batches.
The commit before the generic version is 798a0ba, we could use it for 0.6 and postpone the generic stuff (we might want to backport the perf improvements). Nical suggested on discord to use the |
I pushed the other possible perf improvements in this branch if you want to try them: https://github.com/Davier/bevy/tree/mesh2d_perf |
Seems like frustum culling starts becoming a win again in let map_size = Vec2::splat(320.0); // culling pulls ahead at 640.0 or so, or ~380k sprites (that mesh2d_perf branch with/without culling commit) |
Bawhaha my commit search was apparently laughably bad 😄
I'm getting ~8k more sprites with these. Seems worth it! Looks like removing ComputedVisibility and
Note that Sprites don't currently have frustum culling. Visibility just gets mirrored to ComputedVisibility. |
That explains a great deal. |
Also: @Davier let me know if you won't be able to add the optimizations to this pr by the end of the day. Happy to pick up that work. |
@cart done! I'll go to sleep now though, please handle it if I broke anything 😄 |
bors r+ |
# Objective The current 2d rendering is specialized to render sprites, we need a generic way to render 2d items, using meshes and materials like we have for 3d. ## Solution I cloned a good part of `bevy_pbr` into `bevy_sprite/src/mesh2d`, removed lighting and pbr itself, adapted it to 2d rendering, added a `ColorMaterial`, and modified the sprite rendering to break batches around 2d meshes. ~~The PR is a bit crude; I tried to change as little as I could in both the parts copied from 3d and the current sprite rendering to make reviewing easier. In the future, I expect we could make the sprite rendering a normal 2d material, cleanly integrated with the rest.~~ _edit: see <https://github.com/bevyengine/bevy/pull/3460#issuecomment-1003605194>_ ## Remaining work - ~~don't require mesh normals~~ _out of scope_ - ~~add an example~~ _done_ - support 2d meshes & materials in the UI? - bikeshed names (I didn't think hard about naming, please check if it's fine) ## Remaining questions - ~~should we add a depth buffer to 2d now that there are 2d meshes?~~ _let's revisit that when we have an opaque render phase_ - ~~should we add MSAA support to the sprites, or remove it from the 2d meshes?~~ _I added MSAA to sprites since it's really needed for 2d meshes_ - ~~how to customize vertex attributes?~~ _#3120_ Co-authored-by: Carter Anderson <[email protected]>
Objective
The current 2d rendering is specialized to render sprites, we need a generic way to render 2d items, using meshes and materials like we have for 3d.
Solution
I cloned a good part of
bevy_pbr
intobevy_sprite/src/mesh2d
, removed lighting and pbr itself, adapted it to 2d rendering, added aColorMaterial
, and modified the sprite rendering to break batches around 2d meshes.The PR is a bit crude; I tried to change as little as I could in both the parts copied from 3d and the current sprite rendering to make reviewing easier. In the future, I expect we could make the sprite rendering a normal 2d material, cleanly integrated with the rest.edit: see #3460 (comment)Remaining work
don't require mesh normalsout of scopeadd an exampledoneRemaining questions
should we add a depth buffer to 2d now that there are 2d meshes?let's revisit that when we have an opaque render phaseshould we add MSAA support to the sprites, or remove it from the 2d meshes?I added MSAA to sprites since it's really needed for 2d mesheshow to customize vertex attributes?Add vertex buffer layout toMesh
#3120