Function to outline texts

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
Gunroar:Cannon()
Party member
Posts: 1085
Joined: Thu Dec 10, 2020 1:57 am

Function to outline texts

Post by Gunroar:Cannon() »

I was thinking of a function that's like graphics.print but draws a border around the text in a different color (without editting the font file).

I tried making a function that prints the text twice, one a little bigger then the normal one. This makes it inconsistent (maybe because of spaces). So I don't have the solution now. Any ideas? Maybe I have to split up the word and do it letter by letter (ignoring spaces).
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
BrotSagtMist
Party member
Posts: 604
Joined: Fri Aug 06, 2021 10:30 pm

Re: Function to outline texts

Post by BrotSagtMist »

I think youre talking about text shadows here?
Image
I just print it twice with 1 pixel offset.
You should get a decent border if you do an offset in every direction but that sounds a bit wasteful.
obey
MrFariator
Party member
Posts: 509
Joined: Wed Oct 05, 2016 11:53 am

Re: Function to outline texts

Post by MrFariator »

The simplest, though not exactly optimized way is to draw the text five times:
  • x offset -1, y offset 0 (outline color)
  • x offset 0, y offset -1 (outline color)
  • x offset 1, y offset 0 (outline color)
  • x offset 0, y offset 1 (outline color)
  • x offset 0, y offset 0 (normal text color)
Of course, this assumes more pixel arty resolution for the text, so this is not entirely scalable if the text is "HD", in a sense.
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: Function to outline texts

Post by pgimeno »

I have the same problem. It appears that a shader is the answer. https://bgolus.medium.com/the-quest-for ... 82ed442cd9

Edit: I made this some time ago: viewtopic.php?p=221215#p221215 - It's not enough for my purposes because I need wider outlines, but maybe it's fine for you.
User avatar
GVovkiv
Party member
Posts: 668
Joined: Fri Jan 15, 2021 7:29 am

Re: Function to outline texts

Post by GVovkiv »

pgimeno wrote: Wed Nov 16, 2022 8:22 pm I have the same problem. It appears that a shader is the answer. https://bgolus.medium.com/the-quest-for ... 82ed442cd9

Edit: I made this some time ago: viewtopic.php?p=221215#p221215 - It's not enough for my purposes because I need wider outlines, but maybe it's fine for you.
It's kinda amazing how sometimes task such as adding 1 pixel border to texture or text might end up as 30 minutes manual how to do so
User avatar
Gunroar:Cannon()
Party member
Posts: 1085
Joined: Thu Dec 10, 2020 1:57 am

Re: Function to outline texts

Post by Gunroar:Cannon() »

pgimeno wrote: Wed Nov 16, 2022 8:22 pm I have the same problem. It appears that a shader is the answer. https://bgolus.medium.com/the-quest-for ... 82ed442cd9

Edit: I made this some time ago: viewtopic.php?p=221215#p221215 - It's not enough for my purposes because I need wider outlines, but maybe it's fine for you.
Shaders for the win :monocle:.
GVovkiv wrote: Wed Nov 16, 2022 8:52 pm It's kinda amazing how sometimes task such as adding 1 pixel border to texture or text might end up as 30 minutes manual how to do so
:rofl: Will probably need to do this method.
BrotSagtMist wrote: Wed Nov 16, 2022 1:53 pm I just print it twice with 1 pixel offset.
You should get a decent border if you do an offset in every direction but that sounds a bit wasteful.
MrFariator wrote: Wed Nov 16, 2022 1:56 pm The simplest, though not exactly optimized way is to draw the text five times:
  • x offset -1, y offset 0 (outline color)
  • x offset 0, y offset -1 (outline color)
  • x offset 1, y offset 0 (outline color)
  • x offset 0, y offset 1 (outline color)
  • x offset 0, y offset 0 (normal text color)
Of course, this assumes more pixel arty resolution for the text, so this is not entirely scalable if the text is "HD", in a sense.
It's what I did already but still ended up...
Attachments
(bottom right)
(bottom right)
Screenshot_2022-11-16-21-55-11.png (219.92 KiB) Viewed 1575 times
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
BrotSagtMist
Party member
Posts: 604
Joined: Fri Aug 06, 2021 10:30 pm

Re: Function to outline texts

Post by BrotSagtMist »

But how on earth can you get that result?
obey
User avatar
Gunroar:Cannon()
Party member
Posts: 1085
Joined: Thu Dec 10, 2020 1:57 am

Re: Function to outline texts

Post by Gunroar:Cannon() »

:? The font is ... ermm ... HD. So the overall text next to each other is bigger than the word if individual letters were used I think :?
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
Gunroar:Cannon()
Party member
Posts: 1085
Joined: Thu Dec 10, 2020 1:57 am

Re: Function to outline texts

Post by Gunroar:Cannon() »

pgimeno wrote: Thu May 31, 2018 11:29 am Here's a library for 11.1 that I believe fulfils the requisites:

Code: Select all

