love.js icon indicating copy to clipboard operation
love.js copied to clipboard

Canvas PixelFormat uses rgba4 instead of rgba8

Open Yolwoocle opened this issue 1 year ago • 3 comments

Creating a canvas uses rgb4 by default instead of rgb8 as specified by the wiki. If you try to force it to create a Canvas using rgba8, it returns the following error:

The rgba8 canvas format is not supported by your graphics drivers.

Weirdly enough, srgba8, the gamma-correct version of rgba8, seems to be supported. Although this is not supported by all graphics cards so it's not a workaround that will work for everything.

This is mentioned by #55.

Workaround

This workaround seems to work for me for now. srgba8 seems to be supported by love.js on most devices. Even though I didn't see any noticeable changes, please note that srgba8 is supposed to change the colors rendered on screen.

EDIT: This will not work in LÖVE 12.

local old_newCanvas = love.graphics.newCanvas
function love.graphics.newCanvas(width, height, settings)
    settings = settings or {}

    if not settings.format then
        -- Fallback chain for supported Canvas formats
        local supportedCanvasFormats = love.graphics.getCanvasFormats()
        local fallbackChain = {
            -- It's possible to include other formats if necessary, as long as they have 4 components: 
            -- https://love2d.org/wiki/PixelFormat
            -- I don't know much about the specifics of these formats, please adapt to what works best for you.  
            -- Note that this does not take into account if `t.gammacorrect = true` is set in `love.conf`, please implement it yourself if needed.
            "rgba8",
            "srgba8",
            "rgb10a2",
            "rgb5a1",
            "rgba4",
            "normal"
        }
        local format = fallbackChain[1]
        local i = 1
        while i <= #fallbackChain and not supportedCanvasFormats[format] do
            i = i + 1
            format = fallbackChain[i]
        end
        if i == #fallbackChain + 1 then
            error("No valid canvas format is supported by the system")
        end

        settings.format = format
    end

    return old_newCanvas(width, height, settings)
end

Examples

  • This page creates a Canvas with a normal format, then reads and displays its format : https://yolwoocle.com/love2dtest/test1/index.html

image

Source code:

function love.conf(t)
    t.window.width = 1200
    t.window.height = 800
end

local image = love.graphics.newImage("parrot.jpg")
local canvas = love.graphics.newCanvas(600, 600, {
    format = "normal",
})
local a = 0.0
function love.update(dt)
    a = a + dt
end

function love.draw()
    love.graphics.setCanvas(canvas)
    love.graphics.clear(0, 0, 0, 1)
    love.graphics.draw(image, math.cos(a) * 30, math.sin(a) * 30)
    love.graphics.setCanvas()

    love.graphics.clear(0, 0, 0, 1)
    love.graphics.draw(canvas, 0, 0)
    
    love.graphics.print(tostring(canvas:getFormat()), 40, 40)
end
  • This page creates a Canvas with a normal format, and a second Canvas using rbga8, which causes the error mentioned above: https://yolwoocle.com/love2dtest/test2/index.html

Source code:

function love.conf(t)
    t.window.width = 1200
    t.window.height = 800
end

local image = love.graphics.newImage("parrot.jpg")
local canvas = love.graphics.newCanvas(600, 600, {
    format = "normal",
})
local canvas2 = love.graphics.newCanvas(600, 600, {
    format = "srgba8",
})
local a = 0.0
function love.update(dt)
    a = a + dt
end

function love.draw()
    love.graphics.setCanvas(canvas)
    love.graphics.clear(0, 0, 0, 1)
    love.graphics.draw(image, math.cos(a) * 30, math.sin(a) * 30)
    love.graphics.setCanvas()

    love.graphics.setCanvas(canvas2)
    love.graphics.clear(0, 0, 0, 1)
    love.graphics.draw(image, math.cos(a) * 30, math.sin(a) * 30)
    love.graphics.setCanvas()
    
    love.graphics.clear(0, 0, 0, 1)
    love.graphics.draw(canvas, 0, 0)
    love.graphics.draw(canvas2, 600, 0)
    
    love.graphics.print(tostring(canvas:getFormat()), 40, 40)
    love.graphics.print(tostring(canvas2:getFormat()), 640, 40)
end

It's possible to see what formats are supported using this snippet of code in love.draw:

local y = 0
local canvasformats = love.graphics.getCanvasFormats()
for formatname, formatsupported in pairs(canvasformats) do
    local str = string.format("Supports format '%s': %s", formatname, tostring(formatsupported))
    love.graphics.print(str, 10, y)
    y = y + 20
end

The image I'm using: parrot

Yolwoocle avatar May 12 '24 09:05 Yolwoocle

So that's why my canvas was looking weird... I was drawing a background to a very small canvas

ChicknTurtle avatar May 15 '24 01:05 ChicknTurtle

Here it says no support for rgba8 for canvases, but there is for images https://davidobot.net/lovejs/features_c/

ChicknTurtle avatar May 17 '24 21:05 ChicknTurtle

It seems the default canvas is set to rgba4 too. Colors aren't showing up the same in the love.js port, they're slightly muted.

SamR71 avatar Dec 11 '24 06:12 SamR71