用于多灯的 GLSL 照明不起作用?

GLSL Lighting for multiple light not working?

我正在尝试渲染多个定向光源和多个点光源,但它只渲染光阵列中的最后一个定向光源和最后一个点光源。我检查了所有用于照明的数据是否已正确发送到 glsl 片段着色器,但它似乎不起作用。 NUM_DIR_LIGHTS-1NUM_POINT_LIGHTS-1 被动态插入片段着色器并且也有正确的值。

片段颜色输出的计算:

vec4 ambient = vec4(0.0);
vec4 diffuse = vec4(0.0);
vec4 specular = vec4(0.0);
                    
vec4 diffuseTexel = texture(u_Material.DiffuseMap, v_TexCoord);
vec4 specularTexel = texture(u_Material.SpecularMap, v_TexCoord);
vec4 normalTexel = texture(u_Material.NormalMap, v_TexCoord);

vec3 viewDir = normalize(u_CameraPosition - v_Position);
                    
float dirShadow = 0.0;

// calculate material for all directional lights
vec3 normalFromMap = normalize(transpose(inverse(v_ModelRotation)) * normalTexel.xyz);
vec3 normalizedNormal = normalize(v_Normal);
for (int i = 0; i < NUM_DIR_LIGHTS-1; i++)
{
    vec3 lightDir = normalize(-u_DirectionalLights[i].Direction);

    // if material is mapped then apply lighting with lighting maps
    if (u_Material.IsMapped)
    {
        // ambient lighting
        ambient += vec4(u_DirectionalLights[i].Color * u_DirectionalLights[i].Intensity * diffuseTexel.rgb, 1.0);

        // diffuse lighting
        float diff = max(dot(normalFromMap, lightDir), 0.0);
        diffuse += vec4(u_DirectionalLights[i].Color * diff * diffuseTexel.rgb, 1.0);

        // specular lighting
        vec3 reflectDir = reflect(-lightDir, normalFromMap);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
        specular += vec4(u_DirectionalLights[i].Color * spec * specularTexel.rgb, 1.0);

        dirShadow += calcDirLightShadow(i, lightDir, normalTexel.xyz);
    }
    else
    {
        // ambient lighting for material
        ambient += vec4(u_DirectionalLights[i].Color * (u_Material.Ambient + u_DirectionalLights[i].Intensity * u_Material.Diffuse), 1.0);

        // diffuse lighting for material
        float diff = max(dot(normalizedNormal, lightDir), 0.0);
        diffuse += vec4(u_DirectionalLights[i].Color * u_DirectionalLights[i].Intensity * diff * u_Material.Diffuse, 1.0);

        // specular lighting for material
        vec3 reflectDir = reflect(-lightDir, normalizedNormal);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
        specular += vec4(u_DirectionalLights[i].Color * u_DirectionalLights[i].Intensity * spec * u_Material.Specular, 1.0);
                        
        dirShadow += calcDirLightShadow(i, lightDir, v_Normal);
      }
}
                    
