如何在GLSL中渲染无限的2D网格?

Neo*_*ana 14 opengl glsl

理想情况下,我想要做的是绘制一个四边形并让GLSL处理实际网格线的创建.

在我的尝试到目前为止顶点着色器:

#version 400

layout (location = 0) in vec4 in_position;
layout (location = 2) in vec3 in_UV;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

smooth out vec3 ex_UV;
smooth out vec3 ex_originalPosition;

void main()
{
    gl_Position = projection * view * model * in_position;

    ex_UV = in_UV;
    ex_originalPosition = vec3(in_position.xyz);
}
Run Code Online (Sandbox Code Playgroud)

模型矩阵将四边形向上缩放一些大数,例如10,000.

#version 400

layout (location = 0) out vec4 color;

smooth in vec3 ex_UV;
smooth in vec3 ex_originalPosition;

uniform vec4 lineColor;

void main(void)
{
    if(fract(ex_UV.x / 0.001f) < 0.01f || fract(ex_UV.y / 0.001f) < 0.01f)
        color = lineColor;
    else
        color = vec4(0);
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试过使用纹理坐标和世界空间位置.两者都产生相同的效果,在某些角度看起来很好,但在其他角度看起来很可怕.

在此输入图像描述

在此输入图像描述

我想也许我可以根据距离缩放alpha,这样我的网格就会消失,但问题是你可以在第二张图片中看到,从屏幕中心,你可以看到即使是那些线也是通过它们的间隙渲染(网格的点是在原点周围给出一个可视的参考框架).

有更简单的方法吗?

编辑

截图请求:

带有x8多重采样帧缓冲的VBO线

在此输入图像描述

具有x8多重采样帧缓冲和glEnable的VBO行(GL_LINE_SMOOTH)

在此输入图像描述

我安定下来了

我选择了上面的任何一个(并不重要)并简单地将alpha降低为与原点距离的函数.这符合我的目的,虽然这不是我问的问题. 在此输入图像描述

joz*_*yqk 19

一个简单的别名案例.就像多边形渲染一样,每个像素运行一次片段着色器.仅针对单个中心坐标计算颜色,并且不代表真实颜色.

在此输入图像描述

  1. 您可以创建多重采样FBO并启用超级采样.但那很贵.
  2. 您可以在数学上精确计算每个像素下的线区域和空网格区域的数量,然后在片段着色器中相应地对它们进行着色.鉴于它是一个统一的网格,这可能属于可能的范围,但数学可能仍然相当复杂.
  3. Mipmapping已经为纹理做了这个.创建一个只有几行的网格纹理并将其映射,以便为您真正大的四边形重复(确保设置GL_REPEAT).为纹理和调用设置正确的mipmap过滤参数glGenerateMipmap.在片段着色器中调用texture2D()/时texture(),OpenGL会根据相邻像素之间的纹理坐标增量自动计算要使用的mipmap的哪个级别.最后,为更加惊人的网格设置各向异性过滤.

    在此输入图像描述

如果你想让一个网格真正"无限",我已经看到一些海洋渲染器将网格的边缘连接到具有垂直几何的地平线.如果你之前有足够的网格,你可能会将它们设置为一种平面颜色 - 即mipmap顶层的颜色.


示例(与评论有关):

从VBO中提取的1024x2 GL_LINES
在此输入图像描述
45fps(在HD res上绘制100倍基准)

请参阅有关多重采样以解决GL_LINES别名的注释.

使用mipmapping将32 ^ 2纹理映射到四边形
在此输入图像描述
954fps(在HD res上绘制100倍基准)

Image img;
int w = 128;
int h = 128;
img.resize(w, h, 1);
for (int j = 0; j < h; ++j)
    for (int i = 0; i < w; ++i)
        img.data[j*w + i] = (i < w / 16 || j < h / 16 ? 255 : 0);

tex = img.upload();

glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);

...

//for the quick and dirty, immediate mode
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
glBegin(GL_QUADS);
glTexCoord2f(0,       0); glVertex3f(0, 0, 0);
glTexCoord2f(1024,    0); glVertex3f(1, 0, 0);
glTexCoord2f(1024, 1024); glVertex3f(1, 0, 1);
glTexCoord2f(0,    1024); glVertex3f(0, 0, 1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
Run Code Online (Sandbox Code Playgroud)

  • 纹理根本不能保证无缝的线条。此外,您引入了许多不必要的片段处理和采样,在行方法中,只会运行实际对行有贡献的片段。目标只是绘制一个 2D 网格,对我来说,您的所有方法都是一种巨大的矫枉过正。 (2认同)