#Having a hard time getting a Dithering shader to work

42 messages · Page 1 of 1 (latest)

upbeat sapphire
#

Hey! So I've been tinkering around with a dithering shader here: https://godotshaders.com/shader/dither-gradient-shader/ And I've been trying to adapt it to a 2D scene, by putting the shader material on a Color Rect that's on a Canvas Layer that's on a Camera 2D, kinda following this tutorial: https://youtu.be/x6dOxJa3zXY But even while inputting all the correct parameters it only shows up as a solid color, any thoughts on why that would be the case and the shader wouldn't work? I've tried messing around with different parameters but nothing seems to work, it changes colors from the palette when I go in negative contrast but that's about it..

Shader code is on the godotshaders page.

scarlet lark
#

Weird. I looked at this shader, and it is not clear to me how they are sampling the screen texture at all. They have variables that you'd think were names for doing that, but the stuff they set them equal to is just the texture that is passed to the shader by default from whatever you attach the shader to (the base texture of the object). So, this WILL work as-is if you put everything in a viewport, and then set the texture of your TextureRect equal to that viewport's texture, I suppose. The way I do screen-space shaders involves a different method, though:

// Holds the screen texture
uniform sampler2D screen_texture : hint_screen_texture, filter_nearest;

// Use as needed in our fragment function
vec2 screen_size = vec2(textureSize(screen_texture, 0)) / float(u_dither_size);
vec2 screen_sample_uv = floor(UV * screen_size) / screen_size;
vec3 screen_col = texture(screen_texture, screen_sample_uv).rgb;

I think added that first line and then changing those other lines might be able to do the trick in this case for you. Can't test right now, since I'm away from my actual pc. I kept the variable names the same except for the addition of "screen_texture" where it is used to store the screen texture and used in place of TEXTURE, which just sources the texture from the CanvasItem this shader's material is attached to.

#

I use Godot 4.x, and this is done differently in Godot 3.x. In 3.x you can just access SCREEN_TEXTURE directly, I believe. I think the change to how it is now in 4.x was made for performance reasons.

upbeat sapphire
#

The Shader in the demo project is on a subviewport container or something like that, so maybe they're somehow accessing some thing from that, I'm kinda trying to repurpose it in 2D so I don't have the same node setup, and I don't know what changed from 3.X to 4.X so it's a bit hard to figure it out

upbeat sapphire
#

And there some weird artifacting on the side - I remember in the demo they had a little gradient on the side to display what the dithering was doing but I don't think it's from the shader itself - pretty sure it was just a texture in the scene, so what would be causing this?

scarlet lark
#

That looks like it's caused by some transform offset wonkiness. Your setup includes a CanvasLayer as a child of a camera. I'm surprised that even works this well. I highly recommend the CanvasLayer be just a child of whatever your main scene is, instead. That way your dither filter just sits over top of everything always. You can set that new CanvasLayer to be a higher render layer using its "layer" property.

#

You can then turn it off and on, or move it around as needed on that layer without affecting or being affected by the positions of your other nodes.

upbeat sapphire
#

Alright sure I can work with that, but those side artifacts are a tad annoying

#

comes from the demo I'm guessing but idk where in the code would be displaying that side gradient

#

It seems to scale with the texture..

scarlet lark
#

I've never used that shader and looking through it...its at least got comments. That's more than you can expect from a lot of shader code out there. You might be able to solve the issue if it's due to the shader...BUT it might be related to color choices. Did you fiddle with the color parameters of the shader at all?

upbeat sapphire
scarlet lark
#

Also, have you tried running the scene?

#

It may look different when you actually run it.

upbeat sapphire
#

I tried switching the palettes, that didn't change anything, didn't mess with any of the code besides what you sent, but it looks like somehow the dither texture source gets displayed on the left side

#

shows up on the running scene as well

#

Artifact changes depending on what texture i put on it

scarlet lark
#

hmm.. I think this shader is interpreting that color as "between" two of its available choices in places, and it applying the dithering effect as a result.

upbeat sapphire
#

These are the textures it uses

scarlet lark
#

If you lower contrast, does that change anything for the better?

upbeat sapphire
#

here im messing with a bunch of parameters

scarlet lark
#

Looked like you got a few good results in there. The best thing I can tell you is that this shader appears to have been made for you to tweak it to suit how you will use it in the ways you just did. So, I guess fiddle with it till it looks good. That's what all those parameters are for. It'd be quite a bit more complicated for it to automatically avoid banding in large areas...Though, you might try searching for shaders that remove banding; there's probably a way to merge one into this one to help with that. Still, doing that is rather complicated. If you can get it tweaked good enough with the parameters, I suggest just going with it as-is.

