opengl - 片段着色器 - 绘制曲线

标签 opengl glsl shader

如何使用片段着色器绘制一条线或一条曲线?

我有一个程序,可以根据用户指定的一组顶点计算贝塞尔曲线。早期,我简单地处理应用程序端的每个顶点以生成一组基于此三次贝塞尔曲线方程的插值点非常简单:

Cubic Bezier curve

...然后将所有处理过的顶点存储到 GL_VERTEX_ARRAY 中,以便使用 glDrawArrays(GL_LINE_STRIP, 0, myArraySize) 进行绘制。虽然解决方案很简单,但这个实现的时间复杂度是 O(n^2) .问题出现在我开始增加我的步数时,例如我的循环的每次迭代将 t 增加 0.01,用户生成他们想要的尽可能多的顶点。

所以那是我开始研究着色器的时候,尤其是片段着色器。据我所知,我们的片段着色器程序为 GPU 正在处理的当前片段分配一种颜色。我还没有认真研究着色器编程,但我当前的线着色器实现如下:

#version 120

uniform vec2 resolution;
uniform vec2 ptA;
uniform vec2 ptB;
uniform vec2 ptC;
uniform vec2 ptD;
uniform float stepTotal;

void main()
{
    vec2 uv = gl_FragCoord.xy / resolution.xy;
    vec2 curvePts[int(stepTotal)];

    float t = stepTotal;

    for(float i = 0.; i < 1.0; i += 1./t)
    {
        # Courtesy to: https://yalantis.com/blog/how-we-created-visualization-for-horizon-our-open-source-library-for-sound-visualization/
        vec2 q0 = mix(ptA, ptB, i);
        vec2 q1 = mix(ptB, ptC, i);
        vec2 q2 = mix(ptC, ptD, i);

        vec2 r0 = mix(q0, q1, i);
        vec2 r1 = mix(q1, q2, i);

        vec2 p_int = mix(r0, r1, i);
        curvePts[int(i) * int(stepTotal)] = p_int;
    }

    // TO DO:
    // Check if current fragment is within the curve. Not sure how
    // to proceed from here...
}

如您所见,我目前一直在思考如何检查当前片段是否在曲线内,以及如何为该特定片段分配颜色,使其在显示时最终变成一条曲线。

最佳答案

您可以使用距离函数绘制线段:

float DistanceToLineSegment(vec3 p, vec3 a, vec3 b)
{
    vec3 pa = p - a, ba = b - a;
    float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
    return length( pa - ba*h );
}

如果距离函数的结果小于某个阈值,则片段将位于片段的“内部”。

您也可以用平滑步进函数替换阈值测试来绘制抗锯齿线。

关于opengl - 片段着色器 - 绘制曲线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49517903/

相关文章:

opengl - 在 OpenGL 中同时使用可编程和固定管道功能

textures - Vulkan 纹理模糊问题

android - 在 OpenGL ES 2.0 上使用字节数组的 GL_LUMINANCE

winapi - 获取Win32中的项目目录以进行着色器加载

c++ - GLUPerspective 的原始 OpenGL 等价物?

c - OpenGL4 gl_texture_2d_array不会显示

c++ - 在 OpenGL/GLFW 中管理默认着色器

c++ - GLSL法线贴图问题

c++ - 从深度缓冲区值获取世界位置

opengl - 仅使用可变变量的一部分