Final topic about Anti-Aliasing disease

Final topic about Anti-Aliasing disease
0.0 0

#1

Hi there. I want to start anti-aliasing post. I search many unaswered posts here on forum or answered, but with solutions, that did’t work for me or made such a small impact on resulted graphics. Can we together fight with Aliasing ? Or just draw a good looking smooth curved line is too much asking?
I use cocos2d-x 3.13 for android.

I need to make such curve.


As you can see, it has linear gradient from top Y to bottom Y.
As you can see, it has linear gradient on the right and on the left from alpha 100% to 0%.
And, as you can see, it has smooth borders, so curve is anti-aliased.

How to hell can I do it with cocos2dx?

DrawNode

I can use standart DrawNode class and draw cardinal splines, which will be transformed to a set of polygons. Something like this:

node = DrawNode::create(9);
node->clear();
node->drawCardinalSpline(pts, tension, segments, Color4F::RED);
for (int i = 0; i < pts->count(); ++i) {
    node->drawPoint(pts->getControlPointAtIndex(i), 10, Color4F::BLUE);
}

this picture has folowing artefacts:

  1. stepped curve borders (aliasing)
  2. some cutted holes inside line. (WTF?)

I tried :

  • varry segment number (at screenshot - tension = 0, segments = 120), but this didn’t help.
  • Tried to draw it at huge size and then use scaling - didn’t work.
  • Take a bitmap with RenderTexture and set anti aliasing flag on the resulted sprite - no.
  • smoothstep shader (many times mentioned at forum, for example, see here)

All of this lead to elumination of only small fraction of all the artifacts.

Drawing with triangles

I can draw all the things directly by calculating triangles verticies. I has a working solution with this. It looks like this:


Look at the curved line. (screen captured from android device). In order to make this, I used custom DrawNode, because I can’t set different opacity for different triangle vertex. My class AlphaNode for that:

And then I just fill the Vec2 array of vertices and for every 3 vertices call drawTriangle from my AlphaNode class. At this approach I get antialiasing by manually set alpha to 0 on borderline vertices:
I think I explain the idea clear (but if not I could make separate compilable solution with all the needed code a little bit latter).

This solutions definitely allow me to obtain any graphics I want. But do I really need engine, if I draw triangles by myself?
(and also if anyone have something to say about my custom draw node limitations, please - say)

LibSkia

Well. I can link to libskia on android. Make some path objects on skia side (skia will make them anti-aliased). Then export it to bitmap. Then draw with cocos. But again… why do I need cocos in that case?

Links Review

I will try to search for another way. I will be very happy from every piece of help. And I really think its an important feature for 2-3 d engine - ability to draw lines… How do you solved this issue for your project? How do you draw curves?


DrawNode line width don't work
#2

Update
Find Anti-Grain Geometry (AGG) thing.
Try out its android app. And its aliased at my nexus device! WTF? Antialiased anti-artifacts library demo consist of aliased graphics??! Arggghh.


#3

Update

For better visualisation aliasing effects try to change line width.didn’t worked . Does anything at DrawNode works as expected?


#4

Maybe take a look at MotionStreak


#5

@nite Thanks a lot! I look at it at cpp-tests, looks good. I will see the code pretty soon.

General progress.
As far as I understand, line width can’t be change much because DrawNode use lines for drawPoly. It need tesselation in order to properly varry line width. I use this general paper as a reference and try to implement it with custom DrawNode class. At drawCardinalSpline we first generate spline vertices and then draw them as a line segments. First I start drawing it not as line segments, but using triangles. It looks like that:

As you can see, now we can proper set line width, but I missed line joints. Image from reference article:

After I made some implementation for that I get this:

Now its time for adding some anti-aliasing. I made two border with triangles from alpha 1 to alpha 0. In general Its very bad, because it takes too much triangles and also some code definetelly need to be moved to shader. But I think about it as prototyping. (and I still can’t attach custom shader to my DrawNode. don’t know why).
Anyway. after adding border layers I’ve got this:


As you can see It has good antialiasing at convex edges ( I use big width to demostration), but inner edges still need some correction. I do something wrong here.


#6

It’s getting close, I think we need to tweak part thats generating the vertices.

Also here is an example of how to attach your shader to DrawNode.


#7

Thanks! I will look at this shader example. I can run simple blur shader and even give them arguments.

As for AA progress update. I was taking apart my vertices to see the problem.

Convex corner is good. Inner conner produce artifacts and need to be construct differently. I can detect what side is inner and what is convex. For outer corner I just add joint triangle. For inner - I can calculate bisector between two normal vectors. (points K and K2). But BK size should be greater that (line width / 2).

I hoped that I can fix this overlapping by changing blend mode. Apparently I was wrong and I do need to fix vertices.

Obtain inspiration from shadertoy samples heh =)

Update:
In order to minimize the number of triangles I was wandering, how does the guys from mapbox do this:
Attribute interpolation to the rescue.
If I understand correctlly, It is possible to make such triangles:

How to do that? hmm.


#8

Updates. Finish base algorithm.


(Sorry if it didn’t appears right. its mp4 converted to gif)
I wanted to demonstrate how bad is base aliasing, but, unfortunatelly, base curves get drawn with too small line width =(

I have some problems with:

  • curve ending
  • non-opaque colors (since we got then some triangle overlapping inside the line)
  • too mach calculations on cpu/engine side (I didn’t notice that it slow down something, but we need to calculate all this triangles…)

:TODO:

  • try to steal some shader code and insert it into cocos2dx
  • refactor my own DrawNode (implement other drawing consistently)
  • provide solution for color gradient

#9

Update 1.
Find a sample project SmoothDrawing. It uses pretty much the same approach, only implementation slightly differs. And I can’t compile it with cocos2dx-3-13. So I take geometry calculation from here and draw it via my custom Awesome Draw Node.


Anti-aliasing effect is small and we can’t varry it.

Can’t draw with non-opaque color (

Update 2
Find VASE Renderer. I will try to add it to my cocos project and use.

Well…looks pretty impressive…

But even such complex geometry can’t solve some issues (I have it in mine algorithm too)

Its almost the same inner corner triangles overlaping like I post before in my tesselation.


#10

Update


Here you can see a drawback of my tesselation. End of the line and some bad overlapping. Don’t know how to fix this easy. This is a color with some alpha. But hey! I know how to fix end of the line and I see that VASE Renderer has the same limitation.

Update2


Add debug for showing triangles at my tesselation. Hey. now its funnier!


#11

awesome work!!! keep it up


#12

Is this dead :frowning: ?


#13

I hope not =) I was a little bit discouraged by the fact that cocos2dx maintenance and development now handled by just one man. but I will post updates soon.


#14

Great to hear that!


#15

Don’t know if someone checked this: https://github.com/krzysztofzablocki/LineDrawing


#16

@owlet Any updates? :smiley: