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

Add multimesh_set_buffer_raw to RenderingServer #10650

Open
FireCatMagic opened this issue Sep 3, 2024 · 0 comments · May be fixed by godotengine/godot#96541
Open

Add multimesh_set_buffer_raw to RenderingServer #10650

FireCatMagic opened this issue Sep 3, 2024 · 0 comments · May be fixed by godotengine/godot#96541

Comments

@FireCatMagic
Copy link

Describe the project you are working on

This issue stems from another issue in the main repo, which explains it in greater detail:
godotengine/godot#96503
Please read it first.

In short, for my specific use case, here's a quote from my previous issue:

It proves very useful to pack as much data into this custom data as possible - for example in my game it can be used to render a ton of unique blocks at once (game is like sm64 but a level creator), or missiles with customizations, etc Each block can have a uint8 pattern which is referenced using a texture array, so 8 bits go into the data. Then the block itself can have a color too, as well as the pattern, so rgb of the block goes into COLOR.rgb, and the R channel of pattern color goes into COLOR.a, This leaves 16 bits of color data left, which can easily be added into the bits, leaving 24 used Then the scale of the block has to be added to properly tile the patterns, with precision being cut to save bits, so we will limit blocks scale from 0-1023 and pack their scale into the integer range with 10 bits per component, 30 bits in total Leaving 54 bits used up at this point I could go on, but this is just one example of how efficiently multimesh custom data can be used to pack a ton of data and render a lot of objects efficiently

Describe the problem or limitation you are having in your project

The buffer used inside MultiMesh is a PackedFloat32Array - and as I found out, when using MultiMesh custom data in the Compatibility renderer, the buffer gets messed with which leads to data loss when trying to perform bit-precise operations in shaders.

Quoted from huwpascoe in my previous issue:

Okay, here's what's going on.

transform3d:float32[12]
color:float32[4]
custom:float32[4]

The buffer stores the instance data as float32 regardless of the actual driver. So forward+ or compatible, the data is the same.

But in the case of the gles3 driver, when uploading to the GPU, it copies the buffer, compressing the color and custom components as float16.

https://github.com/godotengine/godot/blob/8120e0324a48190f58616378746d517e4ad40965/drivers/gles3/storage/mesh_storage.cpp#L1927-L1932

Bad ending

The design has been chosen as an abstraction layer, and it's unlikely the rendering team will support a change to bypass that abstraction. This technically leaves only 11 bits of lossless data, integer range of [-2048, 2047] per rgba component for gles3 driver.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The ability to pass direct bytes to the buffer and skip conversions would solve my use case of not being able to set custom data accurately.
And this is a general-purpose addition - it isn't specific to my specific use case of needing accurate data. This could potentially help others who would like to pass raw bytes into the multimesh, because it's the entire buffer - not just one specific multimesh properties.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Essentially:
This proposal would be exclusive to RenderingServer - it is a low level addition that wont be needed in the MultiMesh resource, so in my opinion it belongs only in the RenderServer, with the other low-level functions.
Essentially, it'd just be
RenderingServer::multimesh_set_buffer_raw(RID rid, PackedByteArray buffer)

If this enhancement will not be used often, can it be worked around with a few lines of script?

The multimesh buffer is impossible to access directly in raw form, it only can be modified using the exposed PackedFloat32Array buffer.

What seperates this from just doing PackedByteArray::to_float32_array is the fact that setting the buffer raw skips the abstraction layer, such as any compressing of the color and custom data values as float16 which is done in the Compatibility renderer

Is there a reason why this should be core and not an add-on in the asset library?

It's part of the core rendering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants