Skip navigation.

Software Development

Correcting The Future

Bézier Splines on GPU Part II

I finished the code for drawing cubic splines in hardware and I like the results. It's not perfect, but it's very flexible and is extremely fast. It should work on most cards. The only requirement is vertex shader 1.1 or higher. I know this works on ATI 8500 and up. I don't know about NVidia though most of those should work too. On anything newer, it's insanely fast which means you can set a lot of options to make it look better and use up more of the available GPU processing power.

The first run looked good as I said, except for one thing. It was blocky. All the curves had jaggy edges. Here's a screen shot. Click on the image for the full view. FYI, the frame rates in the screenshots were captured on a 10 year old machine with an ATI 9200SE. This is 100 splines with 64 segments each.



A few things to note. When a spline crosses over on itself, it'll draw on screen twice. That means there's a darker or brighter region where the crossover happens. I've heard people say that's not how it's supposed to be. I don't know. I think it makes sense considering that these splines are blended in with the background. Another thing is that splines with extreme curvature will also draw itself twice just underneath the apex. This is because the inflexion point is in the middle of the thickness of the line. So the spline is stretched out above it and that part is fine. But below it, it folds in over itself and so this part gets drawn multiple times. This part, I agree it shouldn't be like that. I could fix it with a stencil buffer. Right now though, it's good enough.

Jaggies are my enemy. I can't stand them. I refuse to leave them be. So I decided to look around and see if I couldn't antialias my splines. I did try multisampling and it gave great results. But it ate up processing power. It cut the frame rate down by a lot and although newer cards fare better, it just used up processing time that I really didn't see was necessary. I could leave it as an option for newer cards I suppose.

In any case, I decided to fake the antialiasing. I basically adjust the line thickness and draw the spline multiple times. Say my alpha value is 128, then on pass 1, I use an alpha value of 64 with a line thickness that's 2 pixels wider. Then I draw pass 2 with alpha of 64 with the original line thickness.

I had one problem though. It was appearing darker than normal. I didn't understand what was going on until I looked at the math.

Final color = Alpha * Source + (1-Alpha) * Dest

Pass 1: C = 0.25S + 0.75D
Pass 2:
C = 0.25S + 0.75(Pass1 Color)
C = 0.25S + 0.75(0.25S + 0.75D)
C = 0.25S + 0.1875S + 0.5625D
C = 0.4375S + 0.5625D

That's not a 50/50 split like I wanted. It gets worse if I try to apply more passes. That's something I had to fix. Looking at the equation again:

A + (1-A)*B = C

A is the alpha value we need to give the hardware, B is the old alpha from the last pass and C is the new alpha we want. So we need to solve for A.

A + B - AB = C
A - AB = C - B
A(1-B) = C - B
A = (C-B)/(1-B)

All we have to do at every pass is plug in our numbers and we'll get the Alpha we need to give the hardware. We start by setting B to 0 and C to .25 (64/255).

A = (.25-0)/(1-0)
A = .25

The first pass is done as normal. For the second pass, we set B to C. And now we set C to double what we had before which is 0.5. This will apply another .25 Alpha for a total of .5.

A = (0.5-0.25)/(1-0.25)
A = 0.25/0.75
A = 0.33

We now use an alpha of 0.33 with the hardware. That will produce the correct result. You can split up your alpha as many times as you want. I made it an option where you can state how many levels you want for the alpha channel. Level 1 is no antialiasing. 2 is what I described above. For higher levels, it'll simply split up the alpha value by the level number. This is what you get for level 2.



As you can see, it's smoother. I think this is a huge improvement.

Here's level 4.



There's a little color difference on that one of one or two rgb values. Not a big difference. It's noticeable if you need accurate color values though.

To draw a spline, I supply the following:

1. Color
2. Line Width
3. 4 Control Points
4. Antialiasing level (1=NONE)
5. A transformation matrix.

You can also change the number of segments by resetting the vertex list that this function uses. You simply pass the number of segments you want and it'll take care of the rest. I'll make all of this available as a component in Project V for those who want it.

All in all, I really like the results. For me, this is WAY better than I was hoping for. I only need it to connect components. This will do just fine.

Bézier Splines on GPUSave the 2008 American Election TV Show!

Comments

avatar
Oh, forgot to mention that the vertex shader is 70 instructions long. That's close to the 128 limit. What baffles me is that it worked the on the first run except for one vertex at the end. I only needed to flip a negative sign to fix it. Programs that run the first time scare me, especially when I've never done vertex shaders before.

By Vorlath, # 11. February 2008, 05:51:13

Write a comment

Comment
(BBcode and HTML is turned off for anonymous user comments.)

Please type this security code : 483f0d

Smilies

November 2008
S M T W T F S
October 2008December 2008
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29