Page 1 of 1

Palette swap

Posted: Tue Nov 11, 2014 6:17 pm
by Daniel_Cortez
Hello.

I'm making a platformer game and planning to use shared sprites for different enemies just by applying different palettes to them.
So... does anyone know how to perform a palette swap in LÖVE ?

Re: Palette swap

Posted: Tue Nov 11, 2014 7:16 pm
by Davidobot
If you're talking about changing the color of the enemy, use this code before drawing a sprite:

Code: Select all

love.graphics.setColor(r, g, b, a)
Where r, g, b, a and the red, greed, blue and alpha values that you want to apply to the sprite.

Re: Palette swap

Posted: Tue Nov 11, 2014 7:31 pm
by zorg
Unfortunately i have had very little experience with shaders as of yet, but i think that they could be of use to you in this regard.
consider your enemy sprites having a set number of unique colors (rgb triplets), let's say 16. Then, you make a fragment shader (working on pixels) that gets an external parameter, a palette (selected out of many), mapping those 16 colors to 16 others. Calling this shader when you're drawing the enemy sprite will probably color it to what you want. If you have a variable for each monster, defining the index of which palette it should use, then sending those to the shader and drawing them like that, you can achieve what you want.

Re: Palette swap

Posted: Tue Nov 11, 2014 8:18 pm
by s-ol
zorg wrote:Unfortunately i have had very little experience with shaders as of yet, but i think that they could be of use to you in this regard.
consider your enemy sprites having a set number of unique colors (rgb triplets), let's say 16. Then, you make a fragment shader (working on pixels) that gets an external parameter, a palette (selected out of many), mapping those 16 colors to 16 others. Calling this shader when you're drawing the enemy sprite will probably color it to what you want. If you have a variable for each monster, defining the index of which palette it should use, then sending those to the shader and drawing them like that, you can achieve what you want.
Here's a shader:

Code: Select all

    #ifdef VERTEX
    vec4 position( mat4 transform_projection, vec4 vertex_position )
    {
        return transform_projection * vertex_position; // default vertex shader
    }
    #endif
    #ifdef PIXEL
    extern vec4 palette_colors[2]; // size of color palette (2 colors)
    
    vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ) {
        return palette_colors[int(floor(VaryingTexCoord.x))]; // abuse u (texture x) coordinate as color index
    }
    #endif
  ]]
and the corresponding full code:

Code: Select all

function love.load()
  shader = love.graphics.newShader(
  [[
    #ifdef VERTEX
    vec4 position( mat4 transform_projection, vec4 vertex_position )
    {
        return transform_projection * vertex_position; // default vertex shader
    }
    #endif
    #ifdef PIXEL
    extern vec4 palette_colors[2]; // size of color palette (2 colors)
    
    vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ) {
        return palette_colors[int(floor(VaryingTexCoord.x))]; // abuse u (texture x) coordinate as color index
    }
    #endif
  ]] )
  
  mesh = love.graphics.newMesh( {
    { -1, -1, 0 }, { 1, -1, 0 }, { 0, 1.4, 0 }, -- triangle #1 uses first color (0)
    { 3, 0, 1 }, { 5, -3, 1 }, { 2, 2, 1 }      -- triangle #2 uses second color (1)
  }, nil, "triangles" )
end

function love.draw()
  love.graphics.setShader( shader )
  love.graphics.translate( 150, 300 )
  love.graphics.push()
    love.graphics.scale( 50 )
    shader:send( "palette_colors", { 255, 0, 0, 255 }, { 0, 255, 0, 255 } ) -- red and green
    love.graphics.draw( mesh )
  love.graphics.pop()
  love.graphics.translate( 250, 0 )
  love.graphics.scale( 50 )
  shader:send( "palette_colors", { 255, 255, 255, 255 }, { 0, 0, 255, 255 } ) -- white and blue
  love.graphics.draw( mesh )
end
or see the attached .love. Have fun :D

Re: Palette swap

Posted: Fri Nov 14, 2014 2:49 pm
by CaptainMaelstrom
Hey S0III0s, that's pretty dope. Thanks for uploading.

I tried to figure out how to make a general purpose pallete swap shader earlier, but settled for color specific. Until now. :3