如何在GLSL中渲染无限的2D网格? [英] How can I render an infinite 2D grid in GLSL?

查看:35
本文介绍了如何在GLSL中渲染无限的2D网格?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

理想情况下,我想要做的是绘制一个四边形,并让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);
}

模型矩阵将四边形放大某个较大的数字,如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);
}

我已经尝试使用纹理坐标和世界空间位置来实现这一点。两者都会产生相同的影响,在某些角度看起来很好,但在另一些角度开始看起来很可怕。

我想也许我可以根据距离缩放Alpha,这样我的网格就会逐渐消失,但问题是您可以在第二张图像中看到,从屏幕的中心开始,您可以看到,即使是这些线也是通过它们的间隙呈现的(网格的目的是在原点周围提供一个可视的参照系)。

是否有更简单的方法来完成此操作?

编辑

应要求截图:

具有x8多采样帧缓冲区的VBO行

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

我已确定

我选择了上面的任何一个(实际上并不重要),简单地将alpha降低为离原点的距离的函数。这符合我的目的,虽然这不是我问的问题。

推荐答案

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

  1. 您可以创建多采样FBO并启用超采样。但是那很贵。
  2. 您可以通过数学方法精确计算每个像素下有多少线区域和空网格区域,然后在片段着色器中对它们进行相应的着色。如果它是一个统一的网格,这可能是可能的,但数学计算可能仍然会变得相当复杂。
  3. Mipmap已对纹理执行此操作。创建一个只有几条线的网格纹理,并对其进行贴图,以使其针对您的非常大的四边形重复(请确保设置GL_REPEAT)。为纹理设置正确的mipmap过滤参数并调用glGenerateMipmap。在片段着色器中调用texture2D()/texture()时,OpenGL会根据相邻像素之间的纹理坐标增量自动计算要使用的mipmap级别。最后,设置各向异性过滤,使网格看起来更漂亮。

如果您希望栅格真正是"无限的",我见过一些海洋渲染器使用垂直几何体将栅格的边缘连接到地平线上。如果在它们之前有足够的网格,您可以将它们设置为一种平面颜色-mipmap顶层的颜色。


示例(与评论相关):

从VBO绘制的1024x2 GL_LINES

45fps(高清分辨率基准绘制100次)

请参阅有关多重采样的备注以解决GL_LINES混叠问题。

使用mipmap将32^2纹理映射到四边形

954fps(高清分辨率基准绘制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);

这篇关于如何在GLSL中渲染无限的2D网格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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