WebGL 3D Земля в браузере. Библиотека Three.js

Для отображение трехмерного пространства в браузере, с недавних пор, используют WebGL. WebGL позволяет отображать такое пространство без дополнительных плагинов, используя видеокарту для вычислений. Это позволяет добиться высокой скорости выполнения кода и, соответственно, высокого FPS (кадров в секунду). Конечно, WebGL облегчает и разработку трехмерных приложений (не нужно самостоятельно пересчитывать матрицы вершин объектов и просчитывать видимость граней), но для непосвященного пользователя и такой стиль записи слишком сложен. Например для создания куба придется написать что-то подобное:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
function createCube(gl) {
        // Vertex Data
        var vertexBuffer;
        vertexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        var verts = [
           // Front face
           −1.0, −1.0,  1.0,
            1.0, −1.0,  1.0,
            1.0,  1.0,  1.0,
           −1.0,  1.0,  1.0,
 
           // Back face
           −1.0, −1.0, −1.0,
           −1.0,  1.0, −1.0,
            1.0,  1.0, −1.0,
            1.0, −1.0, −1.0,
 
           // Top face
           −1.0,  1.0, −1.0,
           −1.0,  1.0,  1.0,
            1.0,  1.0,  1.0,
            1.0,  1.0, −1.0,
 
           // Bottom face
           −1.0, −1.0, −1.0,
            1.0, −1.0, −1.0,
            1.0, −1.0,  1.0,
           −1.0, −1.0,  1.0,
 
           // Right face
            1.0, −1.0, −1.0,
            1.0,  1.0, −1.0,
            1.0,  1.0,  1.0,
            1.0, −1.0,  1.0,
 
           // Left face
           −1.0, −1.0, −1.0,
           −1.0, −1.0,  1.0,
           −1.0,  1.0,  1.0,
           −1.0,  1.0, −1.0
           ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
 
        // Color data
        var colorBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
        var faceColors = [
            [1.0, 0.0, 0.0, 1.0], // Front face
            [0.0, 1.0, 0.0, 1.0], // Back face
            [0.0, 0.0, 1.0, 1.0], // Top face
            [1.0, 1.0, 0.0, 1.0], // Bottom face
            [1.0, 0.0, 1.0, 1.0], // Right face
            [0.0, 1.0, 1.0, 1.0]  // Left face
        ];
        var vertexColors = [];
        for (var i in faceColors) {
            var color = faceColors[i];
            for (var j=0; j < 4; j++) {
                vertexColors = vertexColors.concat(color);
            }
        }
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexColors), gl.STATIC_DRAW);
 
        // Index data (defines the triangles to be drawn)
        var cubeIndexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeIndexBuffer);
        var cubeIndices = [
            0, 1, 2,      0, 2, 3,    // Front face
            4, 5, 6,      4, 6, 7,    // Back face
            8, 9, 10,     8, 10, 11,  // Top face
            12, 13, 14,   12, 14, 15, // Bottom face
            16, 17, 18,   16, 18, 19, // Right face
            20, 21, 22,   20, 22, 23  // Left face
        ];
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeIndices), gl.STATIC_DRAW);
 
        var cube = {buffer:vertexBuffer, colorBuffer:colorBuffer, indices:cubeIndexBuffer,
                vertSize:3, nVerts:24, colorSize:4, nColors: 24, nIndices:36,
                primtype:gl.TRIANGLES};
 
        return cube;
    }
Только малая часть программистов любят поработать рерайтером, чтобы сделать свой куб... Поэтому упростит нам жизнь библиотека Three.js (скачать можно тут: архив three.js с офф. сайта) Чтобы создать примитив в three.js достаточно написать:
1
var geometry = new THREE.SphereGeometry( 200, 20, 20 );
С помощью примера earth, из библиотеки Three.js, сделаем вращающуюся землю:
1
2
<div id="container" style="min-height:300px;"></div>
<script src="/javascripts/three.js/build/three.min.js"></script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
var container, camera, scene, renderer, group;
  var windowHalfX =  $(container).width() / 2,
      windowHalfY =  $(container).height() / 2;
    
  //запускает инициализацию
  init();
  animate();
  //Функция инициализирует сцену,
  //создает камеру и устанавливает режим отображения
  function init() {
    //получает контейнер для добавления канваса в него
    container = document.getElementById( 'container' );
    //поворачивает наши 3D объекты, при наведении мыши
    container.onmousemove=function(event){
      group.rotation.y+=event.movementX/30;
      group.rotation.x+=event.movementY/30;
    }
    //создаем камеру
    camera = new THREE.PerspectiveCamera(
        60,
        $(container).width() / $(container).height(),
        1, 2000
    );
    camera.position.z = 500;
      
    //создаем сцену, группу. добавляем группу в сцену
    scene = new THREE.Scene();
    group = new THREE.Group();
    scene.add( group );
      
    //создаем загрузчик текстур
    var loader = new THREE.TextureLoader();
    //грузим
    loader.load( '/images/news/101-earth.jpg', /* тут колбек */function ( texture ) {
      //вызывается при загрузке
      //создает примитив, материал
      var geometry = new THREE.SphereGeometry( 200, 20, 20 );
      var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
      //создает меш(поверхность) планеты по геометрии
      var mesh = new THREE.Mesh( geometry, material );
      //добавляет объект в группу
      group.add( mesh );
    } );   
    //получает канвас (хост)
    //т.е. место на чем будет рисовать
    var canvas = document.createElement( 'canvas' );
    canvas.width = 128;
    canvas.height = 128;
    //создаем рисующий объект
    renderer = new THREE.WebGLRenderer();
    //устанавливаем цвет фона
    renderer.setClearColor(0xeeeeee);
    //разрешение
    renderer.setPixelRatio(window.devicePixelRatio);
    //размеры рисуемого хоста
    renderer.setSize($(container).width(), $(container).height());
    //добавляем в контейнер
    container.appendChild(renderer.domElement);
  }
  //отобразит анимацию модели, если она есть
  function animate() {
    requestAnimationFrame( animate );
    render();
  }
  //поворачивает модель планеты
  //вызывает перерисовку сцены
  function render() {
    //поворачиваем камеру
    camera.lookAt( scene.position );
    //поворачиваем модель
    group.rotation.y -= 0.01;
    //отрисовываем
    renderer.render( scene, camera );
  }
Результат - 75 строк вместе с комментариями (меньше, чем создание куба в чистом WebGL) и выглядит неплохо. Если у Вас работает WebGL, то можете посмотреть реализованный пример ниже:
Спасибо за внимание.
Если статья Вам показалась незаконченной или Вы знаете как её улучшить, пожалуйста сообщите мне e@gohtml.ru