Gradients
gradient (Mesh variant)
Synopsis
mesh = gradientMesh( direction, color1, color2, ... )
Creates a gradient object (actually Mesh) from a table of colors to be evenly spaced throughout the gradient. This is better version of gradient function below.
Arguments
string direction
- Gradient direction (horizontal or vertical).
table color1
- First color table.
table color2
- Second color table.
table ...
- Additional color table.
Returns
Mesh mesh
- The gradient object.
Source
-- Color multipler
local COLOR_MUL = love._version >= "11.0" and 1 or 255
function gradientMesh(dir, ...)
-- Check for direction
local isHorizontal = true
if dir == "vertical" then
isHorizontal = false
elseif dir ~= "horizontal" then
error("bad argument #1 to 'gradient' (invalid value)", 2)
end
-- Check for colors
local colorLen = select("#", ...)
if colorLen < 2 then
error("color list is less than two", 2)
end
-- Generate mesh
local meshData = {}
if isHorizontal then
for i = 1, colorLen do
local color = select(i, ...)
local x = (i - 1) / (colorLen - 1)
meshData[#meshData + 1] = {x, 1, x, 1, color[1], color[2], color[3], color[4] or (1 * COLOR_MUL)}
meshData[#meshData + 1] = {x, 0, x, 0, color[1], color[2], color[3], color[4] or (1 * COLOR_MUL)}
end
else
for i = 1, colorLen do
local color = select(i, ...)
local y = (i - 1) / (colorLen - 1)
meshData[#meshData + 1] = {1, y, 1, y, color[1], color[2], color[3], color[4] or (1 * COLOR_MUL)}
meshData[#meshData + 1] = {0, y, 0, y, color[1], color[2], color[3], color[4] or (1 * COLOR_MUL)}
end
end
-- Resulting Mesh has 1x1 image size
return love.graphics.newMesh(meshData, "strip", "static")
end
Notes
The resulting Mesh has dimensions of 1x1. Scaling factor in love.graphics.draw determines the size of the gradient. drawinrect function below is not needed (can't be used really) when using this variant.
gradient (Image variant)
Synopsis
gradient {color1, color2, color3, ..., direction = 'horizontal' or 'vertical'}
Creates a gradient object (really just an Image) from a table of colors to be evenly spaced throughout the gradient, in the direction specified by the "direction" key of the parameter table.
Source
function gradient(colors)
local direction = colors.direction or "horizontal"
if direction == "horizontal" then
direction = true
elseif direction == "vertical" then
direction = false
else
error("Invalid direction '" .. tostring(direction) .. "' for gradient. Horizontal or vertical expected.")
end
local result = love.image.newImageData(direction and 1 or #colors, direction and #colors or 1)
for i, color in ipairs(colors) do
local x, y
if direction then
x, y = 0, i - 1
else
x, y = i - 1, 0
end
result:setPixel(x, y, color[1], color[2], color[3], color[4] or 255)
end
result = love.graphics.newImage(result)
result:setFilter('linear', 'linear')
return result
end
drawinrect
Synopsis
drawinrect(img, x, y, w, h, r, ox, oy, kx, ky)
A convenience function to draw scaled images in a rectangle of absolute size (rather than with a size relative to the size of the image, which is what love.graphics.draw() does). Useful for gradients, because you will almost always want to draw them scaled, and you don't want their bounds to change if the number of colors does.
Source
function drawinrect(img, x, y, w, h, r, ox, oy, kx, ky)
return -- tail call for a little extra bit of efficiency
love.graphics.draw(img, x, y, r, w / img:getWidth(), h / img:getHeight(), ox, oy, kx, ky)
end
Examples
drawing horizontal rainbow that fills the entire screen using Mesh variant
-- assume you already have gradientMesh function
local rainbow
function love.load()
rainbow = gradientMesh("horizontal",
{255, 0, 0},
{255, 255, 0},
{0, 255, 0},
{0, 255, 255},
{0, 0, 255},
{255, 0, 0}
)
end
function love.draw()
love.graphics.draw(rainbow, 0, 0, 0, love.graphics.getDimensions())
end
draw a 100x100 horizontal rainbow (that is, red on top, purple on bottom) in the center of the screen
require "gradient"
local rainbow = gradient {
direction = 'horizontal',
{255, 0, 0},
{255, 255, 0},
{0, 255, 0},
{0, 255, 255},
{0, 0, 255},
{255, 0, 0}
}
function love.draw()
drawinrect(rainbow, love.graphics.getWidth() / 2 - 50, love.graphics.getHeight() / 2 - 50, 100, 100)
end
draw a vertical greyscale spectrum (that is, black on left, white on right) filling the whole screen
require "gradient"
local greyscale = gradient {
direction = 'vertical',
{0, 0, 0},
{255, 255, 255}
}
function love.draw()
drawinrect(greyscale, 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
end