如何在html5和WebGL中从ArrayBuffer创建纹理

时间:2016-02-08 12:16:34

标签: javascript html5 three.js webgl babylonjs

我正在使用服务器端读取的图像,并通过AJAX调用推送到Web浏览器。 我有一个要求,我必须使用WebGL逐行渲染它们。

例如:图像是640X480,其中640是宽度,480是高度。 现在像素的总数将是640 * 480 = 307200像素。 因此,我想使用WebGL在循环中以640(总宽度)间隔渲染整个图像。

现在我在webgl中有texture2D(据我所知)这样做,但不知道从哪里开始。 我也有ArrayBuffer和我,只有使用Texture2D我想慢慢地逐行渲染它。

如果满足要求,我准备去任何js库。

标记Babylon.js和Three.js,这些家伙可以回答我的问题。

添加一些代码来解释我的要求:

//Recieve data
Code : 
var imageDataFromServer = single line data from server;
var imageLineData = new ArrayBuffer(imageDataFromServer.length);
var imageUintArray = new Uint8Array(imageLineData);
for (var i = 0; i < width(i.e.640) ;i++) //because I know one line length =640.
{
   //how to put data in texture2D using Three.js or Babylon.js or just plain WebGL
}

2 个答案:

答案 0 :(得分:1)

好的,下面是工作代码 1)将其放入.html文件中 2)加载图像(参见initTextures函数中的注释)

在此代码中还添加了顶点和片段着色器

<canvas width="400" height="400"></canvas>

<script>
function initShaders(gl, vshader, fshader) {
  var program = createProgram(gl, vshader, fshader);    
  gl.useProgram(program);
  gl.program = program;

  return true;
}

function createProgram(gl, vshader, fshader) {
  var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);
  var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);
  var program = gl.createProgram();

  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);

  gl.linkProgram(program);
  return program;
}

function loadShader(gl, type, source) {
  var shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);
  return shader;
}

function getWebGLContext(canvas, opt_debug) {
  return canvas.getContext('webgl');
}

var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'attribute vec2 a_TexCoord;\n' +
  'varying vec2 uv;\n' +
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +
  '  uv = a_TexCoord;\n' +
  '}\n';

var FSHADER_SOURCE =
  '#ifdef GL_ES\n' +
  'precision mediump float;\n' +
  '#endif\n' +
  'uniform sampler2D uImage0;\n' +
  'uniform vec2 resolution;\n' +
  'uniform float time;\n' +
  'varying vec2 uv;\n' +
  'void main() {\n' +
      'vec2 position = 1.0 - gl_FragCoord.xy / resolution;\n' +
      'vec3 color = vec3(1.0);\n' +

      'if (time > position.y * 10.0) {\n' +
          'color = vec3(texture2D(uImage0, uv));\n' +
      '}\n' +
  '  gl_FragColor = vec4(color, 1.0);\n' +
  '}\n';

function main() {
  var canvas = document.querySelector('canvas');
  var gl = getWebGLContext(canvas);
  initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE);

  var n = initVertexBuffers(gl);
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  initTextures(gl, n)

  function render (dt) {
    gl.uniform1f(time, dt / 1000);
    draw();
    requestAnimationFrame(render);
  }

  render();
}

function initVertexBuffers(gl) {
  var verticesTexCoords = new Float32Array([
    -0.5,  0.5,   0.0, 1.0,
    -0.5, -0.5,   0.0, 0.0,
     0.5,  0.5,   1.0, 1.0,
     0.5, -0.5,   1.0, 0.0,
  ]);
  var n = 4;
  var vertexTexCoordBuffer = gl.createBuffer();

  gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);

  var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
  gl.enableVertexAttribArray(a_Position);

  var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
  gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
  gl.enableVertexAttribArray(a_TexCoord);

  return n;
}

function initTextures(gl, n) {
  var texture = gl.createTexture();
  resolution = gl.getUniformLocation(gl.program, 'resolution');
  gl.uniform2f(resolution, 256, 256);
  time = gl.getUniformLocation(gl.program, 'time');

  var uImage0 = gl.getUniformLocation(gl.program, 'uImage0');

  var image = new Image();
  image.onload = function(){ loadTexture(gl, n, texture, uImage0, image); };

  // load this file: http://www.html5rocks.com/static/images/tutorials/easy-hidpi/chrome1x.png
  // to the same folder as this .html file
  image.src = 'chrome1x.png';

  return true;
}

function loadTexture(gl, n, texture, uImage0, image) {
  count = n;
  GL = gl;

  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
  gl.activeTexture(gl.TEXTURE0);
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
  gl.uniform1i(uImage0, 0);

  draw();
}

function draw () {
  if (!window.GL) {
    return;
  }
  GL.clear(GL.COLOR_BUFFER_BIT);
  GL.drawArrays(GL.TRIANGLE_STRIP, 0, count);
}

main();
</script>

答案 1 :(得分:0)

所以,要逐行写一个图像,我们可以这样做。

顶点着色器

  • lblUserName
  • 片段着色器

    attribute vec2 a_position;?
    attribute vec2 a_texCoord;?
    
    void main() {
       ???
    }
    
  • Javascript用于逐像素渲染

     #ifdef GL_ES
     precision mediump float;
     #endif
    
    uniform float time;
    uniform vec2 mouse;
    uniform vec2 resolution;
    
    void main( void ) {
      vec2 position = 1.0 - gl_FragCoord.xy / resolution;
      vec3 color = vec3(1.0);
    
      if (time > position.y * 10.0) {
          color = texture2D(uImage0, uv);
      }
    
     gl_FragColor = vec4(color, 1.0);
    
    }