如何返回采样像素的掩码

时间:2018-11-01 14:04:15

标签: opengl 360-panorama

我正在使用GitHub(here)上可用的程序,以使用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;

1 个答案:

答案 0 :(得分:0)

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

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

对于第一个近似值,我们只使用原始样本位置的截断整数坐标(用于texture2D调用)。实际上,由于您使用GL_LINEAR作为过滤功能,因此您应该计算最接近的4个纹理像素并将其写入。请参阅https://www.khronos.org/registry/OpenGL/specs/gl/glspec13.pdf的PDF页面150,了解GL使用哪种算法确定用于LINEAR滤波的四个纹理像素。

因此,着色器的一部分将如下所示:

#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);

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