shadertoy's GLSL and Rust Bevy WGSL incoherence

1.6k views Asked by At

I'm trying to get into Shaders and decided to init a project using Rust and Bevy, the objective is to reproduce a raymarching shader just to confirm that the environment is ok, i was able to reproduce the "fragCoord" by using:

var fragCoord: vec2<f32> = vec2<f32>((input.uv.x+1.0) * iResolution.res.x, (input.uv.y+1.0) * iResolution.res.y);
//iResolution.res is the screen res in pixels

up to this point everything is ok, when trying to reproduce BigWing's example i notice a difference in the result imagine when passing only the follow line:

vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y;
//where fragCoord is the pixel position of the frag and the iResolution is the screen size in pixels

shader result image

I suspected about fragCoord, but after a check, it give the same result as shadertoy's version, but after trying to check iResolution I noticed a big difference, then did a test with fixed output color values and got this, as you can see, the color is not the same:

Result of using the same values for the shader

I used different browser too but got the same result :(, i suspect now of my camera/mesh code:

//camera
fn spawn_camera(mut commands: Commands) {
    let mut camera = OrthographicCameraBundle::new_2d();
    camera.orthographic_projection.right = 0.0;
    camera.orthographic_projection.left = 1.0 ;
    camera.orthographic_projection.top = 0.0;
    camera.orthographic_projection.bottom = 1.0;
    camera.orthographic_projection.scaling_mode = ScalingMode::None;
    commands.spawn_bundle(camera);
}

//mesh to display the frag shader
let ZOOM = 1.0;
let vertices = [
       ([-1.0,-1.0,0.0] /*pos*/, [0.0,0.0,0.0] /*normal*/, [1.0 / ZOOM, 1.0 / ZOOM] /*uv*/), //bottom left
       ([-1.0,1.0,0.0], [0.0, 0.0, 0.0], [1.0 / ZOOM, -1.0 / ZOOM]), //top left
       ([1.0,1.0,0.0], [0.0, 0.0, 0.0], [-1.0 / ZOOM, -1.0 / ZOOM]), //top right
       ([1.0,-1.0,0.0], [0.0, 0.0, 0.0], [-1.0 / ZOOM, 1.0 / ZOOM]), //bottom right];

let indices = Indices::U32(vec![ 0, 3, 2,0, 2, 1]);

My main question here is, how i can reproduce the exact environment of shadertoy using Rust and Bevy? If it's not possible please show me an alternative. I'm just trying to use the fragment shader, I don't need to show anything besides the actual fragment shader result.

1

There are 1 answers

0
user3054986 On BEST ANSWER

Kevin Reid is correct. The default color space for is sRGB: How to specify color space for canvas in JavaScript?

You can get the expected result by transforming your colors from linear color space to sRGB, like it is posted here: https://www.shadertoy.com/view/Wd2yRt

Which will make your code look like this:

vec3 lin2srgb( vec3 cl )
{
    vec3 c_lo = 12.92 * cl;
    vec3 c_hi = 1.055 * pow(cl,vec3(0.41666)) - 0.055;
    vec3 s = step( vec3(0.0031308), cl);
    return mix( c_lo, c_hi, s );
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y;
    vec3 c = vec3( lin2srgb( vec3(uv.xy, 0.0) ) );
   
    fragColor = vec4(c,1.0);
}

Making you end up with: enter image description here

So, to finally answer your question: To reproduce the shadertoy's environment, you need to use the sRGB color space in Rust.

Alternative: Just use the transformation to sRGB in shadertoy.