bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.26k stars 3.58k forks source link

Good deterministic random hash in wgsl: pcg3d/pcg4d #11470

Open torsteingrindvik opened 9 months ago

torsteingrindvik commented 9 months ago

What problem does this solve or what need does it fill?

In shaders, whenever randomness is required a good hash function is good to have.

"Good" can mean:

What solution would you like?

Availability of pcg3d and pcg4d in Bevy. Perhaps via bevy_pbr/src/render/utils.wgsl, but it might be better to start putting noise/rng/hash functions in a dedicated wgsl file.

This paper shows why pcg is a great choice. Section 6.1 also has GLSL code for it, so only porting is needed.

The signatures for pcg3d and pcg4d is to both take and return vectors of unsigned ints.

The authors' ShaderToy example shows that we can get float versions via dividing the unsigned int vectors by float max. So pcg3df and pcg4df (float versions) would be great to have as well since we often operate on colors.

BD103 commented 9 months ago

This is an interesting idea and the implementation seems easy enough to translate. Bevy has never had an official RNG crate because of concerns for how it would be used, but perhaps it will be different with shaders.

I recommend pinging one of the people labeled "SME-Rendering" on the Bevy People page to get their advice on this matter. :)

See GLSL Code ```glsl uint3 pcg3d(uint3 v) { v = v * 1664525u + 1013904223u; v.x += v.y*v.z; v.y += v.z*v.x; v.z += v.x*v.y; v ^= v >> 16u; v.x += v.y*v.z; v.y += v.z*v.x; v.z += v.x*v.y; return v; } uint4 pcg4d(uint4 v) { v = v * 1664525u + 1013904223u; v.x += v.y*v.w; v.y += v.z*v.x; v.z += v.x*v.y; v.w += v.y*v.z; v ^= v >> 16u; v.x += v.y*v.w; v.y += v.z*v.x; v.z += v.x*v.y; v.w += v.y*v.z; return v; } ```
torsteingrindvik commented 9 months ago

because of concerns for how it would be used

:thinking: not sure what this means?

I recommend pinging one of the people

Then perhaps @IceSentry could chime in?

Also perhaps the scope of this issue could be increased (or a follow-up issue after) to have an example using the hash function to scroll noise like the shader-toy example I linked. This would be both instructional and would allow us to verify (at least visually) that over time the noise does not degrade.

So something like an example with a custom frag shader which writes its color output via the hash function onto all sides of a cube or something.

BD103 commented 9 months ago

because of concerns for how it would be used

🤔 not sure what this means?

Mainly I could see RNG being misused, especially for cryptographic purposes or not. For instance, should a bevy_rng crate read from /dev/urandom like getrandom or should it instead have a pseudo-random number generator like Python? I feel like this decision is better made by 3rd party libraries, so that the consumer can pick which they want.

On the other hand, I can't see any point in requiring a cryptographically-secure RNG function for shaders. I think it's a little easier to provide a default since it would be harder to misuse.

JMS55 commented 9 months ago

Security is not a concern for shader random functions.

For white noise, I'd like to upstream my PCG wgsl ports: https://github.com/JMS55/bevy/blob/solari3/crates/bevy_pbr/src/solari/global_illumination/utils.wgsl#L8-L36 For blue noise, there's spatio-temporal blue noise: https://github.com/JMS55/bevy/blob/solari3/crates/bevy_pbr/src/solari/stbn.ktx2

torsteingrindvik commented 9 months ago

Security is not a concern for shader random functions.

For white noise, I'd like to upstream my PCG wgsl ports: https://github.com/JMS55/bevy/blob/solari3/crates/bevy_pbr/src/solari/global_illumination/utils.wgsl#L8-L36 For blue noise, there's spatio-temporal blue noise: https://github.com/JMS55/bevy/blob/solari3/crates/bevy_pbr/src/solari/stbn.ktx2

Great, upstreaming would be appreciated :+1:

JMS55 commented 9 months ago

@torsteingrindvik I opened https://github.com/bevyengine/bevy/pull/11956. I didn't add 3d or 4d functions. Let me know what you want that's missing.