• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Shaders GLSL 1Bit Dithering Shader work perfectly in all the shader editors but not compile properly in gms

Heavybrush

Member
Hi guys
I'm getting into the shaders, I love them but I'm not so good to understand what is going on

C:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec2 resolution;
uniform float pixelSize;
uniform float gamma;

void main()
{
    vec2 uv = gl_FragCoord.xy / resolution.xy;
    float alpha = 1.0;
    vec4 color = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    gl_FragColor = color;

    float pixelSize = 3.0;
    float gamma = 3.0;

    vec2 pseudoResolution = floor(resolution.xy / pixelSize);
    vec2 pseudoPixel = floor(gl_FragCoord.xy / pixelSize);
    vec2 pseudoUv = pseudoPixel / pseudoResolution;

    vec3 tex = texture2D(gm_BaseTexture, pseudoUv).rgb;
    float bw = (tex.r + tex.g + tex.b) / gamma;
    float col = 0.0;

    if(bw > 0.8) {
        col = 1.0;
    } else if(bw > 0.6) {
        col = float(!(int(pseudoPixel.x) % 2 == 0 && int(pseudoPixel.y) % 2 != 0));
    } else if(bw > 0.4) {
        col = float((int(pseudoPixel.x) % 2 + int(pseudoPixel.y) % 2) % 2 == 0);
    } else if(bw > 0.2) {
        col = float(int(pseudoPixel.x) % 2 == 0 && int(pseudoPixel.y) % 2 == 0);
    }

    gl_FragColor = color * vec4(col, col, col, alpha);
}
the compile errors says:

Fragment Shader: shd_1BitDithering at line 31 : ''

this shader works perfecty in shadertoy and shader editor tool (a very good software on steam to try shaders)
I'm going to try it also on my phone (there is another shader tool, that is an app where I learned a lot on shaders)

seems to be here there is not a compile error
because the shader works in other places but here it doesn't want that if
it says error on lne 31 but the problem is on the whole if

if I delete it the shader works (but obviously is all black)

what can I do to solve this problem?
thank you so much
 
Last edited:

Heavybrush

Member
thank you
already tried, it doesn't work
here I made some changes
C:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec2 resolution;
uniform int pixelSize;
uniform float gamma;

void main()
{
    vec2 uv = gl_FragCoord.xy / resolution.xy;
    float alpha = 1.0;
    vec4 color = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    gl_FragColor = color;

    int pixelSize = 3;
    float gamma = 3.0;

    vec2 pseudoResolution = floor(resolution.xy / float(pixelSize));
    vec2 pseudoPixel = floor(gl_FragCoord.xy / float(pixelSize));
    vec2 pseudoUv = pseudoPixel / pseudoResolution;

    vec3 tex = texture2D(gm_BaseTexture, pseudoUv).rgb;
    float bw = (tex.r + tex.g + tex.b) / gamma;
    float col = 0.0;

    if(bw > 0.8) {
        col = 1.0;
    } else if(bw > 0.6) {
        col = float(!(int(pseudoPixel.x) mod 2 == 0 && int(pseudoPixel.y) mod 2 != 0));
    } else if(bw > 0.4) {
        col = float((int(pseudoPixel.x) mod 2 + int(pseudoPixel.y) % 2) mod 2 == 0);
    } else if(bw > 0.2) {
        col = float(int(pseudoPixel.x) mod 2 == 0 && int(pseudoPixel.y) mod 2 == 0);
    }

    gl_FragColor = color * vec4(col, col, col, alpha);
}
i changed float pixelSize in int so i cast floor(resolution.xy / float(pixelSize)); and floor(gl_FragCoord.xy / float(pixelSize));
and changed vec3 tex = texture2D(gm_BaseTexture, pseudoUv).xyz; in .rgb because for convention we are using colors and not coordinates

the shader is taken from shadertoy
this is the original
 

chamaeleon

Member
mod is a function taking two parameters, not an operator between arguments.

Edit to add: I am not at all well versed in shaders. Hopefully someone else with more hands-on experience will pinpoint the issue better than I. I'm not having much luck making acceptable changes.
 
Last edited:

KoDeeo

Member
I am trying this corrected version:
C:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec2 resolution;
uniform float pixelSize;
uniform float gamma;

