I am having a image that I am reading in server side and pushing to web browser via AJAX call.
I have a requirement where I have to render them line by line using WebGL.
For Example : Image is 640X480 where 640 is width and 480 is height.
Now the total number of pixels will be 640*480 = 307200 pixels.
So, I want to render the whole image in 640(total width) intervals in a loop using WebGL.
Now I have texture2D(as per my knowledge) in webgl to do so, but not getting any idea of where to start .
I also having the ArrayBuffer with me , only thing is using Texture2D I want to render it slowly ,line by line.
I am ready to go for any js libraries ,if they are satisfying the requirements.
Tagging Babylon.js and Three.js ,incase those guys have a answer to my question with what they already have.
Adding some code to explain my requirement :
//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
}
Ok, below is the working code
1) put it into .html file
2) load image (see comment in initTextures function)
In this code is also added vertex and fragment shaders
<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>
So, to write a image line by line we can do something like this.
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 For rendering pixel by 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 ?