Skip to content Skip to sidebar Skip to footer

Draw Circle Opengl Using Triangle Fan

This time I want to talk virtually drawing geometric shapes using OpenGL. Every bit we know, nosotros tin depict lines, triangles, and quads, but what about circles? There are several means to do this. Offset style is approximate circle with number of lines. Let'due south look at the figure 1. We accept an approximation of circle nowadays by 16 vertices. We will draw sixteen edges: {[v1, v2],[v2, v3],…,[v16, v1]}. This tin can be enough fo the circle to looks polish at depression resolutions, just we have to make more vertices and edges to make the circumvolve shine at loftier DPI displays.

fig_1
To generate this type of circumvolve nosotros tin use this fragment of (C11) code

#define NUMBER_OF_VERTICES 16 float radius = 0.5; std::vector<float> vertexBuffer; for(double i = 0; i < two * M_PI; i += 2 * M_PI / NUMBER_OF_VERTICES){     vertexBuffer.push_back(cos(i) * radius);    //X coordinate     vertexBuffer.push_back(sin(i) * radius);    //Y coordinate     vertexBuffer.push_back(0.0);                //Z coordinate }              

This code generates a buffer, that we tin can demark to attribute vector in vertex shader

glBindBuffer(GL_ARRAY_BUFFER, 0); glVertexAttribPointer(VERTEX_ATTRIBUTE_INDEX , 3, GL_FLOAT, GL_FALSE, 12, vertexBuffer.data());              

and draw it, using OpenGL part glDrawArrays

glDrawArrays(GL_LINE_LOOP, 0, NUMBER_OF_VERTICES);              

line-loop-circle

Draw filled circle

And so, nosotros tin can draw a circle, but what we have to practice if we wan to fill it with color? We accept to subdivide our figure to triangles and render each triangle filled with color. Wait at figure 2.
fig_2new
This shape is subdivided to 14 triangles with common vertices v1. In OpenGL this structure of mesh calls TRIANGLE_FAN, and we have special cartoon way GL_TRIANGLE_FAN. To implement it nosotros'll change just i line of code:

glDrawArrays(GL_TRIANGLE_FAN, 0, NUMBER_OF_VERTICES);              

triangle-fan-circle
Now we complicate our task. We`ll draw something similar a torus projection on the plain. As we did above, nosotros`ll judge this figure with simple polygons. Looks at the figure 3.
fig_3
I suggest using GL_QUAD_STRIP to draw this figure. Now we'll draw a strip of xvi quads, that looks like sequence of vertices: {[v'one,v1,five'ii,v2],[5'2,v2,v'three,v3]…[v'xvi,v16,v'1,v1]}. Allow's generate vertices for quads

#define NUMBER_OF_VERTICES xvi float radius_1 = 0.5; float radius_2 = 0.25; std::vector::vertexBuffer; for(double i = 0; i &amp;lt; 2 * PI; i += PI / NUMBER_OF_VERTICES_2){     vertexBuffer.pushBack(cos(i) * radius_2); //10 coordinate     vertexBuffer.pushBack(sin(i) * radius_2); //Y     coordinate vertexBuffer..pushBack(0.0); //Z     coordinate vertexBuffer.pushBack(cos(i) * radius_1); //X     coordinate vertexBuffer.pushBack(sin(i) * radius_1); //Y     coordinate vertexBuffer..pushBack(0.0); //Z coordinate } vertexBuffer.pushBack(radius_2); vertexBuffer.pushBack(0.0); vertexBuffer.pushBack(0.0); vertexBuffer.pushBack(radius_1); vertexBuffer.pushBack(0.0); vertexBuffer.pushBack(0.0);              

and draw a quad strip:

glBindBuffer(GL_ARRAY_BUFFER, 0); glVertexAttribPointer(VERTEX_ATTRIBUTE_INDEX , 3, GL_FLOAT, GL_FALSE, 12, vertexBuffer.data()); glDrawArrays(GL_QUAD_STRIP, 0, 2*NUMBER_OF_VERTICES+2);              

quad-streep-circle

Describe filled circumvolve in shader (GLSL)

