Need help solving a shader issue

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
SHiLLySiT
Prole
Posts: 2
Joined: Tue Jan 24, 2023 7:02 pm

Need help solving a shader issue

Post by SHiLLySiT »

I'm working on a 1bit game (where it only uses two colors) which leverages a custom shader. I recently started working on adding support to the shader so that I can define a pixel pattern for draw calls. The pattern is specified by 8 hex values that defines the states of pixels in each row, and then this 8x8 pattern is tiled. However I've run into an issue with the shader that I can seem to figure out, I'm fairly certain its a floating point rounding error, but I'm not sure how to fix it.

This is what I want to achieve:
correct.png
correct.png (3.71 KiB) Viewed 127 times
This is what actually happens:
wrong.png
wrong.png (3.3 KiB) Viewed 127 times
I believe the problem lies here, in the shader code:

Code: Select all

vec4 effect(vec4 color, Image tex, vec2 tex_coords, vec2 screen_coords)
{
  // rounding error somewhere on the next three lines?
  float x = mod(screen_coords.x, 8);
  float y = mod(screen_coords.y, 8);
  if (pattern[int(floor(x + y))] == 1) {
    return WHITE;
  } else {
    return BLACK;
  }
}
I've tried several variations of the above to attempt to round the float, but its still always showing the same artifacting. I'm hoping this is an easy fix that I just can't see with my limited shader experience 😭

I'm working on a rather large project, so I've attached a minimal (but working!) project that reproduces the issue in isolation.
shader-example.zip
(822 Bytes) Downloaded 7 times
User avatar
Bigfoot71
Party member
Posts: 114
Joined: Fri Mar 11, 2022 11:07 am

Re: Need help solving a shader issue

Post by Bigfoot71 »

The problem is mostly how you're trying to iterate through the pixels in the array, you can round the (x,y) coordinates to the integer when you call `mod` and then you should iterate through the array instead like this [x+y*w], here is the corrected shader:

Code: Select all

#pragma language glsl3

extern int pattern[64];

const vec4 WHITE =        vec4(176.0f / 255.0f, 174.0f / 255.0f, 167.0f / 255.0f, 1);
const vec4 BLACK =        vec4( 49.0f / 255.0f,  47.0f / 255.0f,  40.0f / 255.0f, 1);

vec4 effect(vec4 color, Image tex, vec2 tex_coords, vec2 screen_coords)
{
    // Use mod() to get the position of the current pixel within the 8x8 pattern
    int x = int(mod(screen_coords.x, 8.0));
    int y = int(mod(screen_coords.y, 8.0));

    // Use "x" and "y" multiplied by "w" to index into the pattern array
    if (pattern[x + y * 8] == 1) {
        return WHITE;
    } else {
        return BLACK;
    }
}
Image

The reason `x+y*8` is used in the indexing calculation is because the pattern array is a one-dimensional array of 64 elements (8x8 pattern), by multiplying the y value by 8, it effectively moves the index to the correct row in the array. Adding x to this value gives you the final index of the element in the array that corresponds to the current pixel. Just remember, when we move in an array a dimension which represents like a pixel buffer we always do it like this "x + y * width".

I hope to be clear, if you have trouble understanding something don't hesitate ^^
My avatar code for the curious :D https://tinyurl.com/getMyAvatarCode
SHiLLySiT
Prole
Posts: 2
Joined: Tue Jan 24, 2023 7:02 pm

Re: Need help solving a shader issue

Post by SHiLLySiT »

Oh derp. This is why I shouldn't be programming so late 😂 Thanks for your help spotting this silly indexing bug.
Post Reply

Who is online

Users browsing this forum: Bigfoot71, pkhead and 79 guests