Tekstura z canvas do webgl

Ten przykład to "making of" projektu obracającej się kuli ziemskiej z wygenerowanej w locie tekstury z elementu canvas. W przykładzie wykorzystujemy następujące biblioteki: jVectorMap - tworzenie wektorowych map, canvg - parser SVG, tworzy canvasa z kodu svg oraz three.js - do obsługi webgl. Pokazuję tutaj jak połączyć trzy biblioteki w celu uzyskania ciekawego efektu. Tekstura z canvas do webgl Kod html przykładu:

<!DOCTYPE html>
<html>
<head>
	<title>Canvas do webgl</title>
	<link rel="stylesheet" href="jquery-jvectormap-1.2.2.css" type="text/css" media="screen"/>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
	<script src="jquery-jvectormap-1.1.1.min.js"></script>
	<script src="jquery-jvectormap-world-mill-en.js"></script>
	<script type="text/javascript" src="canvg-1.3/rgbcolor.js"></script> 
	<script type="text/javascript" src="canvg-1.3/StackBlur.js"></script>
	<script type="text/javascript" src="canvg-1.3/canvg.js"></script> 
	<script type="text/javascript" src="three.min.js"></script> 
	<script src="Detector.js"></script>
</head>
<body>
	<button id="create">Create</button>
	<div id="world-map" style="width: 2048px; height: 1024px;position:absolute;"></div>
	<div id="svg"></div>
	<canvas id="canvas" width="2048px" height="1024px" style="display:none;"></canvas> 
	<div id="webgl"></div>
	<script src="main.js"></script>
</body>
</html>
Załączamy w nim odpowiednie biblioteki oraz plik main.js z naszym kodem. Przycisk create będzie służył do stworzenia obracającej się kuli. Div o id world-map zawiera wekorową mapę jVectorMap, na której będziemy zaznaczać kraje. Po kliknięciu na create utworzy się kula, której teksturą będzie canvas utworzony na bazie jVectorMap.
Poniżej zawartość pliku main.js.
$(function() {
      var vectorMap = $('#world-map').vectorMap({
		regionStyle: {
			hover: {
				fill: '#c6f9ff'
			},
			selected: {
				fill: '#41b6c4'
			}
		},
		selectedRegions: ['PL','DE','ES'],
		regionsSelectable: true
	  });
	  $('#create').on('click', function() {
		createCanv();
		$('#world-map').hide();
		createWebgl();
		return false;
	  });
	  function createCanv() {
			var svg = $('.jvectormap-container').html();
			var svg2 = svg.replace(/<div(.*)<\/div>/, '');
			var rect = '<rect width="2048" height="1024" style="fill:rgb(80,80,80);" />';
			var svg3 = svg2.replace(/(<svg.*?>)/,'$1'+rect);
			canvg(document.getElementById('canvas'), svg3, { ignoreMouse: false, ignoreAnimation: false });
	  }
	function createWebgl() {
		//webgl part
		var webglEl = document.getElementById('webgl');

		if (!Detector.webgl) {
			Detector.addGetWebGLMessage(webglEl);
			return;
		}

		var width  = 1200, height = 800;
		// Earth params
		var radius   = 0.5, segments = 32, rotation = 6;  

		var scene = new THREE.Scene();

		var camera = new THREE.PerspectiveCamera(45, width / height, 0.01, 1000);
		camera.position.z = 1.5;

		var renderer = new THREE.WebGLRenderer();
		renderer.setSize(width, height);

		scene.add(new THREE.AmbientLight(0x333333));

		var light = new THREE.DirectionalLight(0xffffff, 1);
		light.position.set(5,3,5);
		scene.add(light);
		
		var bitmap = document.getElementById('canvas');
		var texture = new THREE.Texture(bitmap);
		texture.needsUpdate = true;
		
		var sphere = new THREE.Mesh(
			new THREE.SphereGeometry(radius, segments, segments),
			new THREE.MeshPhongMaterial({
				map: texture	
			})
		);
		texture.needsUpdate = true;
		
		sphere.rotation.y = rotation; 
		scene.add(sphere);
		webglEl.appendChild(renderer.domElement);

		render();
		function render() {
			sphere.rotation.y += 0.005;
			requestAnimationFrame(render);
			renderer.render(scene, camera);
		}
	}
});
Na początku wstawiamy mapę jVectorMap do diva o id world-map. Więcej na temat jVectorMap. Oprogramowujemy kliknięcie przycisku create. Po jego kliknięciu znika wektorowa mapa i pojawia się kula ziemska z teksturą będącą właśnie tą mapą.
Funkcja createCanv jest odpowiedzialna za stworzenie odpowiedniego canvasa, którego wykorzystujemy w funkcji createWebgl jako teksturę kuli. W funkcji createCanv na podstawie kodu svg wygenerowanego przez jVectorMap za pomocą canvg tworzymy element canvas wyglądający dokładnie tak samo jak nasza wektorowa mapa. Na koniec w ten sposób wygenerowany obraz wykorzystujemy jako tesktura dla obracającej się kuli w funkcji createWebgl. Demo jVectorMap + canvg + three.js