GradientText.. Just for the Fun


--# GradientText
GradientText = class()

function GradientText:init(x,y,txt,color1,color2,size)
 self.x = x
 self.y = y
 self.txt = txt
 self.col1 = color1
 self.col2 = color2
 self.size = size
end

function GradientText:draw()
 fontSize(self.size)
 local x=0
 local diffR, diffG, diffB = (self.col2.r - self.col1.r),
                             (self.col2.g - self.col1.g),
                             (self.col2.b - self.col1.b)
 local stepR, stepG, stepB = (diffR / #self.txt),
                             (diffG / #self.txt),
                             (diffB / #self.txt)
   for i = 1, #self.txt do
       fill(i * stepR + self.col1.r, i * stepG + self.col1.g, i * stepB + self.col1.b)
       text(string.sub(self.txt, i, i), self.x + x, self.y) 
       x = x + textSize(string.sub(self.txt, i, i))
  end
end

function GradientText:touched(touch)
    -- Codea does not automatically call this method
end

--# Main
-- GradientText


function setup()
 displayMode(FULLSCREEN)
 textMode(CORNER)
 text1 = GradientText(50, 200, "Hello world...", color(0, 255, 0), color(0, 0, 255), 30)
 text2 = GradientText(50, 300, "Bonjour le monde...", color(023, 234, 456), color(34, 67, 89), 60)
 text3 = GradientText(50, 450, "Very fuuuunnnn...", color(255, 255, 255), color(255, 0, 0), 120)
end

function draw()
 background()
 text1:draw()
 text2:draw()
 text3:draw()
end

function touched(touch)

end

That’s a pretty good start and even though it doesn’t have too many applications I’m sure someone’s gonna need it

yes it is really for fun… =:)

seems like this would be better in a shader so that the GPU does the work.

@aciolino, This is a simple example, but if you want to optimize …
This class can be used as a member

Another way to potentially do this would be to draw the text in white into an image and then render the image as a mesh (using the image as a texture) and then set the vertex colours which could be animated to produce some funky text effects.

Couldn’t help myself, so I decided to code the above as a proof of concept demo (and threw in some shader love as well)

-- Gradient Text
-- A simnple proof of concept demo - enjoy

local myString = "Codea Rocks!"
local tSize = 100
local txtImg, txtMesh, shaderMesh

-- Use this function to perform your initial setup
function setup()
    
    -- Setup the text style
    fontSize(tSize); textAlign(LEFT); textMode(CORNER);
    
    -- Create an image of the text
    txtImg = image(textSize(myString))
    setContext(txtImg)
    fill(255); text(myString,0,0)
    setContext()
    

    -- Create a mesh with the image as a texture
    local w,h   = txtImg.width, txtImg.height
    local lx,ly = 50, 300
    
    local c1 = color(255,0,0)
    local c2 = color(0,255,0)
    local c3 = color(0,0,255)
    local c4 = color(255,255,0)

    -- Note - Meshes are made up of TRIANGLES!!!
    txtMesh = mesh()
        
    txtMesh.vertices  = { vec2(lx,ly),  vec2(lx+w,ly), vec2(lx+w,ly+h),
                          vec2(lx,ly),  vec2(lx+w,ly+h), vec2(lx,ly+h)}
                          
    txtMesh.colors    = {c3,c3,c1, c3,c1,c1 }

    txtMesh.texture   = txtImg
    txtMesh.texCoords = { vec2(0,0), vec2(1,0), vec2(1,1),
                          vec2(0,0), vec2(1,1), vec2(0,1) }
    
    
    -- Duplicate the above but use a shader (just because!)
    shaderMesh = mesh()
        
    shaderMesh.vertices  = { vec2(lx,ly-100),  vec2(lx+w,ly-100), vec2(lx+w,ly+h-100),
                             vec2(lx,ly-100),  vec2(lx+w,ly+h-100), vec2(lx,ly+h-100)}
                          
    shaderMesh.colors    = {c3,c3,c1, c3,c1,c1 }

    shaderMesh.texture   = txtImg
    shaderMesh.texCoords = { vec2(0,0), vec2(1,0), vec2(1,1),
                             vec2(0,0), vec2(1,1), vec2(0,1) }
                         
    shaderMesh.shader = shader("Effects:Ripple")

end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here

    -- Normal
    fontSize(tSize); textAlign(LEFT); textMode(CORNER)
    fill(255); text(myString,50,500)
    
    -- As an image
    spriteMode(CORNER)
    sprite(txtImg,50,400)

    -- As a mesh
    txtMesh:draw()
    
    -- Also with a shader
    shaderMesh.shader.freq = 0.4
    shaderMesh.shader.time = ElapsedTime
    shaderMesh:draw()

end

Enjoy :slight_smile:

NOTE - Remember meshes are lists of separate triangles, so that’s why there are two sets of three - I did consider using the addRect() method but I wanted a bit more control, plus you can create a nice reflection effect on the shader text, by skewing out the bottom x coords and inverting the texture.

eg.

    -- Duplicate the above but use a shader (just because!)
    shaderMesh = mesh()
        
    shaderMesh.vertices  = { vec2(lx-80,ly-100),  vec2(lx+w+80,ly-100), vec2(lx+w,ly+h-100),
                             vec2(lx-80,ly-100),  vec2(lx+w+80,ly+h-100), vec2(lx,ly+h-100)}
                          
    shaderMesh.colors    = {c2,c2,c3, c2,c3,c3 }

    shaderMesh.texture   = txtImg
    shaderMesh.texCoords = { vec2(0,1), vec2(1,1), vec2(1,0),
                             vec2(0,1), vec2(1,0), vec2(0,0) }