【问题标题】:How pick geometries in OpenGL with multisample framebuffer?如何使用多样本帧缓冲区在 OpenGL 中选择几何图形?
【发布时间】:2016-05-25 23:47:47
【问题描述】:

(编辑) 我使用帧缓冲区进行几何体拾取。我的目标是在一次绘制调用中绘制巨大的场景,但我需要绘制到 多重采样颜色纹理附件 (GL_COLOR_ATTACHMENT0) 并绘制到(编辑)非多重采样纹理附件 (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,然后将其读回用于更改立方体颜色)

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

因为立方体像素的alpha值:

没有多重采样效果很好。但是多重采样将我的输出颜色相乘,然后几何 id 被破坏,因此它选择具有相乘值的随机立方体。

(编辑) 我无法将一个多重采样纹理目标附加到 color0 并将非多重采样纹理目标附加到 color1,它不受支持。如何在一次绘图调用中做到这一点?

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

PS:对不起,英语低。 :)

谢谢。

【问题讨论】:

  • 您不能简单地使用不同的(非多重采样的)帧缓冲区进行挑选吗?您甚至可以拥有一个仅用于拾取的不同着色器,而不是将渲染和拾取值生成为同一着色器的两个输出。
  • 我又读了一遍我的问题,但我没有写正确。我编辑了它。我使用一个帧缓冲区和多个颜色附件。问题是我不能混合多样本和非多样本附件。是否可以在一个绘图调用中使用多个帧缓冲区?一个用于绘制,一个用于选择不同的片段着色器?解决办法是什么?谢谢。
  • @eSeverus:通过将 ID 渲染为颜色来进行挑选可能不是最佳策略。你通常比完全在 CPU 上使用一些光线投射要好得多。但是,我也不知道您为什么要避免额外的渲染通道进行拾取 - 您尤其需要一个 1x1 视口/帧缓冲区,而不是整个场景。另一件事是您似乎在解析多样本数据后进行颜色选择。您可以简单地直接读取多重采样纹理的一个特定样本并获取一个对象或另一个对象,但绝不是 ID 的狂野混合。
  • @derhass 有没有办法回读样本?那会很有趣,但我还没有找到方法。看起来glReadPixels() 在多重采样渲染目标上不受支持。您可能可以使用不会在样本之间进行插值的自定义着色器进行下采样,而只是选择其中一个。
  • @RetoKoradi:是的,你必须通过texelFetch 才能工作。

标签: opengl shader multisampling mouse-picking


【解决方案1】:

您不能在一次绘制调用中进行多重采样和非多重采样渲染。

正如您已经发现的那样,不支持在 FBO 中使用两个颜色目标,并且只对其中一个进行多重采样。来自规范中的“帧缓冲区完整性”部分:

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

您也不能同时渲染到多个帧缓冲区。始终只有一个当前帧缓冲区。

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

无论如何,使用单独的通行证进行采摘对我来说似乎更清洁。这还允许您为每种情况使用专门的着色​​器,而不是总是产生两个输出,即使其中一个大部分未使用。

【讨论】:

  • 我希望得到与您类似的答案。我似乎必须在特殊的“选择”模式下第二次绘制场景,其中仅绘制必要的多边形而没有效果。我假设我需要在 CPU 端使用一些光线投射边界框来消除@derhass 建议的不必要的对象,因为场景是第二次绘制以节省大量时间。我认为这两个答案都是正确的。谢谢。
【解决方案2】:

我认为这是可能的... 您必须将拾取纹理设置为多重采样,并且在渲染场景后,您可以在屏幕上渲染 2 个三角形,在另一个片段着色器中,您可以读取每个样本...要做到这一点,您必须使用 GLSL 命令:

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

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

我现在还没有测试过,但我认为它有效

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    相关资源
    最近更新 更多