在OpenGL/GLSL中绘制镶嵌细分的LineLoop [英] Drawing tessallated LineLoops in OpenGL/GLSL

查看:262
本文介绍了在OpenGL/GLSL中绘制镶嵌细分的LineLoop的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在渲染球体上的一些LineLoop(行星上的边界),并希望将它们细分成更短的线,以防止长线夹入球体. 例子:

I am rendering some LineLoops on a sphere (borders on a planet) and want to tessallate them into shorter lines to prevent long lines clipping into the sphere. Example:

这是我当前的源代码: C ++绘图调用:

Here is my current source code: C++ draw call:

void Border::Draw() const
{
    glBindVertexArray(_vao);

    glPatchParameteri(GL_PATCH_VERTICES, 2);
    glDrawArrays(GL_PATCHES, 0, _size);

    glBindVertexArray(0);
}

顶点着色器:

#version 400

in layout(location = 0) vec3 position;

void main()
{
    gl_Position = vec4(position, 1.0);
}

镶嵌控制着色器:

#version 400

layout (vertices = 2) out;

void main()
{
    if(gl_InvocationID == 0)
    {
        //get the distance between two points
        float dist = length(gl_in[0].gl_Position - gl_in[1].gl_Position);
        gl_TessLevelOuter[0] = 1;
        //divide line in segments of size 1.0
        gl_TessLevelOuter[1] = abs(dist);
    }

    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}

镶嵌化评估着色器

#version 400

layout (isolines, equal_spacing) in;

uniform float planetRadius;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    vec4 p = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);

    //offset point so it is on the spheres surface
    p = normalize(p);
    p *= planetRadius;

    gl_Position = projection * view * p;
}

片段着色器:

#version 400

out vec4 outColor;

void main()
{
    outColor = vec4(1.0, 1.0, 1.0, 1.0);
}

镶嵌细分似乎无法像我期望的那样工作(等值线文档也很糟糕).

The tessallation doesn't seem to work like I expect it to work (documentation on isolines is also bad).

这是我使用LineLoops和仅顶点/片段着色器绘制时的外观:

This is how it looked when I draw it with LineLoops and only Vertex/Fragment Shader:

这是我实施镶嵌处理后的样子:

and this is how it looks like after I implemented my tessallation:

这些线看起来也不是棋盘格状的,并且长度与以前相同.

The lines also do not look tessallated and have the same length as before.

问候乔尼

自己找到解决方案.在下面的答案部分中查看它.

Found the solution myself. Look in answer section below to see it.

推荐答案

我找到了解决方案.问题在于tessallation着色器无法绘制线条.因此,如果您拥有由点{p1, p2, p3, p4, p5, p6}定义的线带,则会在以下位置之间绘制线:
p1-> p2
p3-> p4
p5-> p6

I found the solution. The problem lies within the tessallation shaders inability to draw line strips. So if you hava a line strip defined by the points {p1, p2, p3, p4, p5, p6} it draws lines between:
p1 -> p2
p3 -> p4
p5 -> p6

我通过给着色器每个点2次来修复它,所以我的列表如下所示:
{p1, p2, p2, p3, p3, p4, p4, p5, p5, p6, p6, p1}
镶嵌细分着色器创建以下行:
p1-> p2
p2-> p3
p3-> p4
p4-> p5
p5-> p6
p6-> p1

I fixed it by giving the shader every point 2 times, so my list looks like this:
{p1, p2, p2, p3, p3, p4, p4, p5, p5, p6, p6, p1}
The tessallation shader creates following lines:
p1 -> p2
p2 -> p3
p3 -> p4
p4 -> p5
p5 -> p6
p6 -> p1

我的着色器现在看起来像这样:

My shaders now look like this:

TessControl:

TessControl:

#version 430

layout (vertices = 2) out;

void main()
{
    if(gl_InvocationID == 0)
    {
        float dist = length(gl_in[0].gl_Position.xyz - gl_in[1].gl_Position.xyz);

        gl_TessLevelOuter[0] = 1;
        gl_TessLevelOuter[1] = dist;
    }

    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}

TessEval:

#version 430

layout (isolines, equal_spacing) in;

uniform float planetRadius;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    //only interpolate and normalize xyz coordinates. Thanks to @aslg
    vec3 p = mix(gl_in[0].gl_Position.xyz, gl_in[1].gl_Position.xyz, gl_TessCoord.x);

    p = normalize(p);
    p *= planetRadius;

    gl_Position = projection * view * vec4(p, 1.0);
}

这篇关于在OpenGL/GLSL中绘制镶嵌细分的LineLoop的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