I get glitches and crashes trying to use WebGL for drawing sprites

Recommended Posts

Hello

I am converting my sprite drawing function from canvas 2d to webgl.

As I am new to webgl (and openGL too), I learned from this tuto http://games.greggman.com/game/webgl-image-processing/ and I did copy many lines from it, and some other ones I found.

At last I got it working, but there are some issues. For some reason, some images are never drawn though other ones are, then I get big random black squares on the screen, and finally it makes firefox crash...

I am tearing my hair out trying to solve these problems, but I am just lost... I have to ask for some help.

Please someone have a look at my code and tell me if you see where I made errors.

`<script id="2d-vertex-shader" type="x-shader/x-vertex">	attribute vec2 a_position;	attribute vec2 a_texCoord;	uniform vec2 u_resolution;	uniform vec2 u_translation;	uniform vec2 u_rotation;	varying vec2 v_texCoord;	void main()	{		// Rotate the position		vec2 rotatedPosition = vec2(			 a_position.x * u_rotation.y + a_position.y * u_rotation.x,			 a_position.y * u_rotation.y - a_position.x * u_rotation.x);				// Add in the translation.		vec2 position = rotatedPosition + u_translation;				// convert the rectangle from pixels to 0.0 to 1.0		vec2 zeroToOne = a_position / u_resolution;				// convert from 0->1 to 0->2		vec2 zeroToTwo = zeroToOne * 2.0;				// convert from 0->2 to -1->+1 (clipspace)		vec2 clipSpace = zeroToTwo - 1.0;				gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);				// pass the texCoord to the fragment shader		// The GPU will interpolate this value between points		v_texCoord = a_texCoord;	}</script><!-- fragment shader --><script id="2d-fragment-shader" type="x-shader/x-fragment">	precision mediump float;	// our texture	uniform sampler2D u_image;	// the texCoords passed in from the vertex shader.	varying vec2 v_texCoord;		void main()	{		 // Look up a color from the texture.		 gl_FragColor = texture2D(u_image, v_texCoord);	}</script>`

I use several layered canvas to avoid wasting ressources redrawing the big background and foreground at every frame while they never change. So my canvas are in liste_canvas[] and contexts are in liste_ctx[], c is the id ("background"/"game"/"foreground"/"infos"). Here is their creation code :

`// Get A WebGL contextliste_canvas[c] = document.createElement("canvas") ;document.getElementById('game_div').appendChild(liste_canvas[c]);liste_ctx[c] = liste_canvas[c].getContext('webgl',{premultipliedAlpha:false}) || liste_canvas[c].getContext('experimental-webgl',{premultipliedAlpha:false});liste_ctx[c].viewport(0, 0, game.res_w, game.res_h);// setup a GLSL programliste_ctx[c].vertexShader = createShaderFromScriptElement(liste_ctx[c], "2d-vertex-shader");liste_ctx[c].fragmentShader = createShaderFromScriptElement(liste_ctx[c], "2d-fragment-shader");liste_ctx[c].program = createProgram(liste_ctx[c], [liste_ctx[c].vertexShader, liste_ctx[c].fragmentShader]);liste_ctx[c].useProgram(liste_ctx[c].program);`

And here is my sprite drawing function.

My images are stored in a list too, sprites[], with a string name as id.

They store their origin, which is not necessarily their real center, as .orgn_x and .orgn_y.

(My calculation for rotations may look strange but it does work, I am sure the problem is not in it.)

`function draw_sprite( id_canvas , d_sprite , d_x , d_y , d_rotation , d_scale , d_opacity ){	if( id_canvas=="" ){ id_canvas = "game" ; }	if( !d_scale ){ d_scale = 1 ; }	if( !d_rotation ){ d_rotation = 0 ; }	if( render_mode == "webgl" )	{		c = id_canvas ;				// look up where the vertex data needs to go.		var positionLocation = liste_ctx[c].getAttribLocation(liste_ctx[c].program, "a_position");		var texCoordLocation = liste_ctx[c].getAttribLocation(liste_ctx[c].program, "a_texCoord");				// provide texture coordinates for the rectangle.        	var texCoordBuffer = liste_ctx[c].createBuffer();		liste_ctx[c].bindBuffer(liste_ctx[c].ARRAY_BUFFER, texCoordBuffer);		liste_ctx[c].bufferData(liste_ctx[c].ARRAY_BUFFER, new Float32Array([				0.0,  0.0,				1.0,  0.0,				0.0,  1.0,				0.0,  1.0,				1.0,  0.0,				1.0,  1.0]), liste_ctx[c].STATIC_DRAW);		liste_ctx[c].enableVertexAttribArray(texCoordLocation);		liste_ctx[c].vertexAttribPointer(texCoordLocation, 2, liste_ctx[c].FLOAT, false, 0, 0);		// Create a texture.		var texture = liste_ctx[c].createTexture();		liste_ctx[c].bindTexture(liste_ctx[c].TEXTURE_2D, texture);		// Set the parameters so we can render any size image.		liste_ctx[c].texParameteri(liste_ctx[c].TEXTURE_2D, liste_ctx[c].TEXTURE_WRAP_S, liste_ctx[c].CLAMP_TO_EDGE);		liste_ctx[c].texParameteri(liste_ctx[c].TEXTURE_2D, liste_ctx[c].TEXTURE_WRAP_T, liste_ctx[c].CLAMP_TO_EDGE);		liste_ctx[c].texParameteri(liste_ctx[c].TEXTURE_2D, liste_ctx[c].TEXTURE_MIN_FILTER, liste_ctx[c].LINEAR);		liste_ctx[c].texParameteri(liste_ctx[c].TEXTURE_2D, liste_ctx[c].TEXTURE_MAG_FILTER, liste_ctx[c].LINEAR);		// Upload the image into the texture.		liste_ctx[c].texImage2D(liste_ctx[c].TEXTURE_2D, 0, liste_ctx[c].RGBA, liste_ctx[c].RGBA, liste_ctx[c].UNSIGNED_BYTE, sprites[d_sprite] );				// set the resolution		var resolutionLocation = liste_ctx[c].getUniformLocation(liste_ctx[c].program, "u_resolution");		liste_ctx[c].uniform2f(resolutionLocation, liste_canvas[c].width, liste_canvas[c].height);				// Create a buffer and put a single clipspace rectangle in it (2 triangles)		var buffer = liste_ctx[c].createBuffer();		liste_ctx[c].bindBuffer(liste_ctx[c].ARRAY_BUFFER, buffer);		liste_ctx[c].enableVertexAttribArray(positionLocation);		liste_ctx[c].vertexAttribPointer(positionLocation, 2, liste_ctx[c].FLOAT, false, 0, 0);		                // then I calculate the coordinates of the four points of the rectangle                // taking their origin and scale into account                // I cut this part as it is large and has no importance here                				// and at last, we draw		liste_ctx[c].bufferData(liste_ctx[c].ARRAY_BUFFER, new Float32Array([			 topleft_x , topleft_y ,        		 topright_x , topright_y ,			 bottomleft_x , bottomleft_y ,			 bottomleft_x , bottomleft_y ,			 topright_x , topright_y ,			 bottomright_x , bottomright_y ]), liste_ctx[c].STATIC_DRAW);		// draw		liste_ctx[c].drawArrays(liste_ctx[c].TRIANGLES, 0, 6);	}}`

I did not find any way to port ctx.globalAlpha to webgl by the way. If someone knows how I could add it in my code, I woud be thanksful for that too.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.