opengl LWJGL 3中的镜面反射照明不工作[Phong着色]

b5buobof  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(113)

我在我的引擎中实现了照明。但是有一些问题,物体没有正确点亮

镜面反射照明根本不起作用
下面是顶点着色器:

#version 330

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 tex_coords;
layout (location = 2) in vec3 normals;

uniform mat4 projectionMatrix;
uniform mat4 worldMatrix;
uniform mat4 viewMatrix;

out vec2 coords;
out vec3 vertexNormals;
out vec3 vertexPos;

void main() {
    vec4 mVerPos = worldMatrix * vec4(position, 1.0);
    gl_Position = projectionMatrix * viewMatrix * worldMatrix * vec4(position, 1.0);
    coords = tex_coords;
    vertexNormals = normalize(worldMatrix * vec4(normals, 0.0)).xyz;
    vertexPos = mVerPos.xyz;
}

字符串
以下是片段着色器:

#version 330

struct Material {
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    int hasTexture;
    float reflectance;
};

struct PointLight {
    vec3 color;
    vec3 position;
    float intensity;
    float constant;
    float linear;
    float exponent;
};

struct DirLight {
    vec3 position;
    vec3 color;
    float intensity;
};

out vec4 fragColor;

in vec2 coords;
in vec3 vertexNormals;
in vec3 vertexPos;

uniform sampler2D sampler;
uniform vec3 ambientColor;
uniform Material material;
uniform PointLight pointLight;
uniform float specularPower;
uniform DirLight dirLight;

vec4 ambientC;
vec4 diffuseC;
vec4 specularC;

void setUpColor(Material material, vec2 coords) {
    if (material.hasTexture == 1) {
        ambientC = texture(sampler, coords);
        diffuseC = ambientC;
        specularC = ambientC;
    }
    else {
        ambientC = material.ambient;
        diffuseC = material.diffuse;
        specularC = material.specular;
    }
}

vec4 calcLightColor(vec3 lightColor, float lightIntensity, vec3 position, vec3 to_light_dir, vec3 normal) {
    vec4 diffuseColour = vec4(0, 0, 0, 0);
    vec4 specColour = vec4(0, 0, 0, 0);

    // Diffuse Light
    float diffuseFactor = max(dot(normal, to_light_dir ), 0.0);
    diffuseColour = diffuseC * vec4(lightColor, 1.0) * lightIntensity * diffuseFactor;

    // Specular Light
    vec3 camera_direction = normalize(-position);
    vec3 from_light_dir = -to_light_dir;
    vec3 reflected_light = normalize(reflect(from_light_dir, normal));
    float specularFactor = max(dot(camera_direction, reflected_light), 0.0);
    specularFactor = pow(specularFactor, specularPower);
    specColour = specularC * lightIntensity * specularFactor * material.reflectance * vec4(lightColor, 1.0);
    
    return (diffuseColour + specColour);
};

vec4 calcPointLight(PointLight light, vec3 position, vec3 normal)
{
    vec3 light_direction = light.position - position;
    vec3 to_light_source  = normalize(light_direction);
    vec4 lightColor = calcLightColor(light.color, light.intensity, position, to_light_source, normal);

    // Attenuation
    float distance = length(light_direction);
    float attenuationInv = light.constant + light.linear * distance +
        light.exponent * distance * distance;
    return lightColor / attenuationInv;
}

vec4 calcDirLight(DirLight light, vec3 position, vec3 normal) {
    return calcLightColor(light.color, light.intensity, position, normalize(light.position), normal);
}

void main() {

    setUpColor(material, coords);
    vec4 diffuseSpecularComp = calcDirLight(dirLight, vertexPos, vertexNormals);
    diffuseSpecularComp += calcPointLight(pointLight, vertexPos, vertexNormals);
    fragColor = ambientC * vec4(ambientColor, 1) + diffuseSpecularComp;
    
}


下面是源代码:https://www.dropbox.com/scl/fo/hwlnz913jm6c9xli2dsb6/h?dl=0&rlkey=b2zj0w6kttwu3b1di9rejwnq3
当我把float diffuseFactor = max(dot(normal, to_light_dir ), 0.0);float specularFactor = max(dot(camera_direction, reflected_light), 0.0);处的零值改变为大于0.1的值时,我得到了

,但高光根本不起作用。

w7t8yxp5

w7t8yxp51#

你的代码中有几个问题,但我不完全确定是哪个原因导致了这个问题。

问题

  • 在顶点着色器中,您没有正确计算vertexNormals。在您的特定情况下,这不应该是一个问题,因为看起来您没有不均匀地缩放网格,但值得一提的是,这是一个常见的错误。将对象空间法线与世界矩阵相乘,但应将其与世界矩阵的逆转置相乘。
  • 在片段着色器中,您直接使用vertexNormals,但它不正确。虽然你在顶点着色器中规范化了法线,但是片段着色器并没有得到那个特定的向量。它得到3 vertexNormals的线性插值(基本上是加权平均),结果不一定是归一化的。所以你也应该在片段着色器中将其规格化。
  • setUpColor函数中,为什么给ambientCdiffuseCspecularC赋值相同?通常,这些有不同的纹理,但至少对于漫反射和镜面反射。

其他随机观察

  • 在顶点着色器中,您将position乘以worldMatrix两次,但为什么?这看起来像是浪费了性能(也许编译器优化了它)。
  • DirLight结构体中,您有一个position成员,但平行光没有位置,它们只有方向。我看到你从位置计算方向,但这似乎不寻常。
  • 同样,摄影机始终位于原点,平行光的方向始终指向原点。如果是故意的,没关系,只是看起来不寻常。
  • Material结构体(以及其他地方)中,您使用vec4 s而不是vec3 s,但我猜,最后一个组件总是1。这是浪费内存,你可以在main的末尾设置alpha值为1.0f

Joey de弗里斯有amazing tutorials, including the Phong shading(使用C++)。在 * 最后一件事 * 一节中,他还解释了为什么使用逆转置矩阵来变换法线很重要。

相关问题