Dithering node Unity to Godot 4 ?

Hey,
I try do redo the same technic a was doing in unity shader graph, i'm close to the same result in godot with the visual shader.

I just want a nice dithering effect in the fragment. But i got the same issue in unity, the dither don't have a nice 'disposition' and only the dither node in unity is actually working. Only blue noise texture is not a problem with texture of course.

Here my godot disposition and result :
here the result in unity with the dither node :

i tried as well to "redo" the dither node in a expression, but i'm not good at it. I which we could have a godot dither node in futur ^^
if somebody have a solution : ) i would love it !

Here the dither unity node
void Unity_Dither_float4(float4 In, float4 ScreenPosition, out float4 Out)
{
float2 uv = ScreenPosition.xy * _ScreenParams.xy;
float DITHER_THRESHOLDS[16] =
{
1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
};
uint index = (uint(uv.x) % 4) * 4 + uint(uv.y) % 4;
Out = In - DITHER_THRESHOLDS[index];
}

  • xyz replied to this.

    UlricL
    There you go

    shader_type canvas_item;
    render_mode blend_mix;
    
    uniform sampler2D screen: hint_screen_texture;
    
    void fragment(){
    	const float DITHER_THRESHOLDS[16] ={
    		1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
    		13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
    		4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
    		16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
    	};
    
    	vec2 uv = SCREEN_UV / SCREEN_PIXEL_SIZE;
    	int index = (int(uv.x) % 4) * 4 + int(uv.y) % 4;
    	vec3 pix = texture(screen, SCREEN_UV).rbg;
    	float pixLuma = 0.2126 * pix.r + 0.7152 * pix.g + 0.0722 * pix.b;
    
    	COLOR.rgb = vec3(clamp(pixLuma - DITHER_THRESHOLDS[index], 0.0, 1.0));
    	COLOR.a = 1.0;
    }

      Looks like your output/result might be blurred by mips in godot editor viewport. Outside of noting that I can't really tell much besides your view port zoom likely being an odd fraction so some of the zoomed pixels are displayed in different size to others.

        It's hard to see from your graph just what it is you're dithering. What is the image? Is it just UV-based noise? I think it would be easier to work out what your dither is doing if you started out with an image with distinguishable features. Maybe a picture of someone's face, or something like that.

          xyz
          thanks again xyz ! 🙂
          try to make it work in an expression but since i'm in a spatial shader that's not working ><.

          Megalomaniak
          award

          Sry for the bad screenshots,
          here a better one, as you can see my goal is to do everything in the visual shader, and on a spatial shader. That's why i was talking about unity dither node because you an put it everywhere.

          I just want to dither a simple noise texture as you can see, but the result is not good :/. That's not possible at all in a spatial shader ?

          • xyz replied to this.

            UlricL Pretty much the same code for the spatial shader:

            shader_type spatial;
            render_mode blend_mix,unshaded;
            
            uniform sampler2D noise;
            
            void fragment() {
            
            	const float DITHER_THRESHOLDS[16] ={
            		1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
            		13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
            		4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
            		16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
            	};
            
            	vec2 uv = FRAGCOORD.xy;
            	int index = (int(uv.x) % 4) * 4 + int(uv.y) % 4;
            	vec3 pix = texture(noise, UV).rbg;
            	float pixLuma = 0.2126 * pix.r + 0.7152 * pix.g + 0.0722 * pix.b;
            	ALBEDO = vec3(clamp(pixLuma - DITHER_THRESHOLDS[index], 0.0, 1.0));
            }

              xyz
              You made my day ! thanks again !
              here the result of the dither node in Godot ! 🙂 doing the same thing that the one in unity shadergraph node.

              the full expresion code below, i just adapt @xyz code to have only a dither texture => then you can use step with whatever image you want.

              const float DITHER_THRESHOLDS[16] ={
              		1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
              		13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
              		4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
              		16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
              	};
              	
              vec2 uv = FRAGCOORD.xy * Size;
              int index = (int(uv.x) % 4) * 4 + int(uv.y) % 4;
              Dither_Node = In - DITHER_THRESHOLDS[index];