Palette Swap Shader: How to stop it mixing colors from neighboring pixel?

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
xThomas
Prole
Posts: 16
Joined: Tue May 02, 2017 2:43 am

Palette Swap Shader: How to stop it mixing colors from neighboring pixel?

Post by xThomas »

Code: Select all

local shader = love.graphics.newShader("palette/shader.glsl")
local palette = love.graphics.newImage("palette/Palette.png")
local sprite = love.graphics.newImage("sprite.png")
sprite:setFilter("nearest", "nearest")

function love.load()
   row = 0.0
end


local w, h = love.graphics.getDimensions()
function love.draw()
   love.graphics.setColor(0,0,0,1)
   love.graphics.rectangle('fill',0,0,w,h)
   love.graphics.setColor(1,1,1,1)
   love.graphics.setShader(shader)
   shader:send("palette", palette)
   shader:send("row", row)
   love.graphics.draw(sprite, 20, 20, 0, 8, 8)
   love.graphics.setShader()
   love.graphics.setColor(1,1,1,1)
   love.graphics.print(" row :"..row, 0, 0)
end

function love.update(dt)
   if love.keyboard.isDown("=") then
      row = row + 0.005
   elseif love.keyboard.isDown("-") then
      row = row - 0.005
   end
end

-- function love.keypressed(key)
--   if key == '=' then
--     row = row + 0.01
--   elseif key == '-' then
--     row = row - 0.01
--   end
-- end

Code: Select all

uniform sampler2D palette;
extern float row;

vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
   vec2 u = Texel(texture, texture_coords).ra;
   vec4 pixel = Texel(palette, vec2(u.r, row));
   pixel.a = u.g;
   return pixel * color;
}
i couldn't include the palette and sprite here, so you'll have to download the attachment. but, based on my code, do you see any solutions right now to my problem? For example, I want to grab red from the 5th row of my texture, which is 4x16 pixels. i could divide 1/16 and then multiply by four, giving me .25, but that would give me purple by mixing red from the 5th row and blue from the 4th. To just get red I needed .28

The demo has a main.lua, and a folder called palette with glsl and sprite. Hold = or - to change the row of the texture. Note that there aren't any rows after a point and it's just blank.

note: love2d uses glsl 1.20, texelFetch was added in 1.30
Attachments
Pallete Swap Shader.zip
(6.88 KiB) Downloaded 166 times
JoshGrams
Prole
Posts: 33
Joined: Sat May 27, 2017 10:58 am

Re: Palette Swap Shader: How to stop it mixing colors from neighboring pixel?

Post by JoshGrams »

Does palette:setFilter("nearest", "nearest") do what you want?
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: Palette Swap Shader: How to stop it mixing colors from neighboring pixel?

Post by pgimeno »

To grab the top edge of the top pixel, you use y=0/16. To grab the edge at the frontier between the top pixel and the next, you use y=1/16 etc. At the edges, with bilinear filtering active, the colour is a mix between the two pixels.

To avoid the effects of bilinear filtering, you have two options: either sample from pixel centres (the pixel centre is obtained by adding 0.5 to the row index: 0.5/16 is the centre of the top pixel, 1.5/16 is the centre of the second, and so on) or do as JoshGrams said.

For example, to sample from the 5th row without disabling bilinear filtering, the correct position to sample is 4.5/16 = 0.28125.

Sampling from pixel centres is safer even with filtering disabled, because then you're not exposed to rounding errors in corner cases.

Edit: Hopefully this image will make it clearer:
PaletteHalfPixels.png
PaletteHalfPixels.png (48.24 KiB) Viewed 3900 times
xThomas
Prole
Posts: 16
Joined: Tue May 02, 2017 2:43 am

Re: Palette Swap Shader: How to stop it mixing colors from neighboring pixel?

Post by xThomas »

informative thank you
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot] and 198 guests