Those methods are based on the shape of object. Now I want to present yous another ane method based on a shading. Equally we well know nosotros can inscribe circle into quad, I chose this figure every bit basic archaic that I should pass into fragments shader. I stand for quad by «triangle fan», considering GPUs return «triangle fan» faster then other shapes. Our vertexBuffer volition exist looks like this

float right = 0.5; bladder bottom = -0.5; float left = -0.v; float top = 0.5; bladder vertexBuffer[18]={ //ten y z right, lesser, 0, // v1  right, top, 0, // v2  left, tiptop, 0, // v3  left, bottom, 0, // v4  };              

If we draw this vertexBuffer we'll se a quad on the screen. You can inquire me: So, where is a circle? To turn this quad into a circle we have to add some data.

float valueBuffer[12]={      //lx ly      1.0, -1.0,      ane.0, 1.0,      -1.0, 1.0,     -ane.0, -1.0,  }              

At present we have two coordinate systems: OpenGL coordinate organization and local coordinate system.
coordinates_2
In OpenGL coordinate systems we can do any own modifications of shape (such as translate, rotate and scale) which change vertex data, but values in local coordinate system will be constant. To increases operation I combine vertexBuffer and valueBuffer and demark this consequence to VBO:

float correct = 0.v; float bottom = -0.five; float left = -0.5; float top = 0.5; float quad[xx] = {     //x, y, z, lx, ly     right, bottom, 0, i.0, -1.0,     right, top, 0, 1.0, 1.0,     left, top, 0, -1.0, one.0,     left, bottom, 0, -1.0, -one.0, };      unsigned int glBuffer; glGenBuffers(1, &amp;glBuffer); glBindBuffer(GL_ARRAY_BUFFER, glBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(bladder)*twenty, quad, GL_STATIC_DRAW);              

Let's wait at fragment shader.

attribute vec4 vertex; attribute vec2 value; compatible mat4 viewMatrix;  uniform mat4 projectionMatrix; varying vec2 val; void chief() {      val = value;      gl_Position = projectionMatrix*viewMatrix*vertex;  }              

In fragment shader nosotros have two aspect vectors. Nosotros bid vertexBuffer to vertex aspect vector and valueBuffer to value attribute vector. So nosotros laissez passer local coordinate values to fragment shader using varying vec2 val. Now GPU interpolates local values for each pixel of the quad on the screen. All we know standard equitation of a circle on coordinate airplane:

(x-x0)^2+(y-y0)^2 = R^2              

x0 and y0 are coordinates of the eye on the coordinate plane, x and y are local coordinates of quad and R is radius of the circumvolve. Nosotros accept all necessary data do write a fragment shader.

varying vec2 val;  void main() {      float R = ane.0;      float R2 = 0.five;      float dist = sqrt(dot(val,val));     if (dist >= R || dist <= R2)     { discard; }      gl_FragData[0] = vec4(0.0, 0.0, 1.0, 1.0); //Blue color  }              

aliased-circle
This shader fills with blue colour only altitude betwixt R1 and R2. As you can see, this circle is non antialiased. If you implement 'Deferred rendering' technique with FXAA mail processing you tin can don`t care well-nigh this and use this shader «as-is». By the way, on retina display it looks good. 🙂 Otherwise yous tin smooth edges of circle by smoothstep role.

varying vec2 val; void main() {     float R = 1.0;      bladder R2 = 0.5;     float dist = sqrt(dot(val,val));      if (dist >= R || dist <= R2) { 	    discard;     }     float sm = smoothstep(R,R-0.01,dist);     bladder sm2 = smoothstep(R2,R2+0.01,dist);     bladder blastoff = sm*sm2;     gl_FragColor = vec4(0.0, 0.0, 1.0, alpha); }              

Note, before using this shader, you lot have to enable alpha blending.

glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);              

That'southward all, folks! There is our circumvolve!

antialiased-circle

As usual, you tin can download lawmaking sample from this link:circles.tar.gz

brownunth1972.blogspot.com

Source: https://blog.lapingames.com/draw-circle-glsl-shader/

Post a Comment for "Draw Circle Opengl Using Triangle Fan"