Skip to content

Instantly share code, notes, and snippets.

@Powersaurus
Created August 5, 2022 14:54
Show Gist options
  • Save Powersaurus/f14a7ac3d63cdf9c1c90f62f9f0b4e49 to your computer and use it in GitHub Desktop.
Save Powersaurus/f14a7ac3d63cdf9c1c90f62f9f0b4e49 to your computer and use it in GitHub Desktop.
PICO-8 Palette shader in Love2D
palette_swap_shader = [[
extern vec4 colours_lookup[16];
extern vec4 screen_colours[16];
extern int transparent_colour = 0;
vec4 transparent = vec4(0,0,0,0);
vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) {
vec4 texcolour = Texel(tex, texture_coords);
for (int i = 0; i < 16; i++) {
if (texcolour == colours_lookup[i]) {
if (i == transparent_colour) {
return transparent * color;
} else {
return screen_colours[i] * color;
}
}
}
return texcolour * color;
}
]]
BLACK = {0,0,0, 1.0}
DARK_BLUE = {29/255.0, 43/255.0, 83/255.0, 1.0}
DARK_PURPLE = {126/255.0, 37/255.0, 83/255.0, 1.0}
DARK_GREEN = {0/255.0, 135/255.0, 81/255.0, 1.0}
BROWN = {171/255.0, 82/255.0, 54/255.0, 1.0}
DARK_GRAY = {95/255.0, 87/255.0, 79/255.0, 1.0}
LIGHT_GRAY = {194/255.0, 195/255.0, 199/255.0, 1.0}
WHITE = {255/255.0, 241/255.0, 232/255.0, 1.0}
RED = {255/255.0, 0/255.0, 77/255.0, 1.0}
ORANGE = {255/255.0, 163/255.0, 0/255.0, 1.0}
YELLOW = {255/255.0, 236/255.0, 39/255.0, 1.0}
GREEN = {0/255.0, 228/255.0, 54/255.0, 1.0}
BLUE = {41/255.0, 173/255.0, 255/255.0, 1.0}
GRAY_BLUE = {131/255.0, 118/255.0, 156/255.0, 1.0}
PINK = {255/255.0, 119/255.0, 168/255.0, 1.0}
LIGHT_PEACH = {255/255.0, 204/255.0, 170/255.0, 1.0}
BROWN_BLACK = {41/255.0,24/255.0,20/255.0, 1.0}
DARKER_BLUE = {17/255.0, 29/255.0, 53/255.0, 1.0}
DARKER_PURPLE = {66/255.0, 33/255.0, 54/255.0, 1.0}
BLUE_GREEN = {18/255.0, 83/255.0, 89/255.0, 1.0}
DARK_BROWN = {116/255.0, 47/255.0, 41/255.0, 1.0}
DARKER_GRAY = {73/255.0, 51/255.0, 59/255.0, 1.0}
MEDIUM_GRAY = {162/255.0, 136/255.0, 121/255.0, 1.0}
LIGHT_YELLOW = {243/255.0, 239/255.0, 125/255.0, 1.0}
DARK_RED = {190/255.0, 18/255.0, 80/255.0, 1.0}
DARK_ORANGE = {255/255.0, 108/255.0, 36/255.0, 1.0}
LIME_GREEN = {168/255.0, 231/255.0, 46/255.0, 1.0}
MEDIUM_GREEN = {0/255.0, 181/255.0, 67/255.0, 1.0}
MEDIUM_BLUE = {6/255.0, 90/255.0, 181/255.0, 1.0}
MAUVE = {117/255.0, 70/255.0, 101/255.0, 1.0}
DARK_LIGHT_PEACH = {255/255.0, 110/255.0, 89/255.0, 1.0}
PEACH = {255/255.0, 157/255.0, 129/255.0, 1.0}
all_colours = {
BLACK, DARK_BLUE, DARK_PURPLE, DARK_GREEN,
BROWN, DARK_GRAY, LIGHT_GRAY, WHITE,
RED, ORANGE, YELLOW, GREEN,
BLUE, GRAY_BLUE, PINK, LIGHT_PEACH,
BROWN_BLACK, DARKER_BLUE, DARKER_PURPLE, BLUE_GREEN,
DARK_BROWN, DARKER_GRAY, MEDIUM_GRAY, LIGHT_YELLOW,
DARK_RED, DARK_ORANGE, LIME_GREEN, MEDIUM_GREEN,
MEDIUM_BLUE, MAUVE, DARK_LIGHT_PEACH, PEACH
}
draw_palette = {
BLACK, DARK_BLUE, DARK_PURPLE, DARK_GREEN,
BROWN, DARK_GRAY, LIGHT_GRAY, WHITE,
RED, ORANGE, YELLOW, GREEN,
BLUE, GRAY_BLUE, PINK, LIGHT_PEACH
}
current_palette = {
BLACK, DARK_BLUE, DARK_PURPLE, DARK_GREEN,
BROWN, DARK_GRAY, LIGHT_GRAY, WHITE,
RED, ORANGE, YELLOW, GREEN,
BLUE, GRAY_BLUE, PINK, LIGHT_PEACH
}
function pal(i,c,draw_palette_flag)
if draw_palette_flag == 1 then
changed_draw_palette = true
draw_palette[i+1] = all_colours[c+1]
else
changed_screen_palette = true
if not i then
for f=1,16 do
current_palette[f] = draw_palette[f]
end
else
current_palette[i+1] = draw_palette[c+1]
end
end
end
function palt(i,transparent)
shader:send("transparent_colour", i)
end
function love.load()
love.graphics.setDefaultFilter("nearest", "nearest", 1)
-- just a png with a GREEN background (see colours above)
spritesheet = love.graphics.newImage("ball-3.png")
shader = love.graphics.newShader(palette_swap_shader)
changed_screen_palette = true
update_palette_shader()
palt(11,true)
shader:send("colours_lookup",
draw_palette[1],
draw_palette[2],
draw_palette[3],
draw_palette[4],
draw_palette[5],
draw_palette[6],
draw_palette[7],
draw_palette[8],
draw_palette[9],
draw_palette[10],
draw_palette[11],
draw_palette[12],
draw_palette[13],
draw_palette[14],
draw_palette[15],
draw_palette[16]
)
balls = {}
pal(0,1)
pal(2,3)
pal(4,11)
pal(9,10)
pal(10,7)
spr(0,100,50)
palettes = {
{{0,1},{2,2},{4,4},{9,9}},
{{4,8},{2,2},{9,14},{10,15}},
{{0,1},{2,3},{4,11},{9,10},{10,7}},
{{2,1},{4,13},{9,12}}
}
for i = 1, 80 do
balls[i] = {
x = love.math.random(400),
y = love.math.random(300),
vx = love.math.random(4) - 2 + love.math.random(),
vy = -0.3 - love.math.random(2) + love.math.random(),
palette = palettes[math.floor(love.math.random(#palettes))]
}
end
end
function update_palette_shader()
if changed_screen_palette then
shader:send("screen_colours",
current_palette[1],
current_palette[2],
current_palette[3],
current_palette[4],
current_palette[5],
current_palette[6],
current_palette[7],
current_palette[8],
current_palette[9],
current_palette[10],
current_palette[11],
current_palette[12],
current_palette[13],
current_palette[14],
current_palette[15],
current_palette[16]
)
changed_screen_palette = false
end
end
function spr(s,x,y)
update_palette_shader()
love.graphics.setShader(shader)
love.graphics.draw(spritesheet, x, y)
end
function love.update()
for _,b in ipairs(balls) do
update_ball(b)
end
end
function love.draw()
changed_screen_palette = false
love.graphics.print("FPS: "..tostring(love.timer.getFPS( )), 2, 2)
love.graphics.scale(2,2)
for _,b in ipairs(balls) do
draw_ball(b)
end
end
function update_ball(b)
if b.x > 400 then
b.x = 400
b.vx = -b.vx
end
if b.x < 0 then
b.x = 0
b.vx = -b.vx
end
if b.y > 270 then
b.y = 270
b.vy = -b.vy
end
if b.y < 0 then
b.y = 0
b.vy = -b.vy
end
b.vy = b.vy + 0.3
b.x = b.x + b.vx
b.y = b.y + b.vy
end
function draw_ball(b)
for _,p in ipairs(b.palette) do
pal(p[1], p[2])
end
spr(0, b.x, b.y)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment