Jump to content
  • Advertisement
Sign in to follow this  
aravindant

OpenGL Smoothing of Circles

This topic is 3073 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,
I am new to this forum and opengl. I have been trying to solve this problem for quite a while now. I need to smooth the circles which I draw. On searching, I came to know it can be done with texture mapping.

I have tried texture mapping in my code which I have shown below. I am not able to smooth the edges even when I apply the texture (actually array of white pixels. Any help on pointing me the mistake or any other method would be higly appreciated

[spoiler]

/***************************************/


void create_texture(void)
{
width = 128;
height = 128;

texture_data = (unsigned char *)malloc( width * height * 3 );

for(int i = 0 ; i < width * height * 3 ; i++)
{
texture_data = 0Xff;
}


}

/*****************************************/


Then in the init() function I wrote the following


//Function that creates the white color texture to be used in smoothing the circle boundary
create_texture();

//Initialize the 2D texture parameters

// allocate a texture name
glGenTextures( 1, &texture );


// select our current texture
glBindTexture( GL_TEXTURE_2D , texture );


// select modulate to mix texture with color for shading
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );



// when texture area is small, bilinear filter the closest mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);

// when texture area is large, bilinear filter the original
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );


// the texture wraps over at the edges (repeat)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );



glNewList(texture = glGenLists(1),GL_COMPILE);
glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_data); //check these parrameters
glEndList();

free(texture_data);

/*************************************/
void drawCircle(float radius)
{
double k;


float x , y;



glLineWidth(0.05);


glEnable(GL_TEXTURE_2D);
glCallList(texture);
glBegin(GL_LINE_LOOP);


for ( k=0; k <= 360.0;)
{
float degInRad = k*DEG2RAD;

x = cos(degInRad)*radius;
y = sin(degInRad)*radius;

glTexCoord2f(0.5,0.5);
glVertex2f(x,y);


k = k + 5;
}



glEnd();
glDisable(GL_TEXTURE_2D);

glLineWidth(1.5);


}
[/spoiler]

Share this post


Link to post
Share on other sites
Advertisement
Yes. Anti-aliasing of circles.

I already tried GL_LINE_SMOOTH along with blend. The anti-aliasing works for circles with bigger radius. But for tiny circles, the edges look spongy or foggy. But when I zoom these tiny circles they look smooth.

Hence I moved to texture mapping.

Share this post


Link to post
Share on other sites
I think with a texture, you are supposed to actually save an image of an anti-aliased circle, that you draw in Photoshop or something, and then use that image as a texture and draw a quad in OpenGL, displaying the circle texture at the correct spot.
You could also write a function that draws the anti-aliased circle pixel by pixel into the texture, though that might be harder, depending on how familiar you are with those types of algorithms.

Another thing you can try, is to draw points with point-smoothing. For example, if your circle is supposed to be 10 pixels in radius and have a thickness of 1 pixel, first draw a black point of radius 10 pixels at the circle center, and then draw another point with the background color and radius 9 pixels at the same position, which should leave a black circle edge. Experimenting with the radii you might be able to get nice looking circles.

Share this post


Link to post
Share on other sites
You're drawing your line using linestrips or linelists.
The bigger the radius, you're gonna need more vertices.

I think this should do the trick:


const int nIterations = 72 * ((radius < 1) ? 1.0f : radius);
for ( k=0; k <= nIterations; ++k )
{
float degInRad = (360.0f / (float)(nIterations)) * k * DEG2RAD;

x = cos(degInRad)*radius;
y = sin(degInRad)*radius;

glTexCoord2f(0.5,0.5);
glVertex2f(x,y);
}


Haven't tested, may be there's some typo. Just wrote it. But should work.

Cheers
Dark Sylinc

Share this post


Link to post
Share on other sites
Hi all,
Thanks for the replies. I was able to get smooth circles. But when the circles are close to each other, the texture of one circle hides the other. This is because, the texture is obtained from a bmp image which can be only a square (64 X 64 etc). Hence the empty areas in the square where the circle is not present hide the adjacent circle.
Please find the file hidden_circles.bmp in the following link, which shows a circle hidden by another.

hidden_circles
Any ways to overcome this???



This is how I did.

1. I drew really smooth circles with protractor and other stuffs of required sizes.
2. You can go for scanning these images to get a .bmp image. But I found taking a photograph of this drawing and converting them to a .bmp to be of superior quality.
3. Then load the bmp image into your program as texture.
4. If you need a circle of radius 10 and center (0.0,0.0). Find the enclosing square, which has sides of length 20.
Let A (-10,-10) B(10,-10) C(10,10) and D(-10,10) be the vertices of the square

5. glTextCoord2f(0.0,0.0)
glCoord2f(point A)

glTextCoord2f(1.0,0.0)
glCoord2f(point B)

glTextCoord2f(1.0,1.0)
glCoord2f(point C)

glTextCoord2f(0.0,1.0)
glCoord2f(point D)

This will draw the circle image in the square area





Share this post


Link to post
Share on other sites
You can avoid this with blending. The best way is probably to create a texture with an alpha-channel, which can be used to draw parts of the texture transparently, avoiding overdrawing another circle with white. If you Google for alpha blending tutorials with OpenGL you should find plenty.
Another way is to create a black and white texture, where the circle is white and the other parts of the texture is black, and then drawing with:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR, GL_ONE);

glColor3f(circle-color);

...draw quad...

If you use a black circle on white background instead, using glBlendFunc(GL_ZERO, GL_SRC_COLOR); might work OK instead.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!