【问题标题】:How to fix improperly distributed lighting projected onto a model in OpenGL?如何修复在 OpenGL 中投影到模型上的不正确分布的照明?
【发布时间】:2022-02-21 22:22:00
【问题描述】:

我一直在尝试实现 Blinn-Phong 光照模型,通过 Assimp(github link) 将光照投射到导入的 Wavefront OBJ 模型上。

模型似乎已正确加载,但是,在模型中间附近似乎有一个点灯光似乎被“切断”了。

已启用和未启用照明的导入模型的图像。

如上图左侧所示,模型中间有一个区域,光线有效地“分裂”,这不是预期的。可以看出,存在一种差异,即朝向光源的一侧看起来比正常情况更亮,而远离光源的一侧看起来比正常情况更暗,而这两个方面之间没有任何缓和。

我认为我在片段着色器中实现光照模型的方式可能有问题,但我不能确定为什么会发生这种情况。


顶点着色器:

#version 330 core

layout (location = 0) in vec3 vertPos;
layout (location = 1) in vec3 vertNormal;
layout (location = 2) in vec2 vertTexCoords;

out vec3 fragPos;
out vec3 fragNormal;
out vec2 fragTexCoords;

uniform mat4 proj, view, model;
uniform mat3 normalMat;

void main() {
    fragPos = vec3(model * vec4(vertPos, 1));
    gl_Position = proj * view * vec4(fragPos, 1);
    fragTexCoords = vertTexCoords;
    fragNormal = normalMat * vertNormal;
}

片段着色器:

#version 330 core

in vec3 fragPos;
in vec3 fragNormal;
in vec2 fragTexCoords;

out vec4 FragColor;

const int noOfDiffuseMaps = 1;
const int noOfSpecularMaps = 1;

struct Material {
    sampler2D diffuseMaps[noOfDiffuseMaps], specularMaps[noOfSpecularMaps];
    float shininess;
};

struct Light {
    vec3 direction;
    vec3 ambient, diffuse, specular;
};

uniform Material material;
uniform Light light;

uniform vec3 viewPos;

const float pi = 3.14159265;

uniform float gamma = 2.2;

float near = 0.1;
float far = 100;
  
float LinearizeDepth(float depth) 
{
    float z = depth * 2 - 1;
    return (2 * near * far) / (far + near - z * (far - near));  
}

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

    vec3 calculatedColor = vec3(0);

    for (int i = 0; i < noOfDiffuseMaps; i++) {
        vec3 diffuseTexel = texture(material.diffuseMaps[i], fragTexCoords).rgb;

        // Ambient lighting
        vec3 ambient = diffuseTexel * light.ambient;
    
        // Diffuse lighting
        float diff = max(dot(light.direction, normal), 0);
        vec3 diffuse = diffuseTexel * light.diffuse * diff;

        calculatedColor += ambient + diffuse;
    }
    
    for (int i = 0; i < noOfSpecularMaps; i++) {
        vec3 specularTexel = texture(material.specularMaps[0], fragTexCoords).rgb;
        vec3 viewDir = normalize(viewPos - fragPos);
        vec3 halfWayDir = normalize(viewDir + light.direction);
        float energyConservation = (8 + material.shininess) / (8 * pi);

        // Specular lighting
        float spec = pow(max(dot(halfWayDir, normal), 0), material.shininess);
        vec3 specular = specularTexel * light.specular * spec * energyConservation;

        calculatedColor += specular;
    }

    float depthColor = 1 - LinearizeDepth(gl_FragCoord.z) / far;
    FragColor = vec4(pow(calculatedColor, vec3(1 / gamma)) * depthColor, 1);
}

【问题讨论】:

  • 模型中两个三角形带/扇形/网格之间连接处的顶点法线不一致?

标签: c++ opengl glsl shader lighting


【解决方案1】:

确保你的纹理和颜色也是线性的(这是一个简单的 pow 2.2),因为你在最后进行伽马编码。

另请注意,预计会有一个苛刻的终结者。

http://filmicworlds.com/blog/linear-space-lighting-i-e-gamma/

除此之外,如果您预计会有柔和的衰减,它必须来自区域光。为此,您可以实施环绕照明或区域照明。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 2022-12-17
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    相关资源
    最近更新 更多