--[==========================================================================[--

Outliner shader

Based on code by Micha (Germanunkol)

(C) Copyright 2018 Pedro Gimeno Fortea

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
 
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Usage:

local outline_only = false -- draw the outline AND the image in the same pass
--local outline_only = true -- draw the outline only

-- 'require' returns a constructor that requires the outline_only parameter
local outliner = require 'outliner'(outline_only)

-- sets the outline colour (in 0..1 range)
outliner:outline(r, g, b)

-- draws an outline or an image with outline (decided at construction time),
-- possibly using a quad. Same parameters as love.graphics.draw except for the
-- size prefix, which is the size of the outline.
outliner:draw(size, img, ...)


--]==========================================================================]--

local aux = {0, 0, 0, 0}
local lgdraw = love.graphics.draw
local lgsetShader = love.graphics.setShader

local function outline(self, r, g, b)
  aux[1] = r
  aux[2] = g
  aux[3] = b
  aux[4] = nil
  self.shader:send("outline", aux)
end

local function draw(self, size, img, ...)
  local quad = (...)
  if type(quad) == "userdata" then
    -- assumed quad
    local sx, sy = quad:getTextureDimensions()
    aux[1], aux[2], aux[3], aux[4] = quad:getViewport()
    aux[1] = aux[1] / sx
    aux[2] = aux[2] / sy
    aux[3] = aux[3] / sx
    aux[4] = aux[4] / sy
    self.shader:send("quad", aux)
    aux[1] = size / sx
    aux[2] = size / sy
  else
    local sx, sy = img:getDimensions()
    aux[1], aux[2], aux[3], aux[4] = 0, 0, 1, 1
    self.shader:send("quad", aux)
    aux[1] = size / sx
    aux[2] = size / sy
  end
  aux[3], aux[4] = nil, nil
  self.shader:send("stepSize", aux)
  lgsetShader(self.shader)
  lgdraw(img, ...)
  lgsetShader()
end


local function new_outliner(outline_only)
  local shader = [[

// This parameter affects the roundness. 0.75 is close to the Euclidean
// correct value. If it's 0.0, the shape of the "brush" making the outline
// will be a diamond; if it's 1.0, it will be a square.
const float t = 0.0;

extern vec3 outline; // Outline R,G,B
extern vec2 stepSize; // Distance parameter
extern vec4 quad;

const vec4 zero = vec4(0.,0.,0.,0.);
vec2 q1 = quad.xy;
vec2 q2 = quad.xy + quad.zw;

vec4 effect( vec4 col, Image texture, vec2 texturePos, vec2 screenPos )
{

  // get color of pixels:
  float alpha = -20.0 * texture2D(texture, clamp(texturePos, q1, q2)).a;
  vec2 aux = vec2(stepSize.x, 0.);
  alpha += texture2D(texture, clamp(texturePos + aux, q1, q2) ).a;
  alpha += texture2D(texture, clamp(texturePos - aux, q1, q2) ).a;
  aux = vec2(0., stepSize.y);
  alpha += texture2D(texture, clamp(texturePos + aux, q1, q2) ).a;
  alpha += texture2D(texture, clamp(texturePos - aux, q1, q2) ).a;

  if (t != 0.0)
  {
    aux = stepSize;
    alpha += t * texture2D(texture, clamp(texturePos + aux, q1, q2)).a;
    alpha += t * texture2D(texture, clamp(texturePos - aux, q1, q2)).a;
    aux = vec2(-stepSize.x, stepSize.y);
    alpha += t * texture2D(texture, clamp(texturePos + aux, q1, q2)).a;
    alpha += t * texture2D(texture, clamp(texturePos - aux, q1, q2)).a;
  }

@calc_result@
  return result;
}
  ]]


  if outline_only then
    shader = shader:gsub("@calc_result@", [[
  vec4 result = vec4(outline, alpha);
]])
  else
    shader = shader:gsub("@calc_result@", [[
  vec4 result =
      max(max(sign(alpha), 0.) * vec4( outline, alpha ), zero)
    - min(min(sign(alpha), 0.) * texture2D(texture, texturePos), zero);
]])
  end
  shader = love.graphics.newShader(shader)


  local result = {
    shader = shader;
    draw = draw;
    outline = outline;
  }
  result:outline(0, 1, 0) -- define some starting value
  return result
end

return new_outliner
Works but when I try to run it on you know what (mobile) it gives me

Code: Select all

Error

Error validating pixel shader code:
Line 12: ERROR: 'non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)' : not supported for this version or the enabled extensions 
ERROR: 1 compilation errors.  No code generated.


Traceback

[C]: in function 'newShader'
outliner.lua:144: in function 'newOutliner'
main.lua:18: in function 'load'
[C]: in function 'xpcall'
[C]: in function 'xpcall'
Any way to fix it so it runs on both?
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
BrotSagtMist
Party member
Posts: 604
Joined: Fri Aug 06, 2021 10:30 pm

Re: Function to outline texts

Post by BrotSagtMist »

Just to make this clear, this doesnt work for you?

Code: Select all

love.graphics.setFont(love.graphics.newFont(50))
function love.draw()
 love.graphics.setColor(1,0,0)
 love.graphics.print("HEloooooooooooooooooooooooooooooooooAAA!",-1,-1)
 love.graphics.setColor(0,1,0)
 love.graphics.print("HEloooooooooooooooooooooooooooooooooAAA!",1,1)
 love.graphics.setColor(0,0,1)
 love.graphics.print("HEloooooooooooooooooooooooooooooooooAAA!")
end
obey
Post Reply

Who is online

Users browsing this forum: No registered users and 21 guests