What is the advantage of using an OpenGL fan instead of creating a circle based on different positions?
All the opengl tutorials I have seen show how to create a circle in OpenGL, use the "Fan" method (or some derivative) and I have not seen one of them use the following method:
Create a set of vertices like this:
float vertices[] = {
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 1.0f, -1.0f, // bottom right
-0.5f, -0.5f, 0.0f, -1.0f, -1.0f,// bottom left
-0.5f, 0.5f, 0.0f, -1.0f, 1.0f// top left
};
Create the following Vertex Shader that passes bounding information in a variable format to the fragment shader:
#version 330 core
in vec3 apos;
in vec2 abound;
out vec3 ourColor;
out vec2 ourBound;
void main() {
gl_Position = vec4(apos, 1.0);
ourBound = abound;
}
Create the following fragment shader that takes in interpolated bounds values to determine the fragment's current distance from the center.
#version 330 core
in vec2 ourBound;
uniform vec4 setColor;
void main() {
float dist = sqrt((ourBound.x * ourBound.x) + (ourBound.y * ourBound.y));
vec4 color_used = vec4(vec3(1.0), 0.0);
if(dist < 1.0){
color_used = setColor;
}
gl_FragColor = color_used;
}
- Load shaders
- Enable mixing
- Initialize VBO / EBO objects for apos (offset = 0, stride = 5 * sizeof (float)) and for abundance (offset = 3, stride = 5 * sizeof (float))
- Intialize colorLocation
- Save to VBA
in the draw loop loader:
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader_program);
glUniform4f(colorLocation, 0.0f, 1.0f, 0.0f, 1.0f);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
I don't understand the benefits for building a fan. Is there a performance advantage? It certainly doesn't seem simpler. I just can't seem to find alternative solutions via google other than what's here.
source to share
I don't understand the benefits of building a fan.
This is a tutorial. The purpose of the textbook is to teach a specific skill, not necessarily represent the best way to do something. What's important in the tutorial is not necessarily the result, but how you achieve it.
The two ways to create a circle require completely different skills. The vertex method involves using sin
/ cos
to compute points at the edge of a circle, and how to load such data into a buffer and use that buffer for rendering. Your impostor method demonstrates how to create two-dimensional impostors, and how to determine if a point is inside a (unit) circle.
A person who knows how to do point-in-circle doesn't know how to use sin
it cos
to calculate points on a circle either . Thus, if you then move on to the realms, you must teach them about sin
and cos
. If you've done circles on vertices before, they are one step ahead and can learn about spherical coordinate systems as an extension of what they already know.
Additionally, the vertex method is an easy way to teach users that more vertices can create smoother results. It also helps them understand that it is resolution dependent; the further you are from the vertex-based circle, the lower the vertex count value. You can even use this to teach people how to do dynamic LODing, where you recalculate the vertices of each frame. It has to do with streaming data for dynamically storing objects.
It doesn't matter if you've never used dynamic LODs for a simple circle. What matters is that the user has learned how to make streams of buffers.
These are two different skill sets. Both sets make sense and are useful, but they are different. There is nothing really wrong with any method; it all depends on what skills you are trying to teach.
It certainly doesn't seem simpler.
It depends on how you define "simpler". If the tutorial is trying to teach the user to understand triangular rendering, then your impostor-based approach isn't any easier. He also does not teach how to draw a triangle.
Your path requires the user to have a formal understanding of what's going on at the fragment level. And don't get me wrong; this is a good thing. Teaching users how to create impostors is a very good tool. But is the tool the user is willing to learn at this stage of their development?
Also, the shader approach is more limited. Let's say you want to add textures to this circle. With the vertex approach, you do the usual thing: add texture coordinates to the vertices, pass them along with the fragment shader, and let it extract from the texture. When using the shader approach, FS has to invent a specific mapping from texture to circle.
This means that any time you want to change this mapping, you must change your FS. You can add some parameters to FS to support scaled mapping options, but even that means you now have to split your triangular batches to change the display options. Whereas when using the vertex approach, you can map any number of fans in one callback (thanks to restarting the vertices) by simply baking the mapping into the vertex data.
Indeed, with the vertex approach, you can use the same shader for your circles as you would for any other shape. The shader approach requires changing shaders just to render something else.
Personally, I believe that textbooks should teach impostor techniques before they do. But I don't think crashing the impostors is the best way to go.
Is there a performance advantage?
It's good if you look at it in terms of anti-aliasing. Your fragment method will require special coding to work with multisampling. To do this correctly, you will need to calculate the distance for each pattern position and then output the corresponding pattern mask. Or call a sewing for a selection. It will be a little slower anyway.
But that would do an interesting lesson.
source to share
Is there any performance advantage?
The vertex fan might be better in your version, but if you change the fragment shader in the following way, it should be just as fast.
#version 330 core
in vec2 ourBound;
uniform vec4 setColor;
void main() {
//no sqrt required
float dist = dot(ourBound,ourBound);
//discard pixels on the outside.
//We can leave blending disabled.
if(dist > 1.0){
discard;
}
vec4 color_used = vec4(vec3(1.0), 0.0);
gl_FragColor = color_used;
}
I don't understand the benefits of building a fan.
If you just want to display a 2D circle, I don't think there is an advantage.
Alternative way:
Since it looks like you want to display a simple 2D circle, you can display a quad and place a texture with an alpha channel on it. This makes it easy to get a very nice anti-aliased circle or any other 2D object.
source to share