如何使用多重采样帧缓冲在OpenGL中拾取几何?

时间:2015-05-23 19:51:04

标签: opengl shader multisampling mouse-picking

(编辑)我使用framebuffer完成了几何拾取工作。我的目标是在一次绘制调用中绘制巨大的场景,但我需要绘制到多重采样颜色纹理附件 (GL_COLOR_ATTACHMENT0)并绘制到(eddited)非多重采样纹理附件 (GL_COLOR_ATTACHMENT1)。问题是如果我使用多重采样纹理来挑选,由于多次采样,拾取已被破坏。

我将几何ID写入片段着色器,如下所示:

//...

// Given geometry id
uniform int in_object_id;

// Drawed to screen (GL_COLOR_ATTACHMENT0)
out vec4 out_frag_color0;

// Drawed to pick texture (GL_COLOR_ATTACHMENT1)
out vec4 out_frag_color1;

// ...

void main() {

    out_frag_color0 = ...; // Calculating lighting and other stuff

    //...

    const int max_byte1 = 256;
    const int max_byte2 = 65536;
    const float fmax_byte = 255.0;

    int a1 = in_object_id % max_byte1;
    int a2 = (in_object_id / max_byte1) % max_byte1;
    int a3 = (in_object_id / max_byte2) % max_byte1;

    //out_frag_color0 = vec4(a3 / fmax_byte, a2 / fmax_byte, a1 / fmax_byte, 1);
    out_frag_color1 = vec4(a3 / fmax_byte, a2 / fmax_byte, a1 / fmax_byte, 1);
}

(该代码的一点是使用RGB空间作为商店几何ID,然后将其读回用于更改立方体的颜色)

当我将光标向左移动一个像素时会发生这种情况:

enter image description here

由于立方体像素的alpha值:

enter image description here

没有多重采样效果很好。但是多重采样会使我的输出颜色与几何id相乘然后会被破坏,因此它会选择具有乘法值的随机多维数据集。

(编辑)我无法将一个多重采样纹理目标附加到color0,而非多重采样纹理目标附加到color1,它不受支持。我怎么能在一次抽奖中做到这一点?

enter image description here

多重采样不是我的朋友我不确定如果我理解得很好(整个帧缓冲)。无论如何,这种选择几何形状的方式对我来说看起来很糟糕(我的意思是计算ID到颜色)。我做得好吗?如何解决多重采样问题?还有更好的办法吗?

PS:抱歉英语很低。 :)

感谢。

2 个答案:

答案 0 :(得分:2)

您无法在单次绘制调用中执行多重采样和非多重采样渲染。

正如您已经发现的那样,不支持在FBO中使用两个颜色目标,其中只有一个是多重采样的。从规范中的“Framebuffer Completeness”部分:

  

对于所有附加的渲染缓冲区,RENDERBUFFER_SAMPLES的值相同; TEXTURE_SAMPLES的值对于所有附加纹理都是相同的;并且,如果附加的图像是渲染缓冲区和纹理的混合,则RENDERBUFFER_SAMPLES的值与TEXTURE_SAMPLES的值匹配。

您也无法同时渲染到多个帧缓冲区。总有一个当前的帧缓冲区。

我能想到的唯一合理的选择是在单独的通行证中进行选择。然后,您可以轻松地将帧缓冲区/附件切换到非多重采样渲染缓冲区,并避免所有这些问题。

无论如何,使用单独的通行证对我来说似乎更干净。这也允许您为每种情况使用专门的着色​​器,而不是总是生成两个输出,即使其中一个输出大多未使用。

答案 1 :(得分:0)

我认为这是有道理的...... 您必须将拾取纹理设置为多重采样,并且在渲染场景后,您可以在屏幕上渲染2个三角形,并在另一个碎片整理器内部读取每个样本...为此,您必须使用GLSL命令:

texelFetch(sampler, pixelposition/*[0-texturesize]*/, /*important*/layernumber);

然后,您可以将其渲染为单一采样纹理,并通过glReadPixel读取颜色。

没有现在对它进行了测试,但我认为它有效