2

我有一张正在服务器端阅读并通过 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
}
4

2 回答 2

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>
于 2016-02-08T16:29:27.800 回答
0

因此,要逐行编写图像,我们可以这样做。

顶点着色器

  • attribute vec2 a_position;?
    attribute vec2 a_texCoord;?
    
    void main() {
       ???
    }
    
  • 片段着色器

     #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);
    
    }
    
  • 用于逐像素渲染的Javascript

      function createTextureFromArray(gl, dataArray, type, width, height) {
            var data = new Uint8Array(dataArray);
            var texture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, texture);
            gl.texImage2D(gl.TEXTURE_2D, 0, type, width, height, 0, type, gl.UNSIGNED_BYTE, data);
            return texture;
     }
    
       var arrayBuffer = new ArrayBuffer(640*480);
       for (var i=0; i < 640; i++) {
           for (var j=0; j < 480; j++) {
               arrayBuffer[i] = Math.floor(Math.random() * 255) + 0;     //filling buffer with random data between 0 and 255 which will be further filled to the texture 
               //NOTE : above data is just dummy data , I will get this data from server pixel by pixel.
           }
       }
       var gl = canvas.getContext('webgl');
       // setup GLSL program
       var program = createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
       gl.useProgram(program);
       //what should I add after this ?
    
于 2016-02-10T07:30:12.350 回答