upbeat sapphire
#

Yeah, it's just odd because I'm using the same params that are used in the demo, so i wonder why it wouldn't be working

#

Might be a bug with not having anything to display

#

Seems like if theres a texture that fills the screen you can't see the artifact

scarlet lark
#

It could be getting data from the default background color that isn't working well for what you're trying to do. If worst comes to worst, you can add another CanvasLayer, set it to a lower "layer" value, and fill it with a solid TextureRect as your background (or any other background you want). That might give it better pixel data to work with. I don't know much about how the sampler struct works, so I'm kind of just guessing here.

#

I am actually doing something like that in my current game for a different reason.

upbeat sapphire
#

Yeah had a similar idea - still figuring godot out, barely just starting the learn 2d gamedev course so I'm kinda blindy bumping my way into making stuff work haha, had a hard time messing around with the shader - but you've basically fixed my whole problem I was having so thanks a lot for that! Just making tests to check whats possible and not, at the very beginning of coming up a game idea haha

scarlet lark
#

I should really start blogging my development, but I'm kind of shy about it. If it makes you feel any better, I've been fussing around in the engine for years now and haven't released a game yet. Damn ADHD keeps making me want to start new projects all the time. lol

upbeat sapphire
#

that's the same in every creative sphere hahaha

#

I do graphic design / motion /ui/ux / editing / for a bunch of stuff and different projects, been meaning to start a bunch of different projects, clothing, youtube channels, etc.. but i keep delaying and wanting everything to be perfect before releasing anything it's the bane of a creative haha

scarlet lark
#

Yeah. I got kind of lucky. I'm working with a guy who's doing the music, and I kind of use him as a "This guy will be disappointed if I don't show some more progress soon." kind of muse. lol It's sort of working. haha

#

I took a pixelizer shader from that same site, and I refactored and fitted it to my current project. I might dig that up and share it if you're interested. It can be used in virtually the same way as what you have, but it gives a bit of a different result...Instead of dithering, it uses a process called posterization (more or less).

#

It's a bit hacky looking from my experimenting with it, iirc. Been a while since I looked at the thing.

upbeat sapphire
#

Nice, I'm trying to get a dithering low res look to it, kinda want a vermis aesthetic, drawn and then dithered to give an old school kinda vibe.

scarlet lark
#

Cool.

#

Actually, whoops. Looks like I'm no longer using this. I must have decided at some point not to. Well, I don't need it. It's basically a very slightly modified version of the pixelizer shader on godotshaders, and it has "dither" as a variable, but it is doing a very different thing here:

shader_type canvas_item;

uniform sampler2D screen_texture : hint_screen_texture, filter_nearest;

uniform float pixel_size : hint_range(1.0,50.0) = 4.0;
uniform int color_depth : hint_range(1,256) = 5;

uniform float colors : hint_range(1.0, 64.0);
uniform float dither : hint_range(0.0, 0.5);


void fragment()
{
    vec2 resolution = 1.0 / SCREEN_PIXEL_SIZE;
    vec2 pixCoord = FRAGCOORD.xy;
    vec4 input = texture(screen_texture, UV);
    vec4 img = vec4(floor(input.r*float(color_depth))/float(color_depth), floor(input.g*float(color_depth))/float(color_depth), floor(input.b*float(color_depth))/float(color_depth), input.a);
    
    float a = floor(mod(UV.x / TEXTURE_PIXEL_SIZE.x, 2.0));
    float b = floor(mod(UV.y / TEXTURE_PIXEL_SIZE.y, 2.0));
    float c = mod(a + b, 2.0);
    
    COLOR.r = (round(img.r * colors + dither) / colors) * c;
    COLOR.g = (round(img.g * colors + dither) / colors) * c;
    COLOR.b = (round(img.b * colors + dither) / colors) * c;
    c = 1.0 - c;
    COLOR.r += (round(img.r * colors - dither) / colors) * c;
    COLOR.g += (round(img.g * colors - dither) / colors) * c;
    COLOR.b += (round(img.b * colors - dither) / colors) * c;
}
upbeat sapphire
#

Interesting, thanks for sharing

scarlet lark
#

color_depth and colors change things in a very similar way to each other, but subtly different. You can play around with them a bit. One thing I can tell you is that this doesn't generate artefacts if there's not actually a texture (when sampling the default background). Though, if you add other shaders that rely on background texture similarly to your dither shader, this shader wont remove any artefacts they introduce...though it can make them look more integrated (done on purpose) sometimes.