|
Gradient circles |
Kikaru
Member #7,616
August 2006
|
I am working on a project that would be greatly enhanced by a gradient circle effect. Something like: void grad_circle(BITMAP *bmp, int x, int y, int rad, int col1, int col2) Gradation would go from center to edges, a filled circle. Can anyone recommend either a pre-made function or a way to write a very fast, effective one? I am using plain Allegro, and it's kinda late to change libraries. It needs to be very fast, ideally. Thanks in advance. |
SiegeLord
Member #7,827
October 2006
|
Here's a little thing I hacked from allegro's do_circle routine... It is far from perfect (it has a lot of overdraw - about 28%) but it manages not to use any square roots (since in effect we are just calling allegro's do_circle routine a bunch of times). (note that it is incomplete, I did not put the actual color blending function since you did not specify whether you wanted this to be palette based or not). And here is the actual worker function. I do not understand yet how allegro's do_cirle works, so this hack is sort of primitive. As such it is both ugly and it has a lot of overdraw (as I said above).
Don't ask me how it works. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Edgar Reynaldo
Major Reynaldo
May 2007
|
I came up with another way. It doesn't draw quite as far out as allegro's circle function , but it's always within one pixel of it. Not sure where the difference is. Basically , the function traverses the y-values of the circle and the x-values of the horizontal chord of the circle at that y-value and draws a pixel with the color scaled from the inner color to the outer color according to the distance/radius factor. Here's the function code and a short example that draws a gradient circle using purple and yellow.
What it produces (image scaled down 50%) : You can see there are a few white pixels near the edges , those are an allegro circle drawn underneath with the same radius as the one passed to the function. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Kikaru
Member #7,616
August 2006
|
I will be drawing some of these circles with radii of 1500+, so it needs to be pretty darn fast, and accuracy doesn't matter quite so much. Basically, the fewer doubles, floats, sqrt()s, and sin()/cos()s the better. I will look into these later, as I don't have a compiler right now. The color is either 32 or 16 bit, so no palletes. The second function looks nice, but it shows up really weird on my computor. |
Arthur Kalliokoski
Second in Command
February 2005
|
I've tried stuff like this, and always got untouched pixels within the filled circle??? They all watch too much MSNBC... they get ideas. |
Kikaru
Member #7,616
August 2006
|
Ok, Edgar's circle works, but if I try to copy and paste the function, it looks really weird. Still figuring it out. Thanks for the input! [EDIT] it was defaulting to 8-bit color mode. |
Fladimir da Gorf
Member #1,565
October 2001
|
You'll get a huge performance increase if you can ensure that pixels outside of the screen won't be filled in the routine and replacing putpixel with a _putpixelXX. OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori) |
Thomas Harte
Member #33
April 2000
|
Quote: I will be drawing some of these circles with radii of 1500+, so it needs to be pretty darn fast, and accuracy doesn't matter quite so much. Basically, the fewer doubles, floats, sqrt()s, and sin()/cos()s the better. I will look into these later, as I don't have a compiler right now. I think the fastest method would be to prefill a texture with a scaled version of the fill, then circle with drawing_mode set to DRAW_MODE_COPY_PATTERN. So predraw a circle with at least 256 colour steps in it, using sqrt, sin, cos, whatever. The draw it to an offscreen BITMAP as though you were using stretch_blit instead of circlefill. So if you drew it to the screen you'd get something a lot like the circle you want, but with a jaggedy edge. The trick is that instead of drawing it to the screen, just set the BITMAP you drew to as the fill pattern and then use circlefill. So you get the outline calculated in the normal way and the fill taken from your scaled BITMAP. [My site] [Tetrominoes] |
Kikaru
Member #7,616
August 2006
|
Well, I changed stuff around a bit, so speed doesn't matter so much anymore. Thanks for the functions! |
Edgar Reynaldo
Major Reynaldo
May 2007
|
No problem , it was fun and now I have a gradient circle function to add to my collection of useful code. It may be possible to make it even faster. Right now it's drawn using 4 mirror images but that could be doubled to 8 mirror images by splitting the quarter into an eighth and flipping rel_xpos and rel_ypos to give four more draws per pixel calculation. Maybe I'll mess around with it some more later. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|