Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
antialiased lines in a shape? — Gideros Forum

antialiased lines in a shape?

keszeghkeszegh Member
edited August 2012 in General questions
Can somebody help me how to draw lines which are not jagged? I try to make a sort-of drawing app yet the quality of the lines made using moveto/lineto is much worse than i need. Thanks

Dislikes: drewfg

+1 -1 (+0 / -1 )Share on Facebook

Comments

  • ar2rsawseenar2rsawseen Maintainer
    edited August 2012 Accepted Answer
    Hello,
    unfortunately this is one of the most requested features, that is not yet implemented.

    I have couple of "crazy" ideas, but I doubt they'll work good enough:

    1) draw the shape 2 times or even 4 times bigger and then scale it down to original size
    2) use multiple shape objects by drawing multiple line one over another using same color but only decreasing opacity
    3) Use and bitmap image color pattern, draw the shape that is the size of a line and fill it with this color (maybe even transforming bitmap if needed)

    I'm actually interested how hard that could be to implement anti-alising into Gideros using openGL ES?

    If I look up for the answers then they vary from "it's impossible" to "it could be done by adding 4 lines of code".

    http://stackoverflow.com/questions/1813035/opengl-es-iphone-drawing-anti-aliased-lines

    Unfortunately can't test it and can't give any realistic feedback

    Likes: jack0088

    +1 -1 (+1 / -0 )Share on Facebook
  • Thanks for the clues.
    Also, I forgot to mention that my primary target is android.

    In case it is much requested, is there any chance that it will be implemented sometime in the near future?

  • I tried the 1st method, scaling down did not make any smoothing effect unfortunately.
    i also thought about the
    2nd method as a possible workaround and it is indeed quite effective. using 3 lines with decreasing width and increasing opacity i could achieve a good level of smoothing.
    i did not try the 3rd method.
    so thanks for the ideas, i will accept the answer, although an api-level solution would be the best, i hope that it will come in the future.
  • Sorry to re-launch an older thread but is there any update on this one? It's something I could use too. :-)
  • For single lines, you may create a 2x4 png image and do something like this:
    SingleLine = Core.class()
     
    function SingleLine:init(color, thickness)		
    	self.bmp = Bitmap.new(Texture.new("ima2x4.png", true))	
    	self.bmp:setAnchorPoint(0.5, 0.5)
    	self.bmp:setColorTransform(color.r, color.g, color.b, color.a)
    	self.thickness = thickness
    	stage:addChild(self.bmp)
    end
     
    function SingleLine:Draw(x1, y1, x2, y2) 
    	local bmp = self.bmp
    	local length = math.sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
    	bmp:setScaleX(0.5 * length)
    	bmp:setScaleY(0.5 * self.thickness)
    	bmp:setRotation(math.atan((y2 - y1)/(x2 - x1)) * 180 / math.pi)	
    	bmp:setX(x1 + 0.5 * (x2 - x1))
    	bmp:setY(y1 + 0.5 * (y2 - y1))
    end
     
    ...
    Example of use:
    local yourLine = SingleLine.new({r = 1, g = 1, b = 0, a = 1}, 2)
    yourLine:Draw(10, 10, 200, 100)
    It's just an idea. You can improve it as you wish.
    ima2x4.png
    2 x 4 - 166B
    ima2x4.png
    2 x 4 - 166B
  • @Drix, sounds like another creative solution. I needed variable width lines, so this would not work for me though. Actually finally i use meshes to draw the lines (each segment consists of two triangles).
    There (thanks also to @atilim for the hint) i added a 1-vertex wide (this part was important, maybe it works best if you don't do scaling of your project) border (quadrangular) mesh on each side that has 0 alpha on the outer vertices and 1 alpha on the inner vertices. This gave a quite good antialiasing effect. This way you need altogether 6 triangles per segment instead of 2, but it still performs quite well.
    you can check my app if you want to see how it looks:
    http://www.amazon.com/gp/product/B009IVLQ6Y
  • @keszegh, I still have not had the opportunity to work with meshes in Gideros (just recently I started studying this SDK), but I perfectly understood your solution. Very nice and consistent for the purposes of your app. Moreover, congratulations! Great app with really smooth lines.
  • atilimatilim Maintainer
    edited November 2012
    And here is the resulting code while discussing with @keszegh:
    local mesh = Mesh.new()
     
    local d = 1
    local color = 0x306090
     
    mesh:setVertexArray(-50, -50, 50, -50, 50, 50, -50, 50,
                        -50-d, -50-d, 50+d, -50-d, 50+d, 50+d, -50-d, 50+d)
     
    mesh:setColorArray(color, 1, color, 1, color, 1, color, 1,
                       color, 0, color, 0, color, 0, color, 0)
     
    mesh:setIndexArray(1, 2, 3,
    	1, 3, 4,
    	5, 6, 2,
    	5, 2, 1,
    	2, 6, 7,
    	2, 7, 3,
    	4, 3, 7,
    	4, 7, 8,
    	5, 1, 4,
    	5, 4, 8)
     
    mesh:setPosition(100, 100)
     
    stage:addChild(mesh)
     
    stage:addEventListener(Event.ENTER_FRAME, function()
    	mesh:setRotation(mesh:getRotation() + 0.2)
    end)
    You can change the variable 'd' (e.g. 0, 1, 10) to see various results.
  • How effective is this when used a lot (about 50 objects on screen)? How about drawing circles or arcs?
  • atilimatilim Maintainer
    @gianmichele - there won't be any performance problems. and to draw circles or arcs, you need to subdivide your path into small line segments.
  • So one could actually abstract meshes to Shape object's API (and even more) which would draw antialised meshes underneath?

    Maybe we don't need Shape obejct at all? :)

    I really need to wrap my head around the possibilities of meshes at least once :)
  • Hello,
    Are there some (beginners) samples on how to use mesh?
    I can not find them on the internet..
  • MellsMells Guru
    edited November 2012
    @ar2rsawseen > I am wondering the other way around : what is available in the Shape Class that can't be done through Meshes?

    We would need a wrapper in order to get similar setFillStyle access, and I don't see how to replicate a line style (create polygons with width=1px?) without getting something a bit complicated when setting vertices.

    @DRS
    Here is an example that uses basic functionalities + combine texture mapping and color vertices for advanced effects.
    twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
  • atilimatilim Maintainer
    So one could actually abstract meshes to Shape object's API (and even more) which would draw antialised meshes underneath?

    Maybe we don't need Shape obejct at all? :)

    I really need to wrap my head around the possibilities of meshes at least once :)
    yes. here the most complicated thing can be triangulating (complex) polygons. And while talking with @Mells, we've decided to provide a triangulate function (but again I cannot give a time estimate)
  • @Mells,
    I did see your sample, but i don't understand it really hehe.
    So that why i asked a beginners sample, so i understand how it works..
    Thanks.

    Likes: SimplesApps

    +1 -1 (+1 / -0 )Share on Facebook
  • emreemre Member
    edited January 2014
    Hi, after I released Point to Point some of my friends ask me that why lines are not good enough.
    So I go back this post:
    Currently I am using "Drix" comment on this post.
    SingleLine = Core.class()
     
    function SingleLine:init(color, thickness)		
    	self.bmp = Bitmap.new(Texture.new("ima2x4.png", true))	
    	self.bmp:setAnchorPoint(0.5, 0.5)
    	self.bmp:setColorTransform(color.r, color.g, color.b, color.a)
    	self.thickness = thickness
    	stage:addChild(self.bmp)
    end
     
    function SingleLine:Draw(x1, y1, x2, y2) 
    	local bmp = self.bmp
    	local length = math.sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
    	bmp:setScaleX(0.5 * length)
    	bmp:setScaleY(0.5 * self.thickness)
    	bmp:setRotation(math.atan((y2 - y1)/(x2 - x1)) * 180 / math.pi)	
    	bmp:setX(x1 + 0.5 * (x2 - x1))
    	bmp:setY(y1 + 0.5 * (y2 - y1))
    end
    I could not understand Atilim's solution.

    Is there any update or progress about drawing antialiased lines?

    Thanks.
  • @emre
    that is something we are looking for good solution all the time.

    Atilims solution was to instead of drawing simple 1px wide line, you draw a shape around it, to fill 1px wide shape of line. That was what the Clipper lib was for.
    Then use triangulation algorythm, to create Mesh representing that line
    And fill that Mesh with gradient from the line color to transparent (alpha 0), thus making it antialized.

    While it probably would look good visually, I'd say it is an overkill, especially for fast redrawing shapes. And thus far I only ported Clipper to Gideros and was looking for better triangulaion algorythm implementations.
  • @emre, look also at this thread:
    http://www.giderosmobile.com/forum/discussion/comment/27130#Comment_27130

    there, e.g., in my last comment there is another way of doing antialiased lines using meshes, it's like atilims example but as a function, on the other hand you first need to compute the many coordinates for it (the 4 vertices of the rectangle representing your segment, plus 4 more coordinates representing the vertices of the 'extended' segment, the one which is in gradient to achieve anti-aliasing effect), but this is not hard.
  • keszeghkeszegh Member
    edited February 2014
    let me repeat here from http://giderosmobile.com/forum/discussion/comment/34444#Comment_34444 how to do simply anti-aliased lines with meshes.

    with this class/function:
    Frame = Core.class(Mesh)
     
    function Frame:renderSegment(a1x,a1y, a2x,a2y, b1x,b1y, b2x,b2y, a3x,a3y, b3x,b3y, a4x,a4y, b4x,b4y,color_curr)
      local i=self.i
        --adding vertices:
      self:setVertices(i*8+1, a1x, a1y, i*8+2, a2x, a2y)
      self:setVertices(i*8+3, b1x, b1y, i*8+4, b2x, b2y) 
      self:setVertices(i*8+5, a3x, a3y, i*8+6, b3x, b3y) 
      self:setVertices(i*8+7, a4x, a4y, i*8+8, b4x, b4y)     
     
        --setting vertex colors and transparencies:
      self:setColors(i*8+1, color_curr, 1, i*8+2, color_curr, 1)
      self:setColors(i*8+3, color_curr, 1, i*8+4, color_curr, 1)	
      self:setColors(i*8+5, color_curr, 0, i*8+6, color_curr, 0)
      self:setColors(i*8+7, color_curr, 0, i*8+8, color_curr, 0)	  
     
        --adding the 3x2 triangles (we need 3 quadrangles and each has two triangles):
      self:setIndices(i*18+1, i*8+1, i*18+2, i*8+3, i*18+3, i*8+4)
      self:setIndices(i*18+4, i*8+1, i*18+5, i*8+4, i*18+6, i*8+2)
     
      self:setIndices(i*18+7, i*8+5, i*18+8, i*8+6, i*18+9, i*8+3)
      self:setIndices(i*18+10, i*8+5, i*18+11, i*8+3, i*18+12, i*8+1)  
     
      self:setIndices(i*18+13, i*8+2, i*18+14, i*8+4, i*18+15, i*8+8)
      self:setIndices(i*18+16, i*8+2, i*18+17, i*8+8, i*18+18, i*8+7)
     
      self.i=self.i+1
    end
    you can draw something like this:
    image
  • totebototebo Member
    Is anti-aliased lines still on the roadmap?
    My Gideros games: www.totebo.com
  • SinisterSoftSinisterSoft Maintainer
    You could prob anti-alias lines with a shader in the (near) future?

    See the middle of this paper for code...

    http://jcgt.org/published/0002/02/08/paper.pdf
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
Sign In or Register to comment.