OpenGL 纹理重复伪影

OpenGL texture repeat artifacts

我使用的是 OpenGL(4.5 核,LWJGL 3.0.0 build 90),我注意到使用 GL_REPEAT 大量重复的环绕模式在纹理上出现了一些伪影:

是什么原因造成的,我该如何解决(如果可以)?


这里,平面尺寸为100x100,UVs为10000x10000。这个截图真的非常接近它(从远处看,纹理太小了,我们只能看到一个平坦的灰色),近平面在 0.0001,远平面在 10。 我不确定问题是否出在深度缓冲区中,因为 OpenGL 默认设置在较近的距离上具有非常高的精度。

(编辑: 我正在考虑纹理坐标上的浮点错误,但我不确定)

这是我的着色器(我使用的是延迟渲染,纹理采样在几何通道中,所以我只给几何通道着色器)。

顶点着色器:

#version 450 core

uniform mat4 projViewModel;
uniform mat4 viewModel;
uniform mat3 normalView;

in vec3 normal_model;
in vec3 position_model;
in vec2 uv;
in vec2 uv2;

out vec3 pass_position_view;
out vec3 pass_normal_view;
out vec2 pass_uv;
out vec2 pass_uv2;

void main(){
    pass_position_view = (viewModel * vec4(position_model, 1.0)).xyz;
    pass_normal_view = normalView * normal_model;
    pass_uv = uv;
    pass_uv2 = uv2;

    gl_Position = projViewModel * vec4(position_model, 1.0);
}

片段着色器:

#version 450 core

struct Material {
    sampler2D diffuseTexture;
    sampler2D specularTexture;

    vec3 diffuseColor;

    float uvScaling;
    float shininess;
    float specularIntensity;

    bool hasDiffuseTexture;
    bool hasSpecularTexture;
    bool faceSideNormalCorrection;
};

uniform Material material;

in vec3 pass_position_view;
in vec3 pass_normal_view;
in vec2 pass_uv;
in vec2 pass_uv2;

layout(location = 0) out vec4 out_diffuse;
layout(location = 1) out vec4 out_position;
layout(location = 2) out vec4 out_normal;

void main(){
    vec4 diffuseTextureColor = vec4(1.0);

    if(material.hasDiffuseTexture){
        diffuseTextureColor = texture(material.diffuseTexture, pass_uv * material.uvScaling);
    }

    float specularTextureIntensity = 1.0;

    if(material.hasSpecularTexture){
        specularTextureIntensity = texture(material.specularTexture, pass_uv * material.uvScaling).x;
    }

    vec3 fragNormal = pass_normal_view;
    if(material.faceSideNormalCorrection && !gl_FrontFacing){
        fragNormal = -fragNormal;
    }

    out_diffuse = vec4(diffuseTextureColor.rgb * material.diffuseColor, material.shininess);
    out_position = vec4(pass_position_view, 1.0); // Must be 1.0 on the alpha -> 0.0 = sky
    out_normal = vec4(fragNormal, material.specularIntensity * specularTextureIntensity);
}

是的,我知道,眼睛 space 的位置在 G-Buffer 中是无用的,因为您稍后可以从深度缓冲区中计算它。我只是暂时这样做,但这是暂时的。 此外,如果我的着色器中的任何内容已被弃用或有不良做法,如果您告诉我该怎么做,那就太好了!谢谢!

附加信息(我认为其中大部分无用):

  1. 相机: FOV = 70°,比率 = 16/9, = 0.0001, = 10
  2. OpenGL: 主要 = 4,次要 = 5,简介 = 核心
  3. 纹理: 内部格式 = GL_RGBA过滤器 = 各向异性,三线性
  4. 硬件: GPU = NVIDIA GeForce GTX 970,CPU = Interl(R) Core(TM) i7-4790K CPU @ 4.00GHz,内存 = 16.00 GB RAM(15.94 GB 可用),屏幕 = 1920 x 1080 @ 144Hz
  5. 驱动程序: GeForce Game Ready 驱动程序 V368.69(发布日期:2016 年 7 月 6 日)

这很可能是由于在光栅化(插值、透视校正)过程中产生的浮点不精确以及片段着色器中为获取正确纹理元素而进行的规范化所导致的。

但这也是 mipmap 的一个问题:为了计算使用哪个级别,检索相邻像素的 UV 以了解纹理在屏幕上是否被拉伸或压缩。由于不精确,相邻像素共享相同的 UV,因此它们之间的差异(或 'partial derivatives')为空。这使得 texture() 函数在那些相同的像素上采样最低的 mipmap 级别,从而产生不连续性。