// calculate material for all point lights
vec3 pointAmbient = vec3(0.0);
vec3 pointDiffuse = vec3(0.0);
vec3 pointSpecular = vec3(0.0);
for (int i = 0; i < NUM_POINT_LIGHTS-1; i++)
{
    // if material is mapped then apply lighting with lighting maps
    if (u_Material.IsMapped)
    {
        // ambient lighting
        pointAmbient += u_PointLights[i].Color * u_PointLights[i].Intensity * diffuseTexel.rgb;

        // diffuse lighting
        vec3 lightDir = normalize(u_PointLights[i].Position - v_Position);
        float diff = max(dot(normalFromMap, lightDir), 0.0);
        pointDiffuse += u_PointLights[i].Color * diff * diffuseTexel.rgb;

        // specular lighting
        vec3 reflectDir = reflect(-lightDir, normalFromMap);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
        pointSpecular += u_PointLights[i].Color * spec * specularTexel.rgb;
    }
    else
    {
        // ambient lighting for material
        pointAmbient += u_PointLights[i].Color * (u_Material.Ambient + u_PointLights[i].Intensity * u_Material.Diffuse);

        // diffuse lighting for material
        vec3 lightDir = normalize(u_PointLights[i].Position - v_Position);
        float diff = max(dot(normalizedNormal, lightDir), 0.0);
        pointDiffuse += u_PointLights[i].Color * u_PointLights[i].Intensity * diff * u_Material.Diffuse;

        // specular lighting for material
        vec3 reflectDir = reflect(-lightDir, normalizedNormal);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
        pointSpecular += u_PointLights[i].Color * u_PointLights[i].Intensity * spec * u_Material.Specular;
     }

    // calculate attenuation
    float distance = length(u_PointLights[i].Position - v_Position);
    float attenuation = 1.0f / (u_PointLights[i].Constant + u_PointLights[i].Linear * 
    distance + u_PointLights[i].Quadratic * (distance * distance));

    // include attenuation in lighting
    pointAmbient *= attenuation;
    pointDiffuse *= attenuation;
    pointSpecular *= attenuation;
}

// calculate directional lighting with shadow
vec3 lighting = vec3(ambient + (1.0 - dirShadow) * (diffuse + specular));

return vec4(lighting + pointAmbient + pointDiffuse + pointSpecular, 1.0);

我希望有人能理解为什么它没有渲染所有灯光。

问题是

for (int i = 0; i < NUM_POINT_LIGHTS-1; i++)
{
    // [...]

    pointAmbient *= attenuation;
    pointDiffuse *= attenuation; 
    pointSpecular *= attenuation;
}

此处光源的总和乘以循环中遍历光源的衰减。这意味着已经添加的光源乘以后面光源的衰减。已经添加的光源发出的光会随着每添加一个新光源而变得越来越弱。

可能的解决方案:

vec3 pointAmbient = vec3(0.0);
vec3 pointDiffuse = vec3(0.0);
vec3 pointSpecular = vec3(0.0);
for (int i = 0; i < NUM_POINT_LIGHTS-1; i++)
{
    // calculate attenuation
    float distance = length(u_PointLights[i].Position - v_Position);
    float attenuation = 1.0f / (u_PointLights[i].Constant + u_PointLights[i].Linear * 
        distance + u_PointLights[i].Quadratic * (distance * distance));

    // if material is mapped then apply lighting with lighting maps
    if (u_Material.IsMapped)
    {
        // ambient lighting
        pointAmbient += attenuation * u_PointLights[i].Color * u_PointLights[i].Intensity * diffuseTexel.rgb;

        // diffuse lighting
        vec3 lightDir = normalize(u_PointLights[i].Position - v_Position);
        float diff = max(dot(normalFromMap, lightDir), 0.0);
        pointDiffuse += attenuation * u_PointLights[i].Color * diff * diffuseTexel.rgb;

        // specular lighting
        vec3 reflectDir = reflect(-lightDir, normalFromMap);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
        pointSpecular += attenuation * u_PointLights[i].Color * spec * specularTexel.rgb;
    }
    else
    {
        // ambient lighting for material
        pointAmbient += attenuation * u_PointLights[i].Color * (u_Material.Ambient + u_PointLights[i].Intensity * u_Material.Diffuse);

        // diffuse lighting for material
        vec3 lightDir = normalize(u_PointLights[i].Position - v_Position);
        float diff = max(dot(normalizedNormal, lightDir), 0.0);
        pointDiffuse += attenuation * u_PointLights[i].Color * u_PointLights[i].Intensity * diff * u_Material.Diffuse;

        // specular lighting for material
        vec3 reflectDir = reflect(-lightDir, normalizedNormal);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.Shininess);
        pointSpecular += attenuation * u_PointLights[i].Color * u_PointLights[i].Intensity * spec * u_Material.Specular;
     }
}