实时预览的颜色直方图

时间:2018-04-01 13:27:54

标签: react-native opengl-es gpuimage webgl2

我一直在尝试使用GPU从图片生成颜色直方图(实际上是实时相机预览),因此opengl-es。我遇到了包含histogram filterGPUImage库。我无法直接使用此库,因为我正在使用react-native与Expo GLView(记录为here),我不想处理本机代码。

这就是说,我应该能够调整代码以使用由WebGL API管理的GLView。我一直试图这样做,但检索到的直方图数据只包含“黑色像素”。

定义着色器:

const histogramRedSamplingVertexShaderSource = `#version 300 es
precision mediump float;

in vec4 position;
out vec3 colorFactor;

void main()
{
  colorFactor = vec3(1.0, 0.0, 0.0);
  gl_Position = vec4(-1.0 + (position.x * 0.0078125), 0.0, 0.0, 1.0);
  gl_PointSize = 1.0;
}
`;
const histogramGreenSamplingVertexShaderSource = `#version 300 es
precision mediump float;

in vec4 position;
out vec3 colorFactor;

void main()
{
  colorFactor = vec3(0.0, 1.0, 0.0);
  gl_Position = vec4(-1.0 + (position.y * 0.0078125), 0.0, 0.0, 1.0);
  gl_PointSize = 1.0;
}
`;
const histogramBlueSamplingVertexShaderSource = `#version 300 es
precision mediump float;

in vec4 position;
out vec3 colorFactor;

void main()
{
  colorFactor = vec3(0.0, 0.0, 1.0);
  gl_Position = vec4(-1.0 + (position.z * 0.0078125), 0.0, 0.0, 1.0);
  gl_PointSize = 1.0;
}
`;

const histogramAccumulationFragmentShaderSource = `#version 300 es
precision mediump float;

in lowp vec3 colorFactor;
out vec4 fragColor;

const lowp float scalingFactor = 1.0 / 256.0;
void main()
{
  fragColor = vec4(colorFactor * scalingFactor, 1.0);
}`;

助手功能(供参考)

createShader = (gl, type, source) => {
  var shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);
  var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  if (success) {
    return shader;
  }

  console.log(gl.getShaderInfoLog(shader));
  gl.deleteShader(shader);
};

createProgram = (gl, vertexShader, fragmentShader) => {
  var program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);
  gl.validateProgram(program);
  var success = gl.getProgramParameter(program, gl.LINK_STATUS);
  if (success) {
    return program;
  }
  console.log(gl.getProgramInfoLog(program));
  gl.deleteProgram(program);
};

初始化

// width and height of the camera view.
const { width, height } = this.state;
const downsamplingFactor = 16;

const cameraTexture = (this.texture = await this.createCameraTexture());
gl.bindTexture(gl.TEXTURE_2D, cameraTexture);

const cameraFramebuffer = gl.createFramebuffer();
const histogramFramebuffer = gl.createFramebuffer();

const histogramAccumulationFragmentShader = this.createShader(gl, gl.FRAGMENT_SHADER, histogramAccumulationFragmentShaderSource);

const histogramRedSamplingVertexShader = this.createShader(gl, gl.VERTEX_SHADER, histogramRedSamplingVertexShaderSource);
const histogramRedSamplingProgram = this.createProgram(gl, histogramRedSamplingVertexShader, histogramAccumulationFragmentShader);

const histogramGreenSamplingVertexShader = this.createShader(gl, gl.VERTEX_SHADER, histogramGreenSamplingVertexShaderSource);
const histogramGreenSamplingProgram = this.createProgram(gl, histogramGreenSamplingVertexShader, histogramAccumulationFragmentShader);

const histogramBlueSamplingVertexShader = this.createShader(gl, gl.VERTEX_SHADER, histogramBlueSamplingVertexShaderSource);
const histogramBlueSamplingProgram = this.createProgram(gl, histogramBlueSamplingVertexShader, histogramAccumulationFragmentShader);

渲染循环

// Binding camera texture to framebuffer
gl.bindFramebuffer(gl.FRAMEBUFFER, cameraFramebuffer);
gl.framebufferTexture2D(
  gl.FRAMEBUFFER,
  gl.COLOR_ATTACHMENT0,
  gl.TEXTURE_2D,
  cameraTexture,
  0
);

// Reading pixel data from the camera image.
const pixelData = new Uint8Array(4 * width * height);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixelData);
console.log(pixelData[101]); // Logging one random pixel (yields value different from zero)

// Adapted from https://github.com/BradLarson/GPUImage2/blob/master/framework/Source/Operations/Histogram.swift

// releaseIncomingFramebuffers
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
// activateFramebufferForRendering
gl.bindFramebuffer(gl.FRAMEBUFFER, histogramFramebuffer);
gl.viewport(0, 0, 256, 3);

// clearFramebufferWithColor
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

// enableAdditiveBlending
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.ONE, gl.ONE);
gl.enable(gl.BLEND);

// histogramRedSamplingProgram
gl.useProgram(histogramRedSamplingProgram);
const histogramRedPositionAttributeLocation = gl.getAttribLocation(
  histogramRedSamplingProgram,
  'position'
);
gl.vertexAttribPointer(
  histogramRedPositionAttributeLocation,
  4,
  gl.UNSIGNED_BYTE,
  0,
  (downsamplingFactor - 1) * 4,
  pixelData
);
gl.drawArrays(gl.POINTS, 0, width * height / downsamplingFactor);

// histogramGreenSamplingProgram
gl.useProgram(histogramGreenSamplingProgram);
const histogramGreenPositionAttributeLocation = gl.getAttribLocation(
  histogramGreenSamplingProgram,
  'position'
);
gl.vertexAttribPointer(
  histogramGreenPositionAttributeLocation,
  4,
  gl.UNSIGNED_BYTE,
  0,
  (downsamplingFactor - 1) * 4,
  pixelData
);
gl.drawArrays(gl.POINTS, 0, width * height / downsamplingFactor);

// histogramBlueSamplingProgram
gl.useProgram(histogramBlueSamplingProgram);
const histogramBluePositionAttributeLocation = gl.getAttribLocation(
  histogramBlueSamplingProgram,
  'position'
);
gl.vertexAttribPointer(
  histogramBluePositionAttributeLocation,
  4,
  gl.UNSIGNED_BYTE,
  0,
  (downsamplingFactor - 1) * 4,
  pixelData
);
gl.drawArrays(gl.POINTS, 0, width * height / downsamplingFactor);

// disableBlending
gl.disable(gl.BLEND);

// End of transposition.

const histogramData = new Uint8Array(3 * 256 * 3);
gl.readPixels(0, 0, 256, 3, gl.RGB, gl.UNSIGNED_BYTE, histogramData);
// Try to read some pixel data, from the histogram 256x1 center line,
// these should be different from zero.
console.log([
  histogramData[256 * 3 + 120],
  histogramData[256 * 3 + 121],
  histogramData[256 * 3 + 122],
]);

直方图数据仅包含零(而相机像素数据是有效/非零值)。有可能错误是在帧缓冲区周围;在“模型”中,framebuffer has a defined size,但我看不到如何转置它。 (错误也可能来自其他地方)。

0 个答案:

没有答案