Is there a fast way to the average colors from sev

2019-05-29 22:51发布

I am very new to the WebGL subject. What I want to do is to calculate the average color of 6 different framebuffers like the ones below in the picture. Now I am wondering what the best way to go about it would be? I tried to do

gl.readPixels(0, 0, 256, 256, gl.RGBA, gl.UNSIGNED_BYTE, pixelValues);

but that seems to be very slow... Is there a way that this can happen on the graphics card?

enter image description here

this is how the FBO is set up - I have this from a tutorial:

...

2条回答
We Are One
2楼-- · 2019-05-29 23:31

You have two options

  1. Write a fragment shader that runs once per row (per texture) by rendering a quad (1 x textureheight) and runs through all pixels in the row and averages them. Repeat this process on the averaged rows and you will have the average of the entire image. This is called stream reduction
  2. Call glGenerateMipMap on your FBOs and then access the highest level mipmap (get the params of this mipmap by glGetTexLevelParameter). Now you can use either the ReadPixels method on the much-reduced and averaged mip-image or use GLSL and this ought to be much faster.
查看更多
祖国的老花朵
3楼-- · 2019-05-29 23:46

Off the top of my head

  1. Make 6 fbos.
  2. Make sure each fbo is made with a texture attachment, not a renderbuffer.
  3. Render the 6 scenes to the 6 fbos
  4. For each texture call gl.generateMipmap(...)
  5. Write a shader that takes 6 textures and averages them using texture2D with the bias option. Set the bias to the number of levels in your textures. This is to tell the GPU to use the smallest level.
  6. Render a unit quad with that shader to a 1 pixel fbo (or 1 pixel in your backbuffer).
  7. Call gl.readpixels on that 1 pixel.

I think the shader would look something like this

--fragment shader--

precision mediump float;

uniform sampler2D u_textures[6];
uniform float u_bias;

void main() {
   // since we know we are rendering only with the last mip
   // then there is only 1 texel.
   vec2 center = vec2(0.5, 0.5);
   vec4 sum = 
     texture2D(u_textures[0], center, u_bias) +
     texture2D(u_textures[1], center, u_bias) +
     texture2D(u_textures[2], center, u_bias) +
     texture2D(u_textures[3], center, u_bias) +
     texture2D(u_textures[4], center, u_bias) +
     texture2D(u_textures[5], center, u_bias);
   gl_FragColor = sum / 6.0;
}
查看更多
登录 后发表回答