Jump to content

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


Recommended Posts



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... :unsure: 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.



The vertex shader and fragment shader :

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


Please help. Thanks.

Link to comment
Share on other sites

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.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...