【问题标题】:OpenGL Simple Shading, ArtifactsOpenGL 简单着色,工件
【发布时间】:2023-12-28 14:49:02
【问题描述】:

我一直在尝试实现一个简单的灯光/阴影系统,准确地说是一个没有镜面光的简单 Phong 照明系统。它基本上可以工作,除了它有一些(在我看来)令人讨厌的工件。

我的第一个想法是,这可能是纹理 mipmap 的问题,但禁用它们不起作用。我的下一个最佳猜测是着色器问题,但我似乎找不到错误。

有没有人遇到过类似的问题或想知道如何解决这个问题?

Image of the artifacts

顶点着色器:

#version 330 core

// Vertex shader
layout(location = 0) in vec3 vpos;
layout(location = 1) in vec2 vuv;
layout(location = 2) in vec3 vnormal;

out vec2 uv;        // UV coordinates
out vec3 normal;    // Normal in camera space
out vec3 pos;       // Position in camera space
out vec3 light[3];  // Vertex -> light vector in camera space

uniform mat4 mv;    // View * model matrix
uniform mat4 mvp;   // Proj * View * Model matrix
uniform mat3 nm;    // Normal matrix for transforming normals into c-space

void main() {
    // Pass uv coordinates
    uv = vuv;

    // Adjust normals
    normal = nm * vnormal;

    // Calculation of vertex in camera space
    pos = (mv * vec4(vpos, 1.0)).xyz;

    // Vector vertex -> light in camera space
    light[0] = (mv * vec4(0.0,0.3,0.0,1.0)).xyz - pos;
    light[1] = (mv * vec4(-6.0,0.3,0.0,1.0)).xyz - pos;
    light[2] = (mv * vec4(0.0,0.3,4.8,1.0)).xyz - pos;

    // Pass position after projection transformation
    gl_Position = mvp * vec4(vpos, 1.0);
}

片段着色器:

#version 330 core

// Fragment shader
layout(location = 0) out vec3 color;

in vec2 uv;     // UV coordinates
in vec3 normal;     // Normal in camera space
in vec3 pos;        // Position in camera space
in vec3 light[3];   // Vertex -> light vector in camera space

uniform sampler2D tex;
uniform float flicker;

void main() {
    vec3 n = normalize(normal);

    // Ambient
    color = 0.05 * texture(tex, uv).rgb;

    // Diffuse lights
    for (int i = 0; i < 3; i++) {
        l = normalize(light[i]);
        cos = clamp(dot(n,l), 0.0, 1.0);
        length = length(light[i]);
        color += 0.6 * texture(tex, uv).rgb * cos / pow(length, 2);
    }
}

【问题讨论】:

  • 几乎看起来像精度问题。您将纹理加载为什么格式?
  • 它似乎与纹理无关。我刚刚把整个房间涂成白色,但问题仍然存在。

标签: opengl glsl shader lighting artifacts


【解决方案1】:

正如第一条评论所说,您的颜色计算似乎使用的精度不足。尝试使用 mediump 或 highp 浮点数。

此外,length = length(light[i]); pow(length,2) 表达式效率很低,也可能是观察到的条带的来源;你应该改用dot(light[i],light[i])

【讨论】:

  • 感谢 dot(light[i],light[i]) 的建议!不幸的是,使用 highp 浮点数没有任何改变,问题仍然存在。
  • 你是否也在使用 highp 作为向量?
  • 是的,我试过在所有东西前面写 highp,顶点和片段着色器,只是为了确定。
  • 很奇怪,我完全没有想法。变种人也使用highp?如果您确实发现了错误,请发布更新!
  • 当然可以!是的,还有变化,一切。这真的让我很烦。此外,离光越远,效果越差(我尝试将 pow 或 dot(light[i],light[i]) 排除在等式之外,但它没有改变任何东西)。跨度>
【解决方案2】:

所以我找到了关于我的问题的信息,描述为“渐变条带”,还讨论了here。问题似乎出在我的纹理的性质上,因为只有“白色”纹理和真正的纹理大多是灰色/白色,并且在每个颜色通道使用 8 位时实际上有 256 级灰度。

解决方案是实现后处理抖动或使用更好的纹理。

【讨论】:

  • 您看到条带,但不是因为纹理位深度。如果您查看您在 Photoshop 中发布的屏幕截图,您可以看到每个波段不是像链接的帖子中那样分开一个灰度值,而是两个或三个。链接帖子中的渐变条带看起来明显不同,请注意它有多精细。除非您的纹理中有很多噪点(您是否只尝试了纯色,条纹看起来如何?),在这种情况下,它可能是色彩空间问题(线性与伽马校正),它不会看起来像是一个可能的解释。
  • 我仍然认为它是一些计算工件,甚至可能是除法,'... / pow ...'。您可以尝试预先计算 falloff = 1.0 / pow...,然后在最终计算中将其相乘而不是除法。
  • 我尝试过完全排除衰减。我用白色而不是纹理尝试过它,它给了我在链接中看到的确切的带。我拥有的最简单的片段着色器,除了光和法线向量的点积外,删除了所有内容,它仍然给了我条带。我求助于 OpenGL 论坛,也有人告诉我这只是乐队。
  • 一个谜,它是。您是否尝试过使用不同 GPU 的不同计算机?
  • 如果我能让你的程序在着色器生成器中运行,我会稍后再试,到目前为止我还没有成功运行它...