Difference between revisions of "love.math.gammaToLinear"

m (Notes)
(Updated for 11.0)
 
(5 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
{{newin|[[0.9.1]]|091|type=function}}
 
{{newin|[[0.9.1]]|091|type=function}}
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.
+
Converts a color from gamma-space (sRGB) to linear-space (RGB). This is useful when doing [[love.graphics.isGammaCorrect|gamma-correct rendering]] and you need to do math in linear RGB in the few cases where LÖVE doesn't handle conversions automatically.
  
Read more about gamma-correct rendering [http://http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html here], [http://filmicgames.com/archives/299 here], and [http://renderwonk.com/blog/index.php/archive/adventures-with-gamma-correct-rendering/ here].
+
Read more about gamma-correct rendering [https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch24.html here], [http://filmicgames.com/archives/299 here], and [http://renderwonk.com/blog/index.php/archive/adventures-with-gamma-correct-rendering/ here].
 +
 
 +
In versions prior to [[11.0]], color component values were within the range of 0 to 255 instead of 0 to 1.
  
 
{{notice|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.}}
 
{{notice|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.}}
Line 42: Line 44:
 
=== Returns ===
 
=== Returns ===
 
{{param|number|lc|The value of the color channel in linear RGB space.}}
 
{{param|number|lc|The value of the color channel in linear RGB space.}}
 
== Notes ==
 
Gamma-space sRGB has more precision in the lower end (darker colors) than linear 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 ==
 
== 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">
 
local function PremultiplyLinearPixel(x, y, r, g, b, a)
 
local function PremultiplyLinearPixel(x, y, r, g, b, a)
   r = r * a / 255
+
   r = r * a
   g = g * a / 255
+
   g = g * a
   b = b * a / 255
+
   b = b * a
 
   return r, g, b, a
 
   return r, g, b, a
 
end
 
end
Line 99: Line 57:
 
local function PremultiplyGammaPixel(x, y, r, g, b, a)
 
local function PremultiplyGammaPixel(x, y, r, g, b, a)
 
   r, g, b = love.math.gammaToLinear(r, g, b)
 
   r, g, b = love.math.gammaToLinear(r, g, b)
   r = r * a / 255
+
   r = r * a
   g = g * a / 255
+
   g = g * a
   b = b * a / 255
+
   b = b * a
 
   r, g, b = love.math.linearToGamma(r, g, b)
 
   r, g, b = love.math.linearToGamma(r, g, b)
 
   return r, g, b, a
 
   return r, g, b, a
 
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>
  

Latest revision as of 20:30, 1 April 2018

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 and you need to do math in linear RGB in the few cases where LÖVE doesn't handle conversions automatically.

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

In versions prior to 11.0, color component values were within the range of 0 to 255 instead of 0 to 1.

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.

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
   g = g * a
   b = b * a
   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
   g = g * a
   b = b * a
   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