Page 1 of 1

Drawing text filled with a texture instead of a solid color

Posted: Fri May 22, 2020 7:27 pm
by hoistbypetard
I'm pretty new to LÖVE and to lua, so please point out if I'm missing something even if it seems really obvious.

For a title screen, I want to draw some text on the screen, such that the fill pattern on the letters is an image rather than a solid color. Think of something like this:
textfill.love
(117 KiB) Downloaded 114 times
My first thought was to use stencils for it, but that didn't work out well. After trying a few different things, I settled on drawing the background to one canvas, drawing the text to another, and using mapPixel.

Code: Select all

function MaskImageWithText(image, font, text, x, y)
    local texture_x = x or 0
    local texture_y = x or 0
    local text_drawable = love.graphics.newText(font, text)
    local text_width = text_drawable:getWidth()
    local text_height = text_drawable:getHeight()
    local text_canvas = love.graphics.newCanvas(text_width, text_height)
    local texture_canvas = love.graphics.newCanvas(text_width, text_height)
    local texture_quad = love.graphics.newQuad(texture_x, texture_y, text_width, text_height, image:getDimensions())
    love.graphics.setCanvas(texture_canvas)
    love.graphics.setColor(1.0, 1.0, 1.0, 1.0)
    love.graphics.draw(image, texture_quad, 0, 0)
    love.graphics.setCanvas()
    love.graphics.setCanvas(text_canvas)
    love.graphics.setColor(1.0, 1.0, 1.0, 0.0)
    love.graphics.rectangle('fill', 0, 0, text_width, text_height)
    love.graphics.setColor(0.0, 0.0, 0.0, 1.0)
    love.graphics.draw(text_drawable, 0, 0)
    love.graphics.setCanvas()
    local texture_image_data = texture_canvas:newImageData()
    local text_image_data = text_canvas:newImageData()
    text_image_data:mapPixel(
        function(x,y,r,g,b,a)
            if a ~= 0 then
                return texture_image_data:getPixel(x,y)
            else
                return r,g,b,a
            end
        end
    )
    return love.graphics.newImage(text_image_data)
end

function love.load()
    textureImage = love.graphics.newImage('graphics/propaganda_goo.jpg')
    textureImage:setWrap('repeat', 'repeat')
    texturedText = MaskImageWithText(
        textureImage,
        love.graphics.newFont('fonts/Turtles.ttf', 128),
        'TURTLES'
    )
end

function love.draw()
    tX = math.floor(WINDOW_WIDTH/2 - texturedText:getWidth()/2)
    tY = math.floor(WINDOW_HEIGHT/2 - texturedText:getHeight()/2)
    love.graphics.setColor(1.0, 1.0, 1.0, 1.0)
    love.graphics.draw(texturedText, tX, tY)
end

I'm relatively happy with the result. Is there a more standard way to do this, and does anyone see something that's likely to bite me here?

I've attached the .love archive for anyone who wants to play with it.

Re: Drawing text filled with a texture instead of a solid color

Posted: Fri May 22, 2020 10:32 pm
by grump
Here's a simpler solution with a shader. The texturing depends on the screen position of the text with this code though, which can be easily fixed if required.

Re: Drawing text filled with a texture instead of a solid color

Posted: Fri May 22, 2020 11:06 pm
by hoistbypetard
Thanks! That's much neater. And it looks a lot like how I'd hoped the stencil I was trying at first would work.

I'm going to have to throw that shader language on the pile of things I want to learn more about. Is there any introductory material for GLSL (with or without LÖVE) which you consider especially good?

Re: Drawing text filled with a texture instead of a solid color

Posted: Sat May 23, 2020 2:29 am
by 4vZEROv
hoistbypetard wrote: Fri May 22, 2020 11:06 pm Thanks! That's much neater. And it looks a lot like how I'd hoped the stencil I was trying at first would work.

I'm going to have to throw that shader language on the pile of things I want to learn more about. Is there any introductory material for GLSL (with or without LÖVE) which you consider especially good?
https://thebookofshaders.com/
https://www.shadertoy.com/