【问题标题】:Can one fragment access all texture pixel values in WebGL GLSL? (Not just it's own TexCoord)一个片段可以访问 WebGL GLSL 中的所有纹理像素值吗? (不仅仅是它自己的 TexCoord)
【发布时间】:2014-05-05 22:32:53
【问题描述】:

假设我正在使用 WebGL 和 GLSL 制作计算着色器。

在这个着色器中,每个片段(或像素)都想查看纹理上的每个像素,然后决定它自己的颜色。

通常一个片段从几个纹理中采样它提供的纹理坐标(UV 值),但我想有效地从单个纹理中为单个片段采样所有 UV 值。

这可能吗?

【问题讨论】:

    标签: opengl-es glsl webgl fragment-shader compute-shader


    【解决方案1】:

    编辑:我能够从 128x128 纹理中的每个像素进行采样,但移动到 256x256 会导致 Chrome 失败。这意味着每个像素可以在一次绘制调用中从同一纹理中采样大约 16384 个不同的像素。对机器学习非常有用!

    注意:在 256x256(65536 像素)下,可能存在 2 次方纹理以支持更高的像素样本数,但我只使用方形纹理,因此未对此进行测试。

    GIST OF SOURCE CODE

    void main() {
        vec4 tcol = vec4(0, 0, 0, 0);
        for (float x = 0.0; x < PIXELS_WIDE; x++) 
            for (float y = 0.0; y < PIXELS_TALL; y++) 
                tcol += texture2D(tex0, vec2(x / PIXELS_WIDE, y / PIXELS_TALL));
        tcol /= 100.;
        gl_FragColor = tcol;
    }
    

    在 Chrome 中,我能够执行以下循环:

    100 次传球(作品):

    void main() {
        float reg = 0.0;
        for (int i = 0; i < 100; i++) {
            reg += 1.0 / 255.0;
        }
        gl_FragColor = vec4(reg, 0, 0, 1);
    }
    

    1 000 次通行证(作品):

    void main() {
        float reg = 0.0;
        for (int i = 0; i < 1000; i++) {
            reg += 0.1 / 255.0;
        }
        gl_FragColor = vec4(reg, 0, 0, 1);
    }
    

    10 000 次通行证(作品):

    void main() {
        float reg = 0.0;
        for (int i = 0; i < 10000; i++) {
            reg += 0.01 / 255.0;
        }
        gl_FragColor = vec4(reg, 0, 0, 1);
    }
    

    100 000 次传球(拉屎):

    void main() {
        float reg = 0.0;
        for (int i = 0; i < 100000; i++) {
            reg += 0.001 / 255.0;
        }
        gl_FragColor = vec4(reg, 0, 0, 1);
    }
    
    GL_INVALID_ENUM : glBindFramebuffer: target was GL_READ_FRAMEBUFFER_ANGLE 
    GL_INVALID_ENUM : glBindFramebuffer: target was GL_DRAW_FRAMEBUFFER_ANGLE 
    WebGL: CONTEXT_LOST_WEBGL: loseContext: context lost
    

    【讨论】:

    • 我发现自己经常这样说,但取决于你想要做什么,mipmaps 可能会有所帮助。它们有效地将纹理转换为树状数据结构,您可以通过从更高的 LOD(更高 -> GL 中的更低分辨率)获取有关更大纹理像素块的信息。对于机器学习中的某些事情,您可能实际上不需要知道每个值,您可以有效地将数据聚类到 mipmap LOD 的层次结构中。现代 GL 中有更有效的方法,但对于 WebGL,mipmap 是一种非常漂亮的普遍支持的数据结构。
    • 100000 次通行证基本上是在给你的 GPU 供电。操作系统和/或浏览器将杀死 WebGL,因为 GPU 不可抢占。如果你想做那么多工作,你需要把它分开。你的 texcoord 计算也是错误的。应该是vec2((x + 0.5) / PIXELS_WIDE, (y + 0.5) / PIXELS_TALL)。如果没有 +0.5,您将计算像素之间的确切位置。根据 GPU 和其他因素,您将获得一个像素或另一个像素。见:stackoverflow.com/a/27439675/128511
    • 另外,在您的 100000 次通行证上。一种加速是将问题分解成块。现代 GPU 有超过 2000 个内核,因此它可以并行执行 2000 件事情,但你必须让它并行执行。绘制单个像素是一回事。绘制 2000 个像素需要做 2000 件事情。因此,例如计算 1000 个 1000 个像素的总和,然后将得到的 1000 个结果相加,将使 GPU 有机会并行化 1000 倍,而计算一个像素是 1000000 个像素的总和不会并行化任何东西。
    【解决方案2】:

    这可能吗?

    确实如此,但是由于每次纹理访问都需要多个 GPU 指令周期,因此您可能会遇到一个硬性限制,即片段着色器在中止之前可以在每个片段上花费多少个周期。

    【讨论】:

    • 合法,我有一种强烈的感觉,这将是指令错误过多(或展开该大小的 for 循环时出现的一些类似错误)。目前是否有超越限制的方法?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-24
    • 1970-01-01
    相关资源
    最近更新 更多