[SOLVED] Using the WebGL renderer is really sensitive - am I doing something wrong?


I’m trying to build a rendering layer on top of Lime, and quickly realized that meant I had to learn OpenGL. At first, the program worked on HTML5 and Android, but not Mac/Windows. The only issue it had was that it didn’t display my texture at all.

After about a day of debugging I realized that switching two seemingly unrelated lines in my shaders fixed Mac/Windows, and broke it on Android, and switching two more lines in my other shader fixed all platforms. Am I doing something strictly wrong in my code? The lines in question are 43 and 44, and 65 and 66, and this is the configuration that doesn’t work on Mac/Windows. Flip 43 and 44 to make it work on native platforms, and break Android. Then flip 65 and 66 to fix it on all platforms.

package app;

import lime.app.Application;
import lime.graphics.WebGLRenderContext;
import lime.graphics.RenderContext;
import lime.graphics.opengl.GLProgram;
import lime.graphics.opengl.GLBuffer;
import lime.graphics.opengl.GLTexture;
import lime.utils.Float32Array;
import lime.math.Matrix4;
import lime.graphics.Image;
import lime.utils.Assets;

class Main extends Application {
	var gl:WebGLRenderContext;
	var colorProgram:GLProgram;
	var textureProgram:GLProgram;
	var buffer:GLBuffer;
	var buffer2:GLBuffer;
	var vertexLocationIndex1:Int;
	var vertexColorIndex1:Int;
	var vertexLocationIndex2:Int;
	var vertexTextureIndex2:Int;
	var verticies:Array<Float> = [100,200,0.0,1.0,0.0, 200,200,0.0,1.0,0.0, 150,100,0.0,0.0,0.0];
	var squareVerts:Array<Float> = [100,300,0,0, 200,300,1,0, 100,400,0,1, 200,400,1,1];
	var width:Int;
	var height:Int;

	public function new() {

	public function init() {
		var colorVertexShader =
		"attribute  vec2 aPos;
		attribute vec3 aColor;
		uniform mat4 uMatrix;

		varying vec3 finalColor;

		void main() {
                    finalColor = aColor;
			gl_Position = uMatrix * vec4(aPos, 0.0, 1.0);

		var colorFragmentShader =
		#if (!desktop || rpi)
		"precision mediump float;" +
		"varying vec3 finalColor;

		void main() {
			gl_FragColor = vec4(finalColor,1.0);

		var textureVertexShader =
		"attribute vec2 aPos;
		attribute vec2 aTexCoord;
		uniform mat4 uMatrix;

		varying vec2 finalTex;

		void main() {
			finalTex = aTexCoord;
			gl_Position = uMatrix * vec4(aPos, 0.0, 1.0);

		var textureFragmentShader =
		#if (!desktop || rpi)
		"precision mediump float;" +
		"varying vec2 finalTex;
		uniform sampler2D uImage0;

		void main() {
			gl_FragColor = texture2D(uImage0, finalTex);

		//creating program just for colors
		colorProgram = GLProgram.fromSources(gl, colorVertexShader, colorFragmentShader);

		//creating viewport matrix
		var orthoMatrix = new Matrix4();
		orthoMatrix.createOrtho(0, window.width, window.height, 0, -1000, 1000);
		var matrixLocation = gl.getUniformLocation(colorProgram, "uMatrix");
		gl.uniformMatrix4fv(matrixLocation, false, orthoMatrix);

		//detailing input to shaders
		vertexLocationIndex1 = gl.getAttribLocation(colorProgram, "aPos");
		vertexColorIndex1 = gl.getAttribLocation(colorProgram, "aColor");

		//creating program just for textures
		textureProgram = GLProgram.fromSources(gl, textureVertexShader, textureFragmentShader);

		//viewport matrix again
		matrixLocation = gl.getUniformLocation(textureProgram, "uMatrix");
		gl.uniformMatrix4fv(matrixLocation, false, orthoMatrix);

		//detailing input again
		vertexLocationIndex2 = gl.getAttribLocation(colorProgram, "aPos");

		//create our buffer
 		buffer = gl.createBuffer();

		//basic gl setup
		gl.clearColor (1, 1, 1, 1);
		gl.blendFunc (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
		gl.enable (gl.BLEND);

	public function loadTexture(image:Image) {
		vertexTextureIndex2 = gl.getAttribLocation(textureProgram, "aTexCoord");

		width = image.width*7;
		height = image.height*7;
		squareVerts[4] = 100+width;
		squareVerts[9] = 300+height;
		squareVerts[12] = 100+width;
		squareVerts[13] = 300+height;

		var imageUniform = gl.getUniformLocation(textureProgram, "uImage0");
		gl.uniform1i(imageUniform, 0);

		var texture:GLTexture = gl.createTexture();
		gl.bindTexture(gl.TEXTURE_2D, texture);

		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);

		#if js
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image.src);
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, image.buffer.width, image.buffer.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, image.data);

	override public function onPreloadComplete() {
		var img:Image = Assets.getImage("assets/1.png");

	override public function onWindowCreate() {
		gl = this.window.context.webgl;

	override public function render(context:RenderContext) {
		if (gl == null) return;

		//set view, and clear colors
		gl.clear (gl.COLOR_BUFFER_BIT);

		//update buffer data
		verticies[10] += 1;

		gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticies), gl.DYNAMIC_DRAW);

		//draw our triangle
		gl.vertexAttribPointer(vertexLocationIndex1, 2, gl.FLOAT, false, 5*Float32Array.BYTES_PER_ELEMENT, 0);
		gl.vertexAttribPointer(vertexColorIndex1, 3, gl.FLOAT, false, 5*Float32Array.BYTES_PER_ELEMENT, 2*Float32Array.BYTES_PER_ELEMENT);

		//draw a textured triangle
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(squareVerts), gl.DYNAMIC_DRAW);

		gl.vertexAttribPointer(vertexLocationIndex2, 2, gl.FLOAT, false, 4*Float32Array.BYTES_PER_ELEMENT, 0);
		gl.vertexAttribPointer(vertexTextureIndex2, 2, gl.FLOAT, false, 4*Float32Array.BYTES_PER_ELEMENT, 2*Float32Array.BYTES_PER_ELEMENT);

I just figured it out! I called getAttribLocation() on the wrong GLProgram :sweat_smile:
Pretty interesting that it would have that effect.