类似于OpenGL的广告牌类似表示法

时间:2019-02-26 16:57:20

标签: c++ opengl glsl glm-math

世界是由球体组成的。由于在OpenGL中绘制球体需要很多三角形,因此我认为使用点和半径表示球体然后在OpenGL中使用Billboarding绘制起来会更快。我目前采用的方法是在旋转视图时使相邻的球体不接触。

以下是一个示例:

有两个领域:

球体1 位置(0,0,-3)半径(0.5)

球体2 位置(-1,0,-3)半径(0.5)

使用以下方法定义投影矩阵:

glm::perspective(glm::radians(120.0f), 1.0f, 1.0f, 100.0f);

图片1 :当没有旋转时,它看起来像预期的那样。

No rotation

图像2 :当发生旋转时,广告牌将按预期方式对摄像机做出响应,球体不再接触。而且,如果它们实际上是彼此相邻的球体,那么您会期望它们相互接触。

Rotation

我尝试过的事情:

  • 我尝试了GL_POINTS,他们的表现不佳,因为它似乎并没有 为我正确处理深度测试。
  • 我尝试了一个几何着色器,该着色器可以在之前和之后创建一个正方形 投影矩阵已应用。

这是我现在创建图像的代码:

顶点着色器

#version 460

layout(location = 0) in vec3 position;
layout(location = 1) in float radius;


out float radius_vs;

void main()
{

    gl_Position = vec4(position, 1.0);
    radius_vs = radius;
}

几何着色器

#version 460

layout(points) in;
layout(triangle_strip, max_vertices = 4) out;
layout(location = 2) uniform mat4 view_mat;
layout(location = 3) uniform mat4 projection_mat;

in float radius_vs[];
out vec2 bounds;

void main()
{
    vec3 x_dir = vec3(view_mat[0][0], view_mat[1][0], view_mat[2][0]) * radius_vs[0];
    vec3 y_dir = vec3(view_mat[0][1], view_mat[1][1], view_mat[2][1]) * radius_vs[0];


    mat4 fmat = projection_mat * view_mat;


    gl_Position = fmat * vec4(gl_in[0].gl_Position.xyz - x_dir - y_dir, 1.0f);
    bounds = vec2(-1.0f, -1.0f);
    EmitVertex();

    gl_Position = fmat * vec4(gl_in[0].gl_Position.xyz - x_dir + y_dir, 1.0f);
    bounds = vec2(-1.0f, 1.0f);
    EmitVertex();

    gl_Position = fmat * vec4(gl_in[0].gl_Position.xyz + x_dir - y_dir, 1.0f);
    bounds = vec2(1.0f, -1.0f);
    EmitVertex();

    gl_Position = fmat * vec4(gl_in[0].gl_Position.xyz + x_dir + y_dir, 1.0f);
    bounds = vec2(1.0f, 1.0f);
    EmitVertex();

    EndPrimitive();
}

片段着色器

#version 460

out vec4 colorOut;

in vec2 bounds;

void main()
{
    vec2 circCoord = bounds;
    if (dot(circCoord, circCoord) > 1.0) 
    {
        discard;
    }
    colorOut = vec4(1.0f, 1.0f, 0.0f, 1.0);
}

0 个答案:

没有答案