Opengl es 如何在webgl直方图中排序像素并实现linearGradient?

Opengl es 如何在webgl直方图中排序像素并实现linearGradient?,opengl-es,html5-canvas,webgl,linear-gradients,Opengl Es,Html5 Canvas,Webgl,Linear Gradients,我试图使用webgl实现图像的直方图。 我可以在javascript HTML5画布中完成这项工作,方法是获取255个长度的数组,将每个索引的像素值增加到0-255,并使用createLinearGradient创建直方图 for(var c = 0; c < 256; c++){ histogram[c] = 0; } var ctx = document.getElementById('canvas').getContext('2d'); var pixels= ctx.get

我试图使用webgl实现图像的直方图。 我可以在javascript HTML5画布中完成这项工作,方法是获取255个长度的数组,将每个索引的像素值增加到0-255,并使用createLinearGradient创建直方图

for(var c = 0; c < 256; c++){
    histogram[c] = 0;
}
var ctx = document.getElementById('canvas').getContext('2d');
var pixels= ctx.getImageData(0, 0, width, height).data;
for (var i = 0, j = 0; i < u8a.length; i++, j = j + 4) {
    histogram[pixels[j]]++; //increasing pixel index for histogram
}

我能得出的最好结果是,你不想排序,而是想做一个黑白直方图(所有通道r、g、b的组合)

要做到这一点,您只需要一次对所有通道进行求和,而不是像目前那样进行4次

您需要对以下着色器进行更改,并在javascript中替换一些渲染调用

将“历史vs”更改为 将“最大vs”更改为 对javascript的更改 然后在Javascript中,不需要调用第一个着色器4次,只需调用它一次。另外,由于不需要遮罩均匀性,因此不需要将其传递给着色器

最初看起来像的for循环

  for (var channel = 0; channel < 4; ++channel) {
    gl.colorMask(channel === 0, channel === 1, channel === 2, channel === 3);
    twgl.setUniforms(histProgramInfo, {
      u_texture: tex,
      u_colorMult: [
        channel === 0 ? 1 : 0,
        channel === 1 ? 1 : 0,
        channel === 2 ? 1 : 0,
        channel === 3 ? 1 : 0,
      ],
      u_resolution: [img.width, img.height],
    });
    twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);
  }

?? 对柱状图排序!,如果进行了排序,则不是真正的直方图。无论如何,你的问题很不清楚,你所说的平滑和排序是什么意思?你能提供你想要的图像吗,包括未排序和排序的直方图,因为很难猜出你的意思。从排序我的意思是,它应该以灰度格式从0.0到1.0从最暗到最亮(从黑到白)渲染。我将很快添加预期的图像添加图像,请检查,我目前正在使用Html5画布的createLinearGradient来创建渐变,将最后一行更改为
gl_FragColor=vec4(rr,rr,rr,1.0)*vec4(uv.xxx,1.0)它会将颜色乘以x位置(0-1)作为排序,这还不清楚您的意思。好的,我尝试了您的更改,看起来不错。谢谢。对于排序的事情,请检查我添加的图像,它从较暗的阴影开始,然后转到较亮的阴影。希望这是清楚的。这个解决方案的工作原理和预期的一样,但它并没有像我所附的图像那样产生线性梯度(见顶部覆盖直方图的黑线)。那么,这是否意味着OpenGL不能像我们从HTML5画布createLinearGradient中获得的那样渲染linearGradient?@subffyu546754您需要使用正确的术语。黑线是一个笔划,与梯度无关。是的,我没有注意到这是一个笔划。但是在这种情况下,我们如何在webgl中实现它呢。我可以在网上看到很多例子,但是你能给出一些关于如何在这方面实现stroke的想法吗case@subhfyu546754提供的小提琴不利于添加轮廓,并且显示的笔划延伸到webGl画布之外。您可以轻松地使用2D API
globalCompositeOperation
(gCO)和webGL渲染图像作为遮罩绘制轮廓,但需要修改webGL输出以包括透明像素。然后创建一个新的画布,各边都大一个像素,上下左右各画一个像素的遮罩,将gCO设置为“source TOP”,在画布上画一个黑色矩形,将gCO设置为“source over”,然后在中心画遮罩。好的,我会试试。谢谢你的主意。我接受这个答案
attribute float pixelId;
uniform vec2 u_resolution;
uniform sampler2D u_texture;
void main() {
  vec2 pixel = vec2(mod(pixelId, u_resolution.x), floor(pixelId / u_resolution.x));
  vec2 uv = (pixel + 0.5) / u_resolution;
  vec4 color = texture2D(u_texture, uv);
  float colorSum = (color.r + color.g + color.b) / 3.0 ; 
  gl_Position = vec4((colorSum * 255.0 + 0.5) / 256.0 * 2.0 - 1.0, 0.5, 0, 1);
  gl_PointSize = 1.0;
}
precision mediump float;
uniform sampler2D u_texture;
void main() {
  vec4 maxColor = vec4(0);
  for (int i = 0; i < 256; i++) {
    vec2 uv = vec2((float(i) + 0.5) / 256.0, 0.5);
    maxColor = max(maxColor, vec4(texture2D(u_texture, uv).rgb, 1));
  }
  gl_FragColor = maxColor;
}
precision mediump float;    
uniform sampler2D u_histTexture;
uniform vec2 u_resolution;
uniform sampler2D u_maxTexture;    
void main() {
  vec3 maxColor = texture2D(u_maxTexture, vec2(0)).rgb;
  vec2 uv = gl_FragCoord.xy / u_resolution;
  vec3 hist = texture2D(u_histTexture, uv).rgb;
  gl_FragColor = vec4(step(uv.yyy, hist / maxColor) * uv.x, 1);
}
  for (var channel = 0; channel < 4; ++channel) {
    gl.colorMask(channel === 0, channel === 1, channel === 2, channel === 3);
    twgl.setUniforms(histProgramInfo, {
      u_texture: tex,
      u_colorMult: [
        channel === 0 ? 1 : 0,
        channel === 1 ? 1 : 0,
        channel === 2 ? 1 : 0,
        channel === 3 ? 1 : 0,
      ],
      u_resolution: [img.width, img.height],
    });
    twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);
  }
gl.colorMask(true, true, true, false);
twgl.setUniforms(histProgramInfo, {  u_texture: tex,  u_resolution: [img.width, img.height]});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);