在webgl片段着色器中按颜色计算像素

时间:2014-04-15 18:15:29

标签: glsl webgl fragment-shader

我有2d纹理S并希望返回3d纹理H,这样像素H [r,g,b]等于纹理S中颜色rgb的像素数。基本上是纹理S中颜色的直方图。

我知道遮挡查询,但它只在webgl2和IIUC中可用,即使只有布尔结果,而且我需要对每种颜色进行单独的查询。理想情况下,我想在一个片段着色器传递中执行此操作。有没有办法在片段着色器中进行缩小(折叠)操作?

为什么我需要这个(如果你有兴趣):

我正在尝试在webgl片段着色器中对象和静态地形之间进行像素完美的2D碰撞检测。

计划是使用过去的技巧 - 画一个精灵4次 - 移动(0,0),(0,dy),(dx,0)和(dx,dy)像素 - 并计算精灵的像素每次都与地形相撞 - 从中​​我可以计算出矢量(nx,ny),它代表物体应尽快移动以反弹地形的方向。简单地将该矢量添加到物体的速度使得物体沿着地形(沿着山丘,在颠簸上跳跃等)很好地滑动。我在旧的C ++游戏中使用它并且效果很好,但在js中它太慢了。

我想在游戏中绘制所有精灵的整个顶点缓冲区(每个精灵都有不同的颜色,以便能够识别哪些物体碰撞)4次,每次在它们上面绘制黑色地形,然后计算每种颜色的像素数在得到的4个帧缓冲区中。

问题是 - 如何计算片段着色器中的像素?

1 个答案:

答案 0 :(得分:2)

  

如何计算片段着色器中的像素?

在一次通过中,可能 - 您可能会遇到GPU超时异常或太多命令异常。我最近运行了一些配置文件来查看WebGL中的限制:Can one fragment access all texture pixel values in WebGL GLSL? (Not just it's own TexCoord)

基本上你想使用for循环(或两个for循环用于x / y)遍历纹理上的每个像素,这个例子将所有颜色值添加到一个像素中:

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

然后如果您希望每个像素代表不同颜色的总出现次数,则需要渲染到具有C像素的曲面,其中C是您想要直方图的唯一颜色数。这要求每个像素都知道它的颜色值,这最简单的方法是通过使纹理包含所有颜色一次,从UV(纹理坐标)中采样,然后迭代实际场景中的所有像素进行组织编排并计算颜色:

void main() {
    vec4 this_pixels_unique_color = texture2D(tex_unique_colors, tex_coord);
    int  occurrences_of_this_unique_color = 0;
    for (float x = 0.0; x < SCENE_PIXELS_WIDE; x++) 
        for (float y = 0.0; y < SCENE_PIXELS_TALL; y++) 
            color_register += texture2D(tex_scene_to_histogram, vec2(x / SCENE_PIXELS_WIDE, y / SCENE_PIXELS_TALL));
    gl_FragColor = vec4(occurrences_of_this_unique_color, occurrences_of_this_unique_color, occurrences_of_this_unique_color, 1);
}

离开你的渲染表面,每个唯一颜色有一个像素,其中每个像素的暗度代表场景中的那种颜色的量化。