使用OpenGL粉丝而不是根据不同的位置创建圆圈有什么好处?

whn*_*whn 3 c++ opengl shader geometry drawing

我见过的所有opengl教程都展示了如何在OpenGL中创建一个圆圈使用"Fan"方法(或一些衍生物),我没有看到使用以下方法:

像这样创建一组顶点:

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
};
Run Code Online (Sandbox Code Playgroud)

创建以下顶点着色器,将不同格式的边界信息传递给片段着色器:

#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;
}
Run Code Online (Sandbox Code Playgroud)

创建以下片段着色器,该着色器采用插值边界值来计算当前片段距中心的距离

#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;
}
Run Code Online (Sandbox Code Playgroud)
  • 加载着色器
  • 启用混合
  • 初始化VBO/EBO对象为(offset = 0,stride = 5*sizeof(float))和​​abound(offset = 3,stride = 5*sizeof(float))
  • 初始化colorLocation
  • 存储在VBA中

在绘制循环加载程序中:

    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);
Run Code Online (Sandbox Code Playgroud)

我的结果 在此输入图像描述

我不明白创建风扇的好处.是否有一些性能优势?它当然似乎并不简单.除了这里的那个,我根本无法通过谷歌找到替代解决方案.

Nic*_*las 6

我不明白创建风扇的好处.

这是一个教程.教程的目的是教授一些特定的技能,而不一定是提出做某事的最佳方法.教程中最重要的不一定是结果,而是你实现它的方式.

创建圈子的两种方式需要截然不同的技能.顶点方法涉及使用sin/ cos计算圆边上的点,以及如何将这些数据上传到缓冲区并使用该缓冲区进行渲染.您的冒名顶替者方法演示了如何创建2D冒名顶替者,以及如何判断某个点是否位于(单位)圆内.

知道如何进行圆点测试的人不知道如何使用sincos计算圆上的点.因此,如果你继续做领域,你必须教他们关于sincos.然而,如果您之前通过顶点做过圆,那么它们就是领先一步,可以了解球面坐标系作为他们已知的扩展.

此外,顶点方法是一种向用户传授更多顶点可以创建更平滑结果的简单方法.它还有助于他们了解这取决于分辨率; 离基于顶点的圆越远,顶点的数量就越少.您甚至可以使用它来教人们如何进行动态LOD,每次重新计算顶点.这涉及动态地将数据流传输到缓冲对象.

如果你永远不会将动态LOD用于单纯的圈子并不重要.重要的是用户已经学会了如何进行缓冲流式传输.

这是两套不同的技能.这两组都是有意义和有用的,但它们是不同的.两种方法都没有任何内在错误; 这都是你想要教授什么技能的问题.

它当然似乎并不简单.

这取决于你如何定义"更简单".如果教程试图教会用户理解三角形渲染,那么基于冒名顶替者的方法并不简单.它也没有教三角渲染.

您的方式要求用户正式了解片段级别的内容.别误会我的意思; 这是一件好事.教用户如何制作冒名顶替者是一个非常好的工具.但这是用户在开发过程中准备学习的工具吗?

此外,着色器方法更受限制.假设您要为此圆圈添加纹理.使用顶点方法,您可以执行以下操作:将纹理坐标添加到顶点,将它们传递到片段着色器,然后从纹理中获取.使用着色器方法,FS必须发明从纹理到圆的特定映射.

这意味着只要您想要更改此映射,就必须更改FS.您可以向FS添加一些参数以支持缩放映射的变体,但即使这意味着您现在必须拆分三角形批处理以更改映射参数.而使用顶点方法,您可以在单个绘制调用中渲染任意数量的扇形(由于顶点重新启动),只需将映射烘焙到顶点数据即可.

实际上,使用顶点方法,您可以像对待任何其他形状一样使用与圆相同的着色器.着色器方法需要更改着色器才能呈现不同的内容.

就个人而言,我认为教程应该比他们更早地教授冒名顶替者的方法.但我不认为圈子冒名顶替是最好的方式.

是否有一些性能优势?

好吧,如果你从抗锯齿的角度来看待它.基于片段的方法需要特殊编码才能使用多重采样.要正确完成,您需要计算每个样本位置的距离,然后输出与之对应的样本掩码.或者调用每个样本着色.无论哪种方式,这都会慢一些.

但那将是一个有趣的教训.