C++ 为什么在正向渲染灯光时会出现Z-fighting?

C++ 为什么在正向渲染灯光时会出现Z-fighting?,c++,opengl,glsl,shader,lighting,C++,Opengl,Glsl,Shader,Lighting,在我的OpenGL程序中,我注意到在正向渲染算法中灯光混合在一起的地方出现了黑色像素。起初,我忽略了它,直到当它在视觉上出现问题时,我切换窗口API(SDL到GLFW) 当我禁用GL_DEPTH_TEST时,黑色工件消失了,但对它们后面的灯光来说,事情变得透明了,所以这不是一个解决方案。(这就是我发现潜在问题的方式) 我不确定问题是什么,可能是深度缓冲区,但切换窗口API会增强工件,有什么帮助吗 当我移动相机时,图案会闪烁 在每个三角形中,黑线/黑点似乎是孤立的 这是我混合灯光的地方 // N

在我的OpenGL程序中,我注意到在正向渲染算法中灯光混合在一起的地方出现了黑色像素。起初,我忽略了它,直到当它在视觉上出现问题时,我切换窗口API(SDL到GLFW)

当我禁用GL_DEPTH_TEST时,黑色工件消失了,但对它们后面的灯光来说,事情变得透明了,所以这不是一个解决方案。(这就是我发现潜在问题的方式)

我不确定问题是什么,可能是深度缓冲区,但切换窗口API会增强工件,有什么帮助吗

当我移动相机时,图案会闪烁

在每个三角形中,黑线/黑点似乎是孤立的

这是我混合灯光的地方

// Note: I wrapped OpenGL calls into wrapper functions but the naming convenction is still the same
gl::Clear(gl::e_ColorBufferBit | gl::e_DepthBufferBit);

mesh->Render(m_forward_ambient);
gl::Enable(gl::e_Blend);
gl::SetBlendFunc(gl::e_One, gl::e_One); // Additive blending
gl::SetDepthMask(false); // No need to write to depth buffer
gl::SetDepthFunc(gl::e_Equal); // Only draw fragments of equal depths (ignore fragments behind basically)
{
    for (word i = 0; i < m_lights.Length(); ++i)
    {
        m_active_light = m_lights[i];
        mesh->Render(m_active_light->shader); // Shaders use active light
    }
}
gl::SetDepthFunc(gl::e_Lequal); // Restore default state
gl::SetDepthMask(true);
gl::Disable(gl::e_Blend);

您没有将
gl_Position
顶点着色器输出声明为
invariant
,因此即使在两个过程中使用完全相同的公式和按位完全相同的输入,也不能保证着色器获得完全相同的结果。您应该向所有过程中的所有着色器添加适当的设置。

请提供适当的设置。还有很多事情是未知的,尤其是所有与顶点变换相关的PAT——在我看来,这似乎是最有可能出现问题的地方。哇。可能就是这样。我不是一个尝试它的家,但我想我学到了一个新的着色器信息。
// Vertex
void main()
{
    // pv_matrix is projection and camera, ml_matrix is model transform
    gl_Position = pv_matrix * ml_matrix * vec4(pos, 1);
    f_pos = (ml_matrix * vec4(pos, 1)).xyz;
    f_nrm = (ml_matrix * vec4(normalize(nrm), 0)).xyz;
    f_txc = txc;
}
// Fragment
struct Light
{
    vec3 color;
    float intensity;
};
struct Attenuation
{
    float constant;
    float linear;
    float exponent;
};
struct PointLight
{
    Light light;
    Attenuation atten;
    vec3 position;
    float range;
};
struct SpotLight
{
    PointLight plight;
    vec3 direction;
    float cutoff;
};
vec4 CalculateLight(Light light, vec3 direction, vec3 normal)
{
    float diffuse_factor = dot(normal, -direction);
    vec4 diffuse_color = vec4(0, 0, 0, 0);
    vec4 specular_color = vec4(0, 0, 0, 0);

    if (diffuse_factor > 0)
        diffuse_color = vec4(light.color, 1) * light.intensity * diffuse_factor;

    vec3 direction_to_eye = normalize(eye_pos - f_pos); // eye_pos is uniform for camera pos, f_pos is (position) attribute sent from vertex shader
    vec3 reflect_direction = normalize(reflect(direction, normal));
    float specular_factor = dot(reflect_direction, direction_to_eye); // specular calculations
    if (specular_factor > 0)
    {
        specular_factor = pow(specular_factor, specular_power);
        specular_color = vec4(light.color, 1) * specular_intensity * specular_factor;
    }

    return diffuse_color + specular_color;
}

vec4 CalculatePointLight(PointLight plight, vec3 normal)
{
    vec3 light_direction = f_pos - plight.position; 
    float distance = length(light_direction); 

    if (distance > plight.range)
        return vec4(0, 0, 0, 0);

    light_direction = normalize(light_direction);
    vec4 color = CalculateLight(plight.light, light_direction, normal);

    float a = plight.atten.constant + (plight.atten.linear * distance) + (plight.atten.exponent * (distance * distance)) + 0.0001;

    return color / a;
}

vec4 CalculateSpotLight(SpotLight slight, vec3 normal)
{
    vec3 light_direction = normalize(f_pos - slight.plight.position);
    float spot_factor = dot(light_direction, slight.direction);

    vec4 color = vec4(0, 0, 0, 0);
    if (spot_factor > slight.cutoff)
        color = CalculatePointLight(slight.plight, normal) * (1.0 - ((1.0 - spot_factor) / (1.0 - slight.cutoff))); 

    return color; 
}

uniform SpotLight spot_light;

void main()
{
    FragColor = CalculateSpotLight(spot_light, f_nrm); // f_nrm is a (normal) attribute sent from vertex shader
}