I’ve tried several approaches to getting text shadows, but none of them are working. I’m trying achieve text shadow effect like this:
The methods I’ve experimented with were based off this this thread How font cache works.
I’ve tried several approaches to getting text shadows, but none of them are working. I’m trying achieve text shadow effect like this:
The methods I’ve experimented with were based off this this thread How font cache works.
An easy way to do this offset type would be to create two text nodes (or more), and parent one to the other. Then make one the darker color, and then update all text nodes to whatever text you want.
I was trying to be clever thinking the only way was to use a shader (premature optimization…). Not sure why I never considered this simple solution. Thanks a bunch @Pkeod!
For those interested, heres a function I’ve made for this. It caches the generated shadow nodes so you can apply it to the same node with low performance cost.
-- should replace with an lru cache
local appliedNodes = {}
local function addShadow(parentPos, shadow, color, offset)
gui.set_color(shadow, color)
local offsetPos = parentPos + offset
gui.set_position(shadow, offsetPos)
return shadow
end
local function setShadow(parent, textColor, layer, shadows)
local root = parent
local rootPos = gui.get_position(root)
local id = gui.get_id(root)
local previouslyApplied = appliedNodes[id] ~= nil
local t1 = nil
if not previouslyApplied then
-- remove color from parent since we'll be creating child nodes for the actual visual result
gui.set_color(root, vmath.vector4(0))
-- new text to proxy the root
t1 = gui.clone(root)
gui.set_inherit_alpha(t1, false)
gui.set_parent(t1, root)
gui.move_above(t1, root)
end
-- store generated gui nodes so we can reference them for future updates
appliedNodes[id] = appliedNodes[id] or {
t1 = t1,
shadowNodes = {}
}
local shadowNodes = appliedNodes[id].shadowNodes
t1 = appliedNodes[id].t1
gui.set_layer(t1, layer)
gui.set_color(t1, textColor)
if shadows == nil then
return
end
for i=1, #shadows do
local color, offset = unpack(shadows[i])
local previouslyRendered = shadowNodes[i] ~= nil
local shadow = shadowNodes[i] or gui.clone(t1)
shadowNodes[i] = shadow
if not previouslyRendered then
gui.set_inherit_alpha(shadow, false)
gui.set_parent(shadow, root)
gui.move_above(t1, shadow)
end
gui.set_layer(shadow, layer)
addShadow(rootPos, shadow, color, offset)
end
end
function init(self)
self.r = 0
self.dir = 1
end
function update(self, dt)
-- change direction
if self.r >= 1 then
self.dir = -1
elseif self.r <= 0 then
self.dir = 1
end
-- change color over time
self.r = self.r + (dt * self.dir)
local node = gui.get_node("text")
local textColor = vmath.vector4(self.r,1,1,1)
local layer = "text"
local shadowColor = vmath.vector4(self.r,.3,.3,1)
local shadows = {
-- south shadow
{
shadowColor,
-- 2px down
vmath.vector3(0, - 2, 1)
},
-- east shadow
{
shadowColor,
-- 2px right
vmath.vector3(2, 0, 1)
},
}
setShadow(node, textColor, layer, shadows)
end