Open ivanceras opened 3 months ago
Why can't you use the world_position
for this?
Adding this to bevy would need to be optional because that would be a lot of wasted bandwidth for most games. The issue is I'm not sure how that would be implemented to let users control that.
Why can't you use the
world_position
for this?
Because world_position
only works if the Mesh
is not rotated or translated around.
If I use world_position, the mapping will be distorted for objects that are not in the origin and/or rotated at some axes.
Adding this to bevy would need to be optional because that would be a lot of wasted bandwidth for most games. The issue is I'm not sure how that would be implemented to let users control that.
There is only 1 field that needs to be added to VertexOutput
which is a vec4<f32>
, even a vec3<f32>
would suffice. I don't think it would add a lot of bandwidth.
struct VertexOutput {
...
@location(2) local_position: vec4<f32>,
...
Even better:
world_position
to be set to the value of vertex.position
in mesh.wgsl
#ifdef VERTEX_POSITIONS
out.world_position = vertex.position;
let position = mesh_functions::mesh_position_local_to_world(world_from_local, vec4<f32>(vertex.position, 1.0));
out.position = position_world_to_clip(position.xyz);
#endif
If users want the old intended value for the `world_position` in the fragment shader, they can do so cheaply using:
```wgsl
let old_version_world_position = mesh_functions::mesh_position_local_to_world(world_from_local, in.world_position);
There is only 1 field
It's still 128 bit more per vertices and it would not be used by the vast majority of people. I have no idea if that actually would make a noticeable performance impact. A PR implementing it would need benchmark numbers to be approved.
Use the world_position to be set to the value of vertex.position
That's not better, that's worse because now the world_position isn't the world_position and the much more common use case of the world_position that is already used by every mesh using the StandardMaterial would break.
I think it probably makes sense to include the world to local matrix so the fragment world position (or any world position/direction) can be cheaply converted to local space. Part of it is already included: https://github.com/bevyengine/bevy/blob/160bcc787c9b2f8dacafbf9dca7d7a6b2349386a/crates/bevy_pbr/src/render/mesh.rs#L264
Linking this as another possible general solution that would allow access to whatever in the vertex shader to forward to fragment. https://github.com/bevyengine/bevy/issues/13373
What problem does this solve or what need does it fill?
When writing a fragment shader for a material that needs the position of the point relative to the mesh origin.
For example, I'm writing a shader for Earth material. The mesh is destructible, so vertex is not only limited to surface vertices, but also to vertices of subterranean holes and crevices due to mesh destruction. So, fragments that is below the planet radius is using some procedural function to create a color similar to a lava.
What solution would you like?
bevy_pbr::forward_io::Vertex::position
into one of the fields forbevy_pbr::forward_io::VertexOutput.local_position
.bevy_pbr::mesh_types::MeshTypes::world_from_local
, name it:inv_world_from_local
orlocal_from_world
.Either 1 or 2 will suffice for obtaining the mesh local position.
What alternative(s) have you considered?
Currently, I wrote a custom struct to hold an output of the vertex shader to include
local_position
like so:Then I can use the
local_position
in the fragment shader to give a color of the fragment based on its position relative to the object mesh.If an
inverse_world_from_local
is included inVertexOutput
calculating thelocal_position
would simply be:In cases, where there is no access to vertex shader, ie: Meshlet material I use a rather expensive
inverse_mat4(world_from_local)
function to get the inverse of theworld_from_local
. Then getting thelocal_position
would then just be:The code for
inverse_mat4
is very expensive, and it is calculated for each fragment.Additional context
https://github.com/user-attachments/assets/8c735ab2-a8a6-4060-b447-97b08f3e05d1