Difference between revisions of "love.math.gammaToLinear"

m (Notes)
(Examples)
Line 47: Line 47:
  
 
== Examples ==
 
== Examples ==
=== Gamma-correct rendering using colored circles ===
 
<source lang="lua">
 
function love.load()
 
    -- Enable the sRGB mode for the window. This converts from linear RGB to gamma-space sRGB when
 
    -- things are drawn to the screen (but blending calculations are done in linear RGB space.)
 
    -- Computer monitors display in the sRGB color space.
 
    love.window.setMode(800, 600, {srgb=true, fsaa=4})
 
 
    -- If sRGB mode for the screen isn't supported, the flag will be false.
 
    local _, _, flags = love.window.getMode()
 
    gammacorrect = flags.srgb
 
 
    -- Here we have a red-ish color with 50% opacity. I chose the color values here based on what it looked like
 
    -- on-screen, and because computer monitors display in the sRGB color space, this color is in the sRGB color space.
 
    color1 = {187, 54, 100, 128}
 
 
    if gammacorrect then
 
        -- If the window is in srgb mode, it converts from linear RGB to sRGB when drawing. This means we need to
 
        -- convert the sRGB-space color to linear RGB space.
 
        color1 = {love.math.gammaToLinear(color1)}
 
    end
 
 
    -- We want this color to be halfway between white and black (with 50% opacity as well).
 
    -- If the window is in srgb mode, it expects linear-space colors and does blending that way, so this will work
 
    -- out fine. If the window isn't in srgb mode, the color won't be halfway between white and black because
 
    -- the values drawn to the screen aren't treated as linear-space RGB and converted to sRGB.
 
    -- We could use love.math.linearToGamma in that case, but blending would still be wrong.
 
    color2 = {128, 128, 128, 128}
 
end
 
 
-- Draw two overlapping circles with additive blending, using the colors above.
 
function love.draw()
 
    love.graphics.setBlendMode("additive")
 
   
 
    love.graphics.setColor(color1)
 
    love.graphics.circle("fill", 300, 300, 200)
 
 
    love.graphics.setColor(color2)
 
    love.graphics.circle("fill", 500, 300, 200)
 
end
 
</source>
 
 
=== Pre-multiply an image's alpha with its RGB values in linear RGB space ===
 
=== Pre-multiply an image's alpha with its RGB values in linear RGB space ===
 
<source lang="lua">
 
<source lang="lua">
Line 106: Line 65:
 
end
 
end
  
-- Loads an image and pre-multiplies its RGB values with its alpha, for use with the 'premultiplied' alpha blend mode.
+
-- Loads an image and pre-multiplies its RGB values with its alpha, for use with the ('alpha', 'premultiplied') blend mode.
 
-- The multiplication correctly accounts for the color-space of the image.
 
-- The multiplication correctly accounts for the color-space of the image.
function NewPremultipliedImage(filepath, format)
+
function NewPremultipliedImage(filepath, flags)
 
     local imagedata = love.image.newImageData(filepath)
 
     local imagedata = love.image.newImageData(filepath)
  
     local mapfunction = format == "srgb" and PremultiplyGammaPixel or PremultiplyLinearPixel
+
     local mapfunction = (flags and flags.linear) and PremultiplyLinearPixel or PremultiplyGammaPixel
 
     imagedata:mapPixel(mapfunction)
 
     imagedata:mapPixel(mapfunction)
  
     return love.graphics.newImage(imagedata, format)
+
     return love.graphics.newImage(imagedata, flags)
 
end
 
end
  
-- This assumes gamma-correct rendering (with the sRGB window flag) is being done.
+
image = NewPremultipliedImage("pig.png")
image = NewPremultipliedImage("pig.png", "srgb")
 
 
</source>
 
</source>
  

Revision as of 03:09, 24 December 2015

Available since LÖVE 0.9.1
This function is not supported in earlier versions.

Converts a color from gamma-space (sRGB) to linear-space (RGB). This is useful when doing gamma-correct rendering using colors created based on what they look like on-screen.

Read more about gamma-correct rendering here, here, and here.

O.png Gamma-correct rendering is an advanced topic and it's easy to get color-spaces mixed up. If you're not sure whether you need this, you might want to avoid it.  


Function

Synopsis

lr, lg, lb = love.math.gammaToLinear( r, g, b )

Arguments

number r
The red channel of the sRGB color to convert.
number g
The green channel of the sRGB color to convert.
number b
The blue channel of the sRGB color to convert.

Returns

number lr
The red channel of the converted color in linear RGB space.
number lg
The green channel of the converted color in linear RGB space.
number lb
The blue channel of the converted color in linear RGB space.

Notes

An alpha value can be passed into the function as a fourth argument, but it will be returned unchanged because alpha is always linear.

Function

Synopsis

lr, lg, lb = love.math.gammaToLinear( color )

Arguments

table color
An array with the red, green, and blue channels of the sRGB color to convert.

Returns

number lr
The red channel of the converted color in linear RGB space.
number lg
The green channel of the converted color in linear RGB space.
number lb
The blue channel of the converted color in linear RGB space.

Function

Synopsis

lc = love.math.gammaToLinear( c )

Arguments

number c
The value of a color channel in sRGB space to convert.

Returns

number lc
The value of the color channel in linear RGB space.

Notes

Dark colors have more precision in gamma-space sRGB than in linear-space RGB. Using this function to convert from sRGB to RGB can result in non-integer color values, which get truncated to integers and lose precision when used with other functions such as love.graphics.setColor.

Examples

Pre-multiply an image's alpha with its RGB values in linear RGB space

local function PremultiplyLinearPixel(x, y, r, g, b, a)
   r = r * a / 255
   g = g * a / 255
   b = b * a / 255
   return r, g, b, a
end

local function PremultiplyGammaPixel(x, y, r, g, b, a)
   r, g, b = love.math.gammaToLinear(r, g, b)
   r = r * a / 255
   g = g * a / 255
   b = b * a / 255
   r, g, b = love.math.linearToGamma(r, g, b)
   return r, g, b, a
end

-- Loads an image and pre-multiplies its RGB values with its alpha, for use with the ('alpha', 'premultiplied') blend mode.
-- The multiplication correctly accounts for the color-space of the image.
function NewPremultipliedImage(filepath, flags)
    local imagedata = love.image.newImageData(filepath)

    local mapfunction = (flags and flags.linear) and PremultiplyLinearPixel or PremultiplyGammaPixel
    imagedata:mapPixel(mapfunction)

    return love.graphics.newImage(imagedata, flags)
end

image = NewPremultipliedImage("pig.png")

See Also

Other Languages