Cześć,
Chce wygenerować kulę ziemską z trójkątów. Napisałem skrypt, który oblicza współrzędne wierzchołków dla trójkątów, dodaje indeksy dla wierzchołków, a także liczy normalne dla każdego trójkąta. Problem jest taki, że skrypt działa w kilku procentach, bo rysuje się tylko kawałek tej kuli.
Czy jest jakieś ograniczenczenie w ilości rysowanych elementów?

Skrypt:

window.onload = function() {
	var gl = document.getElementById("webgl_canvas").getContext("experimental-webgl");

	// Create vertex shader
	var vertexShaderCode = document.querySelector("#vs").textContent;
	var vertexShader = gl.createShader(gl.VERTEX_SHADER);
	gl.shaderSource(vertexShader, vertexShaderCode);
	gl.compileShader(vertexShader);
	
	// Create fragment shader
	var fragmentShaderCode = document.querySelector("#fs").textContent;
	var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
	gl.shaderSource(fragmentShader, fragmentShaderCode);
	gl.compileShader(fragmentShader);

	// Create program
	var program = gl.createProgram();
	gl.attachShader(program, vertexShader);
	gl.attachShader(program, fragmentShader);
	gl.linkProgram(program);
	gl.useProgram(program);

	// Create buffer for positions of vertices
	var posLoc = gl.getAttribLocation(program, "pos");
	gl.enableVertexAttribArray(posLoc);
	// Create buffer for position of vertices
	var posBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
	
	
	// ########################
	var phi = 0; // angle of rotation begin since 0, than phi+=10
	var theta = -90; // range betwen 90 and -90
	var radius = 1;
	 
	var vertices = [];
	var indices = [];
	var normals = [];
	
	function sphere2cartesian(phi, theta, radius){
		var x = radius * Math.cos(theta*(Math.PI/180)) * Math.cos(phi*(Math.PI/180));
		var y = radius * Math.cos(theta*(Math.PI/180)) * Math.sin((phi*Math.PI/180));
		var z = radius * Math.sin(theta*(Math.PI/180));
		// console.log(phi, theta, radius);
		// console.log(x, '  \t', y, '\t', z);
		// var x = radius * Math.sin(theta*Math.PI/180) * Math.cos(phi*Math.PI/180);
		// var y = radius * Math.sin(theta*Math.PI/180) * Math.sin(phi*Math.PI/180);
		// var z = radius * Math.cos(theta*Math.PI/180);
		
		return [x, y, z];
	}
	
	
	function find_normal(x1, x3, x4, y1, y3, y4, z1, z3, z4){
		var r1x = x1-x4;
		var r2x = x3-x4;
		
		var r1y = y1-y4;
		var r2y = y3-y4;
		
		var r1z = z1-z4;
		var r2z = z3-z4;
		
		//cross product
		var nx = (r1y*r2z)-(r1z*r2y);
		var ny = -((r1x*r2z)-(r1z*r2x));
		var nz = (r1x*r2y)-(r1y*r2x);
		
		// change wector length to 1 unit
		var n_len = Math.sqrt(Math.pow(nx, 2)+Math.pow(ny, 2)+Math.pow(nz, 2));
		
		return [nx/n_len, ny/n_len, nz/n_len];
	}
	
	
	
	var index = 0;
	for (var theta=-90; theta<90; theta+=10){	
		for (var phi=0; phi<360; phi+=10){ 
			// generate vertices
			// We need many vertices, because each vertex need
			// own value of normal and UV
			var xyz = sphere2cartesian(phi, theta, radius);
			var x1 = xyz[0];
			var y1 = xyz[1];
			var z1 = xyz[2];
			phi+=10;
					
			var xyz = sphere2cartesian(phi, theta, radius);
			var x2 = xyz[0];
			var y2 = xyz[1];
			var z2 = xyz[2];
			theta+=10;		
			
			var xyz = sphere2cartesian(phi, theta, radius);
			var x3 = xyz[0];
			var y3 = xyz[1];
			var z3 = xyz[2];
			phi-=10;
			
			var xyz = sphere2cartesian(phi, theta, radius);
			var x4 = xyz[0];
			var y4 = xyz[1];
			var z4 = xyz[2];
			theta-=10;
		
			
			vertices.push(x1, y1, z1);
			vertices.push(x2, y2, z2);
			vertices.push(x3, y3, z3);
			vertices.push(x4, y4, z4);
			
			//	adding indices		
			indices.push(index, index+1, index+2);
			indices.push(index, index+2, index+3);
			index += 4;
			
			// adding normals
			var normal = find_normal(x1, x3, x4, y1, y3, y4, z1, z3, z4);
			normals.push(normal[0], normal[1], normal[2]);
			normals.push(normal[0], normal[1], normal[2]);
			normals.push(normal[0], normal[1], normal[2]);
			normals.push(normal[0], normal[1], normal[2]);
			
		
		}
	}
	
	
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
	gl.vertexAttribPointer(posLoc, 3, gl.FLOAT, false, 0, 0);

	// Create buffer for UV coordinates
	var uvLoc = gl.getAttribLocation(program, "uv");
	gl.enableVertexAttribArray(uvLoc);
	var uvBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
	
	// ###################
	// generate UVS
	
	var texture_size_row = 1/36;
	var texture_size_col = 1/18;

	var uvs = [];
	for (var texture_y=1; texture_y>=0; texture_y-=texture_size_col){
		for (var texture_x=0; texture_x<1; texture_x+=texture_size_row){ 

			uvs.push(texture_x, texture_y);	
			uvs.push((texture_x+texture_size_row), texture_y);
			uvs.push((texture_x+texture_size_row), (texture_y-texture_size_col));
			uvs.push(texture_x, (texture_y-texture_size_col));
	
		}
	}
	
	// ###################
	
	
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(uvs), gl.STATIC_DRAW);
	gl.vertexAttribPointer(uvLoc, 2, gl.FLOAT, false, 0, 0);

	// Create buffer for vertex normals
	var normalLoc = gl.getAttribLocation(program, "normal");
	gl.enableVertexAttribArray(normalLoc);
	var normalBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);

	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);
	gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, true, 0, 0);

	// Create index buffer
	var indexBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
	
	 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array(indices), gl.STATIC_DRAW);
	// gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(indices), gl.STATIC_DRAW);

	
	// Create and load image used as texture
	var image = new Image();
	image.src = "./globe_texture.jpg";
	image.onload = function() {
		var texture = gl.createTexture();
		gl.bindTexture(gl.TEXTURE_2D, texture);
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
		gl.generateMipmap(gl.TEXTURE_2D);

		gl.activeTexture(gl.TEXTURE0);
		gl.bindTexture(gl.TEXTURE_2D, texture);
		var samplerLoc = gl.getUniformLocation(program, "sampler");
		gl.uniform1i(samplerLoc, 0); // nula odpovídá gl.TEXTURE0
	};

	// Create matrix for model
	var modelMatrix = mat4.create();
	mat4.scale(modelMatrix, modelMatrix, vec3.fromValues(0.8, 0.8, 0.8));
	var modelLocation = gl.getUniformLocation(program, "modelMatrix");
	gl.uniformMatrix4fv(modelLocation, false, modelMatrix);

	// Create matrix for view
	var viewMatrix = mat4.create();
	mat4.translate(viewMatrix, viewMatrix, vec3.fromValues(0, 0, -5));
	var viewLocation = gl.getUniformLocation(program, "viewMatrix");
	gl.uniformMatrix4fv(viewLocation, false, viewMatrix);

	// Create matrix for projection
	var projMatrix = mat4.create();
	mat4.perspective(projMatrix, Math.PI/3, 1, 0.1, 100);
	var projLocation = gl.getUniformLocation(program, "projMatrix");
	gl.uniformMatrix4fv(projLocation, false, projMatrix);

	// Create matrix for transformation of normal vectors
	var normalMatrix = mat3.create();
	var normalLocation = gl.getUniformLocation(program, "normalMatrix");
	mat3.normalFromMat4(normalMatrix, modelMatrix);
	gl.uniformMatrix3fv(normalLocation, false, normalMatrix);

	// Enable depth test
	gl.enable(gl.DEPTH_TEST);

	// Create polyfill to make it working in the most modern browsers
	window.requestAnimationFrame = window.requestAnimationFrame
		|| window.mozRequestAnimationFrame
		|| window.webkitRequestAnimationFrame
		|| function(cb) { setTimeout(cb, 1000/60); };

	var render = function() {
		mat4.rotateX(modelMatrix, modelMatrix, 0.005);
		mat4.rotateY(modelMatrix, modelMatrix, 0.01);
		gl.uniformMatrix4fv(modelLocation, false, modelMatrix);

		mat3.normalFromMat4(normalMatrix, modelMatrix);
		gl.uniformMatrix3fv(normalLocation, false, normalMatrix);

		gl.clear(gl.COLOR_BUFFER_BIT, gl.DEPTH_BUFFER_BIT);
		gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_BYTE, 0); 
		requestAnimationFrame(render);
	}
	
	render();
}