Difference between revisions of "Gradients"
m |
Moltony112 (talk | contribs) (More fix) |
||
(3 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | ==gradient== | + | ==gradient (Mesh variant)== |
+ | ===Synopsis=== | ||
+ | <source lang="lua">mesh = gradientMesh( direction, color1, color2, ... )</source> | ||
+ | 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=== | ||
+ | {{param|string|direction|Gradient direction ('''horizontal''' or '''vertical''').}} | ||
+ | {{param|table|color1|First color table.}} | ||
+ | {{param|table|color2|Second color table.}} | ||
+ | {{param|table|...|Additional color table.}} | ||
+ | ===Returns=== | ||
+ | {{param|Mesh|mesh|The gradient object.}} | ||
+ | ===Source=== | ||
+ | <source lang="lua"> | ||
+ | -- 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 | ||
+ | </source> | ||
+ | ===Notes=== | ||
+ | The resulting [[Mesh]] has dimensions of 1x1. Scaling factor in [[love.graphics.draw]] determines the size of the gradient. [[#drawinrect|drawinrect]] function below is not needed (can't be used really) when using this variant. | ||
+ | ==gradient (Image variant)== | ||
===Synopsis=== | ===Synopsis=== | ||
<source lang="lua">gradient {color1, color2, color3, ..., direction = 'horizontal' or 'vertical'}</source> | <source lang="lua">gradient {color1, color2, color3, ..., direction = 'horizontal' or 'vertical'}</source> | ||
− | Creates a gradient object (really just an | + | 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=== | ===Source=== | ||
<source lang="lua"> | <source lang="lua"> | ||
Line 41: | Line 98: | ||
</source> | </source> | ||
==Examples== | ==Examples== | ||
+ | ===drawing horizontal rainbow that fills the entire screen using Mesh variant=== | ||
+ | <source lang="lua"> | ||
+ | -- 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 | ||
+ | </source> | ||
===draw a 100x100 horizontal rainbow (that is, red on top, purple on bottom) in the center of the screen=== | ===draw a 100x100 horizontal rainbow (that is, red on top, purple on bottom) in the center of the screen=== | ||
<source lang="lua"> | <source lang="lua"> | ||
Line 46: | Line 123: | ||
local rainbow = gradient { | local rainbow = gradient { | ||
− | direction = 'horizontal' | + | direction = 'horizontal', |
− | {255, 0, 0} | + | {255, 0, 0}, |
− | {255, 255, 0} | + | {255, 255, 0}, |
− | {0, 255, 0} | + | {0, 255, 0}, |
− | {0, 255, 255} | + | {0, 255, 255}, |
− | {0, 0, 255} | + | {0, 0, 255}, |
− | {255, 0, 0} | + | {255, 0, 0} |
} | } | ||
function love.draw() | function love.draw() | ||
− | drawinrect(rainbow, love.graphics.getWidth() / 2 - 50, love.graphics.getHeight() / 2 - 50, 100) | + | drawinrect(rainbow, love.graphics.getWidth() / 2 - 50, love.graphics.getHeight() / 2 - 50, 100, 100) |
end | end | ||
</source> | </source> | ||
Line 64: | Line 141: | ||
local greyscale = gradient { | local greyscale = gradient { | ||
− | direction = 'vertical' | + | direction = 'vertical', |
− | {0, 0, 0} | + | {0, 0, 0}, |
− | {255, 255, 255} | + | {255, 255, 255} |
} | } | ||
Latest revision as of 15:47, 24 April 2024
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