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

标签 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);
}

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

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

enter image description here

enter image description here

我想也许我可以根据距离缩放 alpha,这样我的网格就会消失,但问题是你可以在第二张图像中看到,从屏幕的中心,你可以看到即使是那些线通过它们呈现间隙(网格的点是在原点周围提供视觉引用框架)。

有没有更简单的方法来做到这一点?

编辑

按要求截图:

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

enter image description here

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

enter image description here

我定了

我选择了上述任何一种(实际上并不重要),并简单地将 alpha 降低为与原点的距离的函数。尽管这不是我问的问题,但这符合我的目的。
enter image description here

最佳答案

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

enter image description here

  • 您可以创建一个多重采样 FBO 并启用 super 采样。但这很昂贵。
  • 您可以在数学上准确计算每个像素下有多少线条区域和空网格区域,然后在片段着色器中对它们进行相应的着色。鉴于它是一个统一的网格,这可能是可能的,但数学可能仍然会变得相当复杂。
  • 微映射 已经为纹理做了这个。只用几条线创建一个网格纹理并映射它,以便它为你真正的大四边形重复(确保设置 GL_REPEAT )。为纹理设置正确的mipmap过滤参数并调用 glGenerateMipmap .当您调用 texture2D()/texture()在片段着色器中,OpenGL 根据相邻像素之间的纹理坐标增量自动计算要使用的 mipmap 级别。最后,设置各向异性过滤以获得更令人惊叹的网格。
  • https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt
  • https://gamedev.stackexchange.com/q/69374/34435

  • enter image description here
    如果您希望网格真正“无限”,我已经看到一些海洋渲染器使用垂直几何将网格的边缘连接到地平线。如果在它们之前有足够的网格,则可以将它们设置为一种纯色——mipmap 顶层的颜色。

    示例(与评论有关):

    从 VBO 绘制的 1024x2 GL_LINES
    enter image description here
    45fps(以 HD res 为基准绘制 100 次)

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

    使用 mipmapping 映射到四边形的 32^2 纹理
    enter image description here
    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);
    

    关于opengl - 如何在 GLSL 中渲染无限的 2D 网格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30842755/

    相关文章:

    c++ - OpenGL、FreeGlut 和 Glew 因 glGenVertexArrays 调用而崩溃

    c++ - mac 上的 OpenGL 版本

    c++ - 延迟渲染的特殊情况

    OpenGL 4.4/ES 3.0 和缓存 channel 之间的顶点数据

    android - Android 设备上 OpenGL fragment 着色器中的 SIGSEGV

    opengl - GLSL/HLSL - 多单行条件语句而不是单 block

    c++ - OpenGL 第三人称相机

    c++ - OS X 上的 OpenGL 版本支持

    java - 如何在 JAVA 中的简单 FPS 中使用游戏状态

    opengl - glBlendFunc 禁用着色器