• Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

Dither-Lighting Shader/Surface Issue

W

WAVINDY

Guest
Hey there all, I'm looking to figure out this thing that happens when I apply a dithering system with surfaces involved.

I made it work perfectly using a video found here: GM Wolf's Dithering Method

The end result is almost there, but for example, when I shoot a bullet, the bullet's drawing of a light around it makes horizontal lines when it's light intersects another like this:
2020-09-17 23_10_21-GameMaker_ Studio.png

Here's the Shader:

GML:
//
// Simple passthrough vertex shader
//
attribute vec3 in_Position;                  // (x,y,z)
//attribute vec3 in_Normal;                  // (x,y,z)     unused in this shader.
attribute vec4 in_Colour;                    // (r,g,b,a)
attribute vec2 in_TextureCoord;              // (u,v)

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
 
    v_vColour = in_Colour;
    v_vTexcoord = in_TextureCoord;
}
GML:
//
// Simple passthrough fragment shader
//
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec2 texSize;
uniform sampler2D ditherTex;

float height = 4.;
vec2 size = vec2(16,16);
vec2 tSize = vec2(32,64);

vec2 rSize = size / tSize;


void main()
{
    float band = floor(texture2D( gm_BaseTexture, v_vTexcoord ).r * 8.);
    vec2 offset = vec2(rSize.x * floor(band / height), rSize.y * mod(band, height));
    vec2 texcoord = vec2( (mod((v_vTexcoord.x * texSize.x) , size.x) / (tSize.x)),
                          (mod((v_vTexcoord.y * texSize.y) , size.y) / (tSize.y)));
    gl_FragColor = texture2D(ditherTex, texcoord + offset);
}
The drawing of shader onto objects through draw event of obj_lighting:
GML:
draw_set_blend_mode(bm_add);

surface_set_target(surface);

draw_clear_alpha(c_black,1);
 
    with (obj_Light)
        draw_self();
     
    with (obj_Character)
        draw_sprite_ext(spr_Light2,random(3),x,y,3,3,0,c_white,1);
     
    with (obj_bullet)
        draw_sprite_ext(spr_Light2,0,x,y,1,1,0,c_white,1);


surface_reset_target();

draw_set_blend_mode(bm_normal);

texture_set_interpolation(0);

shader_set(shd_dither);
shader_set_uniform_f(u_size, room_width, room_height);
texture_set_stage(u_dither_tex, dither_tex);
draw_surface(surface,0,0);
shader_reset();
 
Last edited by a moderator:

Fanatrick

Member
What's the size of your surface? I believe you're supposed to edit the uniform to match the dimensions of the primitive (quad) you're rendering:
shader_set_uniform_f(u_size, room_width, room_height);

Edit:
Seeing how you have banding issues all over the place I'm almost certain this is your issue. Not sure if you're using views but I believe u_size should match either its dimensions or dimensions of the surface. Let me know if this works:
shader_set_uniform_f(u_size, surface_get_width(surface), surface_get_height(surface));
 
W

WAVINDY

Guest
What's the size of your surface? I believe you're supposed to edit the uniform to match the dimensions of the primitive (quad) you're rendering:
shader_set_uniform_f(u_size, room_width, room_height);

Edit:
Seeing how you have banding issues all over the place I'm almost certain this is your issue. Not sure if you're using views but I believe u_size should match either its dimensions or dimensions of the surface. Let me know if this works:
shader_set_uniform_f(u_size, surface_get_width(surface), surface_get_height(surface));
I wish this was the problem, but in my creation code for the lighting I already have

GML:
surface = surface_create(room_width,room_height);
dither_tex = background_get_texture(bg_Dithering);

u_size = shader_get_uniform(shd_dither,"texSize");
u_dither_tex = shader_get_sampler_index(shd_dither,"ditherTex");
So it's already set the surface dimensions to room widith and height, unless the room width and height is the problem itself??

Thank you šŸ˜‡
 

rytan451

Member
A question regarding maintainability: why are you setting size to room_width, room_height? Likewise with your surface. Shouldn't you be limiting your surface and shader to only the size of the application surface?
 
W

WAVINDY

Guest
A question regarding maintainability: why are you setting size to room_width, room_height? Likewise with your surface. Shouldn't you be limiting your surface and shader to only the size of the application surface?
I could, I could set it to view_wview[0] and view_hview[0], and it's the same.
 

Gradius

Member
Trying to render without the shader to see if there's any weirdness happening to the input surface would be a good start. Looks like there is some issue of scaling though, only one of the outer layers of dither there's a lot of one-pixel lines where the dithering isn't lining up with the scale of the rest of the underlying art, which I'm assuming you want. You should absolutely be using view_width and view_height (or whatever the current versions are in the version of GM you're using) though. You're switching to a worse practice more likely to break down the line the moment you want the level to be larger than a single screen worth of content.
 
W

WAVINDY

Guest
I set the width and height to the view_wview[0] and view_hview[0], and was sure to set the surface to create at view_xview[0] and view_yview[0]. It seems to just turn the whole screen black with no lights cutting out of the surface now. Any suggestions?
 
W

WAVINDY

Guest
Trying to render without the shader to see if there's any weirdness happening to the input surface would be a good start. Looks like there is some issue of scaling though, only one of the outer layers of dither there's a lot of one-pixel lines where the dithering isn't lining up with the scale of the rest of the underlying art, which I'm assuming you want. You should absolutely be using view_width and view_height (or whatever the current versions are in the version of GM you're using) though. You're switching to a worse practice more likely to break down the line the moment you want the level to be larger than a single screen worth of content.
my rooms are already upwards of 2400 in width/height, the screen is only about 320 x 240. The previous method was working for following my character and all that, it was just this weird overlap.
 
Top