javascript - three - webgl game development




Come creare una Texture da un ArrayBuffer in html5 e WebGL (2)

Ok, di seguito è riportato il codice di lavoro 1) Inserito nel file .html 2) carica immagine (vedi commento nella funzione initTextures)

In questo codice sono anche aggiunti vertex e frammenti shader

<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>

Ho un'immagine che sto leggendo sul lato server e che spingo al browser web tramite chiamata AJAX. Ho un requisito in cui devo renderli riga per riga utilizzando WebGL.

Ad esempio: Image è 640X480 in cui 640 è larghezza e 480 è altezza. Ora il numero totale di pixel sarà 640 * 480 = 307200 pixel. Quindi, voglio rendere l'intera immagine in intervalli 640 (larghezza totale) in un ciclo utilizzando WebGL.

Ora ho texture2D (per quanto ne so) in webgl per farlo, ma non ho idea di dove cominciare. Ho anche l'ArrayBuffer con me, l'unica cosa che uso Texture2D voglio renderlo lentamente, riga per riga.

Sono pronto ad andare per qualsiasi libreria js, se soddisfano i requisiti.

Tagging Babylon.js e Three.js, nel caso in cui quei ragazzi abbiano una risposta alla mia domanda con quello che già hanno.

Aggiunta di codice per spiegare il mio requisito:

// 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(ie640) ;i++) //because I know one line length =640. { //how to put data in texture2D using Three.js or Babylon.js or just plain WebGL } var imageDataFromServer = single line data from server; var imageLineData = new ArrayBuffer(imageDataFromServer.length); var imageUintArray = new Uint8Array(imageLineData); for (var i = 0; i < width(ie640) ;i++) //because I know one line length =640. { //how to put data in texture2D using Three.js or Babylon.js or just plain WebGL }


Quindi, per scrivere un'immagine riga per riga, possiamo fare qualcosa di simile.

Vertex Shader

  • attribute vec2 a_position;?
    attribute vec2 a_texCoord;?
    
    void main() {
       ???
    }
  • Fragment Shader

     #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 Per il rendering pixel per pixel

      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 ?




babylonjs