void main()
{
    vec2 uv = gl_FragCoord.xy / resolution.xy;
    float alpha = 1.0;
    vec4 color = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    gl_FragColor = color;
 
    float pixelSize = 3.0;
    float gamma = 3.0;
 
    vec2 pseudoResolution = floor(resolution.xy / pixelSize);
    vec2 pseudoPixel = floor(gl_FragCoord.xy / pixelSize);
    vec2 pseudoUv = pseudoPixel / pseudoResolution;
 
    vec3 tex = texture2D(gm_BaseTexture, pseudoUv).rgb;
    float bw = (tex.r + tex.g + tex.b) / gamma;
    float col = 0.0;
 
    if(bw > 0.8) {
        col = 1.0;
    } else if(bw > 0.6) {
        col = float(!( mod(pseudoPixel.x, 2.0) == 0 && mod(pseudoPixel.y, 2.0) != 0));
    } else if(bw > 0.4) {
        col = float(mod(pseudoPixel.x, 2.0) + mod(mod(pseudoPixel.y, 2.0), 2.0) == 0);
    } else if(bw > 0.2) {
        col = float(mod(pseudoPixel.x, 2.0) == 0 && mod(pseudoPixel.y, 2.0) == 0);
    }
 
    gl_FragColor = color * vec4(col, col, col, alpha);
}
But now it's throwing
1626019741397.png
 

KoDeeo

Member
I also tried to change all the 2s to 2.0s to be coherent with the doc asking for a float as second argument for `mod`, but with no result.
Now it seems to be complaining about == operator?
Is this a real error or the message is just giving out wrong information?
For what I know, == should be known by the engine
 

KoDeeo

Member
Hello again and excuse me for the multiple posts.

I managed to make this shader work, you had some syntax errors in your code.
1st of all mod() accepts floats as second parameter.
I converted everything into a float. You also had some confusion with parentheses on line 29 (it's pretty messy), I fixed that and now the shader is working properly.

Here is the functioning code for
C:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec2 resolution;
uniform float pixelSize;
uniform float gamma;

void main()
{
    vec2 uv = gl_FragCoord.xy / resolution.xy;
    float alpha = 1.0;
    vec4 color = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    gl_FragColor = color;
    float pixelSize = 3.0;
    float gamma = 3.0;
    vec2 pseudoResolution = floor(resolution.xy / pixelSize);
    vec2 pseudoPixel = floor(gl_FragCoord.xy / pixelSize);
    vec2 pseudoUv = pseudoPixel / pseudoResolution;
    vec3 tex = texture2D(gm_BaseTexture, pseudoUv).rgb;
    float bw = (tex.r + tex.g + tex.b) / gamma;
    float col = 0.0;
    if(bw > 0.8) {
        col = 1.0;
    }
    else if(bw > 0.6) {
        col = float(!( mod(pseudoPixel.x, 2.0) == 0.0) && (mod(pseudoPixel.y, 2.0) != 0.0) );
    }
    else if(bw > 0.4)
    {
        col = float(mod((mod(pseudoPixel.x, 2.0) + mod(pseudoPixel.y, 2.0)), 2.0) == 0.0);
        
    } else if(bw > 0.2) {
        col = float((mod(pseudoPixel.x, 2.0) == 0.0) && (mod(pseudoPixel.y, 2.0) == 0.0));
    }
    gl_FragColor = color * vec4(col, col, col, alpha);
}
 

Vusur

Member
Did it work @Heavybrush ? I'm curious because

1. float(!(int(pseudoPixel.x) mod 2 == 0 && int(pseudoPixel.y) mod 2 != 0));
and
2. float(!( mod(pseudoPixel.x, 2.0) == 0.0) && (mod(pseudoPixel.y, 2.0) != 0.0) );

Looks almost the same, but is different (I don't mean the syntax, I mean the logic). (1) is an old trick to force a number into an integer by casting it into int. It removes possible floating-point errors when doing "is equal to" conditions. We could argue, if this cast is useful in the first place. int(1.999999982) == 1 when I remember it correctly and the cast is a floor function. Maybe it's round, then this works. mod( int(1.999999982), 2.0) == 0; if int casts with round(). or mod(int(2.000000021), 2.0) == 0; if int casts with floor() or round()
But now, you do mod(1.999999982, 2.0) which is obviously not 0.0. Same with mod(2.0000000021, 2.0) != 0 which the first version would definitve catch.

In the end, it also depends what the x is. Can it even have a floating-point error? It's a pixel, right? But at the same time, it's seen as float and the error could accure from a previous calculation. Also, if x can't have a floating-point error, can mod produce one (I think not. mod in GLSL ES is x - y * floor(x/y), which only carries the floating-point error over)?
If it works, then all is good. Just keep this in mind in case, you do something with x.
 
Last edited:
Top