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. 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 ?
Can anybody complete the code , I have no idea of how to write code to accomplish this.
It's not clear at all what you're trying to accomplish and why you are using WebGL at all. Are you sending one line of data at a time and you want to render that one individual line of data when its received? Are you sending all the data and you just want reveal it a line at time horizontally?
If you have the entire image available then you can just render a larger and larger portion of it using canvas2d. The
drawImage
function takes optional source and destination rectangles.If you're sending them 1 line of data at a time you can use
ImageData
to make a 1xheight image and useputImageData
to draw it.If you want to scale the
ImageData
put it in a second canvas and use that canvas as input todrawImage
using the first technique.You can do the same things in WebGL. If you have the entire texture in memory then each frame adjust your positions and texture coordinates to draw a different part of it. If you're receiving 1 column of data at a time then just use a texture that's 1 x height and draw that at the appropriate place. OR, copy that 1 x height data into the fullsize texture using
gl.texSubImage2D
and then adjust the positions and texture coordinates appropriately to draw the part of the texture you want to draw to the part of the canvas you want to draw it.drawImage
implemented in WebGL would look something like this. I'm using twgl.js because WebGL is too verbose.To understand them matrix math see these articles and work your way backward or forward in those articles.
OpenGL is not designed to draw images "line by line." However, you can achieve this effect in software by writing to an array, uploading it as a texture, and sampling from it in your shader when drawing a full screen polygon.
To go about this you should create an unsigned byte array. For each pixel in your image you can have some combination of red, green, blue, and alpha channels. The simplest case would be RGB, 3 unsigned bytes for each pixel. The final array should be sized according to the component size (3), times your width (640), times your height (480). You should initialize the values in your array according to what you want your background color to be, then upload it to the gpu using texImage2D.
To 'draw line by line' would be to update 'width' pixels at a time given a row. Each time you change the image data you should then reupload the image to the gpu then draw the fullscreen polygon.
The fullscreen polygon is simply two triangles that cover the entire clip space of the screen. The screen goes from -1 to 1 in x and y dimensions, so make an array buffer accordingly, upload it with the two triangles, and call drawArrays as you update the texture. The UV's for the polygon should go from 0 to 1, so in your vertex shader you should have a 'varying' output variable that will be 0.5 * position + 0.5. This is used in the fragment shader to sample from the texture.
The official documentation is one of the best places to learn from. The official reference pages for openGL ES or openGL 3 contain relevant information, while the reference card https://www.khronos.org/files/webgl/webgl-reference-card-1_0.pdf show the available functions in WebGL that correspond roughly to the same api.