【问题标题】:Normal mapping working incorrectly, weird half-light effect法线贴图工作不正确,奇怪的半光效果
【发布时间】:2020-02-23 17:17:04
【问题描述】:

我们正在尝试在我们的 2D 游戏引擎中实现法线贴图并获得奇怪的效果。 如果正常是这样手动设置的 vec3 Normal = vec3(0.0, 0.0, 1.0) light 工作正常,但是我们没有得到我们想要通过法线贴图实现的“深度”效果: 但是,如果我们使用法线贴图纹理得到法线:vec3 Normal = texture(NormalMap, TexCoord).rgb 它根本不起作用。不应该被照亮的被照亮,反之亦然(例如砖块之间的缝隙)。除此之外,纹理的底部(或顶部,取决于光线的位置)一侧有一个深色区域。 虽然法线贴图本身的纹理看起来不错: 这是我们的片段着色器:

#version 330 core
layout (location = 0) out vec4 FragColor;

in vec2 TexCoord;
in vec2 FragPos;

uniform sampler2D OurTexture;
uniform sampler2D NormalMap;

struct point_light
{
    vec3 Position;
    vec3 Color;
};

uniform point_light Light;

void main()
{
    vec4 Color = texture(OurTexture, TexCoord);
    vec3 Normal = texture(NormalMap, TexCoord).rgb;

    if (Color.a < 0.1)
        discard;

    vec3 LightDir = vec3(Light.Position.xy - FragPos, Light.Position.z);

    float D = length(LightDir);

    vec3 L = normalize(LightDir);
    Normal = normalize(Normal * 2.0 - 1.0);

    vec3 Diffuse = Light.Color * max(dot(Normal, L), 0);
    vec3 Ambient = vec3(0.3, 0.3, 0.3);

    vec3 Falloff = vec3(1, 0, 0);

    float Attenuation = 1.0 /(Falloff.x + Falloff.y*D + Falloff.z*D*D);
    vec3 Intensity = (Ambient + Diffuse) * Attenuation;

    FragColor = Color * vec4(Intensity, 1);
}

还有顶点:

#version 330 core
layout (location = 0) in vec2 aPosition;
layout (location = 1) in vec2 aTexCoord;

uniform mat4 Transform;
uniform mat4 ViewProjection;

out vec2 FragPos;
out vec2 TexCoord;

void main()
{
    gl_Position = ViewProjection * Transform * vec4(aPosition, 0.0, 1.0);
    TexCoord = aTexCoord;
    FragPos = vec2(Transform * vec4(aPosition, 0.0, 1.0));
}

我对此进行了谷歌搜索,发现一些人得到了相同的结果,但他们的问题仍未得到解答。 知道是什么原因吗?

【问题讨论】:

  • Normal = normalize(Normal * 2.0 - 1.0); 是什么意思?是否允许从 Vec3 中减去标量?把这行注释掉会有什么效果?
  • @Rixment:是的。虽然法线向量是几何实体,而纹理通常仅用于颜色信息。在这里,我们通过将采样的法线颜色从 [0,1] 重新映射回 [-1,1] 来反转将法线映射到 RGB 颜色的过程,然后将采样的法线向量用于即将进行的照明计算。
  • @Rixment 请不要混淆其他用户。当然GLSL中是允许的
  • @Rabbid76 我一直认为这是不允许的,这就是我问的原因。如果我可以问一下,这个操作的结果是什么?
  • @Rixment 在 glsl 中的所有操作都是按组件处理的。

标签: c++ glsl rendering light normals


【解决方案1】:

法线贴图使用什么纹理格式? SRGB、SNORM 等?这可能是问题所在。试试 UNORM。

此外,由于您没有使用切线空间,因此请确保平面的 Z 轴与法线的 Z 轴对齐。 OGL 也以相反的方向读取 Y,因此您需要翻转从法线贴图读取的法线的 Y 坐标。或者,您可以使用反向 Y 法线贴图(绿色向下)。

【讨论】:

  • 我完全重写了纹理加载器,现在它可以正常工作了。我仍然无法理解错误的纹理格式如何产生如此奇怪的效果。此外,纹理本身看起来不错,但光照计算是错误的。所以无论如何,将格式从 SRGB/SRGBA 更改为 RGB/RGBA 解决了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-09
  • 2020-11-03
  • 2022-09-23
  • 2019-12-23
  • 2015-10-24
相关资源
最近更新 更多