Final topic about Anti-Aliasing disease

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?

9 Likes

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.

Update

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

Maybe take a look at MotionStreak

@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.

5 Likes

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.

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.

1 Like

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
4 Likes

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.

1 Like

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!

6 Likes

awesome work!!! keep it up

1 Like

Is this dead :frowning: ?

1 Like

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.

2 Likes

Great to hear that!

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

@owlet Any updates? :smiley:

Okay, I recently quit my job so now I’m on some sort of sabbatical and I’m planing to finish some of the works, like was presented in this thread so stay tuned and let see what will happens =)

If anyone here still draw lines and do custom graphics with cocos2dx (or everyone gone to make blockchain out of engine that can’t draw lines…)

1 Like

Updates: Rewrite code && refactor for approximation by triangles.
Apparently, there is a bug inside cardinal spline math inside DrawNode code, which messed up curve ends. Fix.

3 Likes

Updates: distinguish two separate cases for thick and thin lines. For thin, I used my tesselation algorithm. For thick, draw cardinal spline’s segments by segment shader works better. Added fillings for curves and dashed \ dotted-dashed lines. com-video-to-gif

Soon you will be able to grab things from github and leave feedback.

2 Likes

awesome :smiley: