如何返回采样像素的掩码



我正在使用GitHub上的一个程序(此处(,使用OpenGL将等矩形图像(360度图像(转换为透视图(视口(。为此,光线跟踪方法用于找到单位球体上碎片点的交点,稍后将使用该信息从等矩形图像中采样所需像素,并将其投影到透视图上。一切都很好,但现在随着投影结果,我需要程序还给我一个掩码图像(类型为无符号字节,大小与矩形图像相同(,它表示从矩形图像中采样的像素。

如何更改片段着色器以在渲染帧缓冲区上的视图的同时返回此无符号字节掩码(0表示非采样,255表示采样像素(?

更具体地说,我当前的片段着色器如下所示:

const float pi = 3.141592653589793;
varying vec3 planePoints;
uniform sampler2D tex;
void main()
{
vec2 equirectangularTexturePos;
vec3 spherepos = normalize(planePoints);
equirectangularTexturePos.x = (atan(spherepos.y, -spherepos.x)+pi)/(2.0*pi);
equirectangularTexturePos.y = acos(spherepos.z)/(pi);
gl_FragColor = texture2D(tex, equirectangularTexturePos);
}

我想要的是将类似于以下内容添加到我的碎片着色器中:

texture2D(mask, equirectangularTexturePos) = 255;

我写这篇文章只是为了详细说明一个可能的解决方案,我试图在上面的评论中使用Image Load Store来提示这个解决方案。首先,您需要创建一个与等矩形纹理尺寸相同的新纹理(可以使用GL_R8作为内部格式(。您可以使用glTexImage2D或glTexStorage2D执行此操作。

然后,您需要在着色器中声明一个图像绑定点,并将遮罩图像的第一级绑定到该图像绑定点。然后,在着色器中,从原始颜色纹理采样时,还将使用imageStore()函数写入该纹理单元位置的遮罩纹理。注意:纹素的位置在实际的纹素中,而不是在整个纹理维度的一小部分中!

对于第一个近似,我们只使用原始样本位置的截断整数坐标(用于texture2D调用(。实际上,由于使用GL_LINEAR作为过滤函数,因此应该计算最近的4个texel并写入这些texel。请参阅PDF第150页,共150页https://www.khronos.org/registry/OpenGL/specs/gl/glspec13.pdf以知道GL使用哪种算法来确定用于线性滤波的四个纹素。

因此,着色器的某些部分将看起来像这样:

#extension GL_ARB_shader_image_load_store : enable
layout(binding = 0, r8) writeonly uniform image2D maskImage;
...
ivec2 texel = ivec2(equirectangularTexturePos * textureSize(tex, 0));
imageStore(maskImage, texel, vec4(1.0, 0.0, 0.0, 0.0));

为了将图像绑定到图像绑定点,您可以在主机程序中使用以下内容:

glBindImageTexture(0, maskTex, 0, false, 0, GL_WRITE_ONLY, GL_R8);

此外,在运行着色器之前,不要忘记清除纹理。着色器运行并填充遮罩纹理的0级访问的纹素后,需要添加适当的同步屏障,以便从该纹理进行的进一步GL调用可以看到更新的纹理值。您可以通过:

glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

现在,您可以以任何方式使用该纹理并从中获取源,例如与另一个着色器一起使用。

最新更新