Opengl 通过SSBO输出每个片段的数据

Opengl 通过SSBO输出每个片段的数据,opengl,glsl,shader,fragment-shader,Opengl,Glsl,Shader,Fragment Shader,我需要在着色器中为每个片段输出24个索引。我已经达到了渲染目标的最大数量,因为我正在为我的gbuffer使用四个其他渲染目标。所以我试着用SSBO输出数据,用像素的gl_FragCoord索引它。问题是,它需要深度正确。因此,我尝试在中使用layoutearly_fragment_测试;观察指数。我现在可以在一些点上看到奇怪的每像素错误,看起来下面三角形的索引正在通过,当我将相机移近这些点时,它会停止。 我仔细检查了ssbo的索引,它是正确的+整个三角形的索引应该是相同的,但闪烁是每像素。所以我

我需要在着色器中为每个片段输出24个索引。我已经达到了渲染目标的最大数量,因为我正在为我的gbuffer使用四个其他渲染目标。所以我试着用SSBO输出数据,用像素的gl_FragCoord索引它。问题是,它需要深度正确。因此,我尝试在中使用layoutearly_fragment_测试;观察指数。我现在可以在一些点上看到奇怪的每像素错误,看起来下面三角形的索引正在通过,当我将相机移近这些点时,它会停止。 我仔细检查了ssbo的索引,它是正确的+整个三角形的索引应该是相同的,但闪烁是每像素。所以我认为深度测试只适用于光栅化的每像素输出,而不适用于整个片段着色器代码。这可能是问题所在,还是有人知道深度测试是否应该停止对碎片的整个处理?如果不是这样,即使是单独的深度预传球也帮不了我

以下是片段着色器示例:

#version 440 core

layout(early_fragment_tests) in;

layout(location = 0) uniform sampler2D texSampler;

#include "../Header/MaterialData.glslh"
#include "../Header/CameraUBO.glslh"

layout(location = 3) uniform uint screenWidth;//horizontal screen resolution in pixel

layout(location = 0) out vec4 fsout_color;
layout(location = 1) out vec4 fsout_normal;
layout(location = 2) out vec4 fsout_material;

coherent layout(std430, binding = 3) buffer frameCacheIndexBuffer
{
    uvec4 globalCachesIndices[];
};

in vec3 gsout_normal;
in vec2 gsout_texCoord;
flat in uvec4 gsout_cacheIndices[6];
flat in uint gsout_instanceIndex;

void main()
{
    uint frameBufferIndex = 6 * (uint(gl_FragCoord.x) + uint(gl_FragCoord.y) * screenWidth);
    for(uint i = 0; i < 6; i++)
    {
        globalCachesIndices[frameBufferIndex + i] = gsout_cacheIndices[i];//only the closest fragment should output
    }

    fsout_normal = vec4(gsout_normal * 0.5f + 0.5f, 0);
    fsout_color = vec4(texture(texSampler, gsout_texCoord));

    MaterialData thisMaterial = material[materialIndex[gsout_instanceIndex]];

    fsout_material = vec4(thisMaterial.diffuseStrength, 
                        thisMaterial.specularStrength, 
                        thisMaterial.ambientStrength, 
                        thisMaterial.specularExponent);
}

你的着色器有问题。我试图跟踪frameBufferIndex的计算,因为我认为您在多个着色器调用中覆盖了SSBO中的相同索引,但宽度未定义。我怀疑它在你使用include指令的一个文件中。另外,如果你在多个绘图调用中执行此操作,你可能需要一个内存屏障。哦,我的错,你是对的,它位于摄像头中,代表以像素为单位的水平屏幕分辨率。我将为width变量添加一个解释。覆盖这些值也是我的第一个想法,但我仔细检查了frameBufferIndex,它看起来是正确的。是的,我在着色器调用之间使用glMemoryBarrier,但它在某些像素上仍然闪烁。您能否澄清您的意思,以便我认为深度测试仅适用于光栅化的每像素输出,而不适用于整个片段着色器代码。?片段着色器仅在光栅化片段上运行。由于三角形的处理顺序不能保证与绘制顺序相匹配,因此即使进行深度排序,也可以多次写入相同的内存,但早期的深度测试将使其成为最后一次写入。该行为适用于在同一glDraw*调用中绘制的三角形,以捕获其他与顺序相关的问题。使用了内存屏障。对于光栅化输出,我指的是将保存到纹理中的数据,如颜色、材质和法线。如果只保证光栅化每纹理输出的深度正确,这就可以解释我的错误。我的意思是,gpu仍然可以处理fragmen,因为它的并行行为,并且只有在每个纹理输出不是最接近的深度值时才转储它。我将再次检查屏障,以确保它们按预期工作。我也在使用glMultiDraw*可能glMemoryBarrier在那些调用的着色器调用之间不起作用?但即使是这样,我已经用单个网格对其进行了测试,它也会导致闪烁。