SlideShare a Scribd company logo
1 of 92
Интерактивные
3D-карты своими
руками
Амосов Александр, AVITO
email: s9k0@ya.ru
twitter: @gc_s9k
История
2
3
4
5
6
2D vs 3D
7
Почему 3D?
• Это красиво
8
Почему 3D?
• Это красиво
9
Почему 3D?
• Это красиво
• Это наглядно
10
Почему 3D?
• Это красиво
• Это наглядно
• Потому что я могу
11
Создание модели
12
Создание модели
• Найти моделлера (опционально)
• Найти готовые модели (опционально)
• Освоить 3D-редактор самому
13
14
Blender
• бесплатность
• открытый код
• постоянное развитие
• кроссплатформенность
• пользовательские скрипты на python
15
16
SVG Blender
17
18
19
20
import bpy
geometry = bpy.data.meshes['place']
for obj in bpy.context.selected_objects:
obj.rotation_euler.x = 0
obj.rotation_euler.y = 0
obj.data = geometry
obj.location.z = 0
21
22
Тени
23
24
25
26
OpenGL 1.5 OpenGL 2.0 OpenGL 3.3 OpenGL 4.5
OpenGL ES 1.1 OpenGL ES 2.0 OpenGL ES 3.0
Vulkan
WebGL 1.0 WebGL 2.0
27
WebGL Next?
28
29
2D vs 3D [2]
30
2D
31
<canvas id="canvas" width="100" height="100"></canvas>
<script>
(function() {
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.fillStyle = 'rgba(255, 0, 0, 1)';
context.fillRect(25, 25, 50, 50);
}());
</script>
3D
32
<canvas id="canvas" width="100" height="100"></canvas>
<script>
(function() {
const canvas = document.getElementById('canvas');
const gl = canvas.getContext('webgl');
// Инициализировать шейдеры
// Создать программу
// Создать вершинный буфер
// Сохранить ссылку на буферный объект в атрибут
// Вызвать отрисовку
}());
</script>
Вершинный шейдер
33
const vertexShaderSource = `
attribute vec4 position;
void main() {
gl_Position = position;
}
`;
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
Фрагментный шейдер
34
const fragmentShaderSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, vertexShaderSource);
gl.compileShader(fragmentShader);
Программа
35
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
Вершинный буфер
36
const vertices = new Float32Array([
-0.5, 0.5, -0.5, -0.5,
0.5, 0.5, 0.5, -0.5
]);
const vertexSize = 2;
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
const attrPosition = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(attrPosition, vertexSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(attrPosition);
Отрисовка
37
const vertices = new Float32Array([
-0.5, 0.5, -0.5, -0.5,
0.5, 0.5, 0.5, -0.5
]);
const vertexSize = 2;
// …
gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertices.length / vertexSize);
38
WebGL Programming Guide:
Interactive 3D Graphics:
Programming with WebGL
Авторы: Коичи Мацуда, Роджер Ли
39
WebGL Framework
(three.js)
40
WebGL Framework
• Удобные абстракции
• Краткий код
• Никаких шейдеров (поначалу)
41
var scene, camera, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
geometry = new THREE.BoxGeometry( 200, 200, 200 );
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
42
var scene, camera, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
geometry = new THREE.BoxGeometry( 200, 200, 200 );
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
43
44
45
var scene, camera, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
geometry = new THREE.BoxGeometry( 200, 200, 200 );
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
46
47
var scene, camera, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
geometry = new THREE.BoxGeometry( 200, 200, 200 );
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
48
var scene, camera, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
geometry = new THREE.BoxGeometry( 200, 200, 200 );
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
49
var scene, camera, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
geometry = new THREE.BoxGeometry( 200, 200, 200 );
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
50
var scene, camera, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
var loader = new THREE.ObjectLoader();
loader.load('model.json', function(mesh) {
scene.add(mesh);
});
ry =
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
51
SVG Blender
{
"metadata": {
"version": 4.4,
"sourceFile": "model.blend",
"generator": "io_three",
"type": "Object"
},
"geometries": [
...
],
"materials": [
...
],
"object": {
...
}
}
JSON
io_three
52
Больше контроля
53
Больше контроля
54
Больше контроля
55
<script src="three/build/three.js"></script>
<script src="three/examples/js/controls/OrbitControls.js"></script>
var scene, camera, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
var loader = new THREE.ObjectLoader();
loader.load('model.json', function(mesh) {
scene.add(mesh);
});
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
56
var scene, camera, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
new THREE.OrbitControls(camera);
var loader = new THREE.ObjectLoader();
loader.load('model.json', function(mesh) {
scene.add(mesh);
});
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.y += 0.02;
renderer.render( scene, camera );
}
57
58
https://goo.gl/ell2e7
Interactive 3D Graphics Course With Three.js & WebGL
https://www.udacity.com/course/interactive-3d-graphics--cs291
59
Как работает
приложение
60
Viewer 61
• Модель с запеченными тенями
• Рейкастинг объектов
• Спрайты для иконок
UI 62
• React
Viewer UI
Redux store
63
Viewer UI
Redux store
64
{
type: 'SELECT_FLOOR',
floor: 10
}
Все тормозит?
65
66
Сглаживание
67
// WebGL:
const gl = canvas.getContext("webgl", { antialias: true });
// three.js:
const renderer = new THREE.WebGLRenderer({ antialias: true });
На взлет
68
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
Не рендерить все время
69
Начало движения камеры
Конец движения камеры
Запуск рендеринга
Остановка рендеринга
Изменение состояния приложения Отрендерить один кадр
Raycasting
70
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(normalizedMouseCoordinates, camera);
const intersects = raycaster.intersectObjects(objects);
Colliders
71
72
73
Instancing
До:
365 draw calls
После:
51 draw calls
74
ANGLE_instanced_arrays extension
75
76
uniform
uniform
uniform
uniform
77
uniform
uniform
uniform
uniform
uniform
78
uniform
uniform
uniform
uniform
uniform
79
uniform
uniform
uniform
uniform
attribute
attribute
attribute
attribute
Instancing
80
• Сильно повышает производительность
Instancing
81
• Сильно повышает производительность
• Сложно
https://goo.gl/zdaWZU
82
Упрощение модели
83
Оптимизация текстур
84
Сжатые текстуры
Плюсы:
• В 4 раза меньше видеопамяти занимают
Ограничения:
• Разные форматы: DXT, PVRTC, ETC
• Ухудшение картинки
• Проблемы с прозрачностью
• Больший объем файлов (но можно применить gzip)
85
https://goo.gl/swsgxR
Сжатые текстуры
86
Сжатые текстуры
87
88
Сжатые текстуры
Не гонитесь за
реализмом
89
You are not alone
90
Ссылки
Курс по трехмерной графике на Udacity
Книга "Программирование трехмерной графики"
Примеры threejs
Видео про рендеринг текста в WebGL (слайды)
Видео про производительность WebGL (статья)
91
Спасибо! Вопросы?
92
Ссылки
https://goo.gl/wt4wzp

More Related Content

Similar to Интерактивные 3D-карты своими руками / Александр Амосов (Avito)

«3D-плеер на WebGL», Василика Климова, MoscowJS 21
«3D-плеер на WebGL», Василика Климова, MoscowJS 21«3D-плеер на WebGL», Василика Климова, MoscowJS 21
«3D-плеер на WebGL», Василика Климова, MoscowJS 21MoscowJS
 
Dmitry Bartalevich - "How to train your WebVR"
Dmitry Bartalevich - "How to train your WebVR"Dmitry Bartalevich - "How to train your WebVR"
Dmitry Bartalevich - "How to train your WebVR"IT Event
 
Promise me an Image... Антон Корзунов, Яндекс, MoscowJs 33
Promise me an Image... Антон Корзунов, Яндекс, MoscowJs 33Promise me an Image... Антон Корзунов, Яндекс, MoscowJs 33
Promise me an Image... Антон Корзунов, Яндекс, MoscowJs 33MoscowJS
 
создание HTML игр на элементе canvas
создание HTML игр на элементе canvasсоздание HTML игр на элементе canvas
создание HTML игр на элементе canvasAlexander Samantsov
 
DUMP-2013 Frontend - Возможности последних WEB-стандартов в API Яндекс.Карт -...
DUMP-2013 Frontend - Возможности последних WEB-стандартов в API Яндекс.Карт -...DUMP-2013 Frontend - Возможности последних WEB-стандартов в API Яндекс.Карт -...
DUMP-2013 Frontend - Возможности последних WEB-стандартов в API Яндекс.Карт -...it-people
 
проект Gpu digital lab швабе
проект Gpu digital lab швабепроект Gpu digital lab швабе
проект Gpu digital lab швабеoleg gubanov
 
Обзор программных средств Майкрософт для графики и визуализации: коммерческой...
Обзор программных средств Майкрософт для графики и визуализации: коммерческой...Обзор программных средств Майкрософт для графики и визуализации: коммерческой...
Обзор программных средств Майкрософт для графики и визуализации: коммерческой...Dmitri Soshnikov
 
"Погружение в Robolectric" Дмитрий Костырев (Avito)
"Погружение в Robolectric"  Дмитрий Костырев (Avito)"Погружение в Robolectric"  Дмитрий Костырев (Avito)
"Погружение в Robolectric" Дмитрий Костырев (Avito)AvitoTech
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в DjangoMoscowDjango
 
Марина Степанова "Много объектов на карте"
Марина Степанова "Много объектов на карте"Марина Степанова "Много объектов на карте"
Марина Степанова "Много объектов на карте"Yandex
 
ObjectManager, или как работать с большим количеством объектов на карте, Мари...
ObjectManager, или как работать с большим количеством объектов на карте, Мари...ObjectManager, или как работать с большим количеством объектов на карте, Мари...
ObjectManager, или как работать с большим количеством объектов на карте, Мари...Ontico
 
Что API Карт забыл на сервере — Антон Корзунов
Что API Карт забыл на сервере — Антон КорзуновЧто API Карт забыл на сервере — Антон Корзунов
Что API Карт забыл на сервере — Антон КорзуновYandex
 
Всеволод Шмыров, Яндекс
Всеволод Шмыров, ЯндексВсеволод Шмыров, Яндекс
Всеволод Шмыров, ЯндексElena Voynova
 
Пощупать 3д в браузере | Odessa Frontend Meetup #15
Пощупать 3д в браузере | Odessa Frontend Meetup #15Пощупать 3д в браузере | Odessa Frontend Meetup #15
Пощупать 3д в браузере | Odessa Frontend Meetup #15OdessaFrontend
 
Четвертое занятие курса iOS-разработки в ГУ-ВШЭ
Четвертое занятие курса iOS-разработки в ГУ-ВШЭЧетвертое занятие курса iOS-разработки в ГУ-ВШЭ
Четвертое занятие курса iOS-разработки в ГУ-ВШЭOleg Parinov
 
Делаем кроссбраузерные тесты поверх Webdriver
Делаем кроссбраузерные тесты поверх WebdriverДелаем кроссбраузерные тесты поверх Webdriver
Делаем кроссбраузерные тесты поверх WebdriverSQALab
 
Тестирование CSS-регрессий с Gemini — Сергей Татаринцев
Тестирование CSS-регрессий с Gemini — Сергей ТатаринцевТестирование CSS-регрессий с Gemini — Сергей Татаринцев
Тестирование CSS-регрессий с Gemini — Сергей ТатаринцевYandex
 
JavaScript. Уровень 3г. HTML5 API
JavaScript. Уровень 3г. HTML5 APIJavaScript. Уровень 3г. HTML5 API
JavaScript. Уровень 3г. HTML5 APIIvan Matiishyn
 
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)Ontico
 

Similar to Интерактивные 3D-карты своими руками / Александр Амосов (Avito) (20)

«3D-плеер на WebGL», Василика Климова, MoscowJS 21
«3D-плеер на WebGL», Василика Климова, MoscowJS 21«3D-плеер на WebGL», Василика Климова, MoscowJS 21
«3D-плеер на WebGL», Василика Климова, MoscowJS 21
 
Dmitry Bartalevich - "How to train your WebVR"
Dmitry Bartalevich - "How to train your WebVR"Dmitry Bartalevich - "How to train your WebVR"
Dmitry Bartalevich - "How to train your WebVR"
 
Promise me an Image... Антон Корзунов, Яндекс, MoscowJs 33
Promise me an Image... Антон Корзунов, Яндекс, MoscowJs 33Promise me an Image... Антон Корзунов, Яндекс, MoscowJs 33
Promise me an Image... Антон Корзунов, Яндекс, MoscowJs 33
 
создание HTML игр на элементе canvas
создание HTML игр на элементе canvasсоздание HTML игр на элементе canvas
создание HTML игр на элементе canvas
 
DUMP-2013 Frontend - Возможности последних WEB-стандартов в API Яндекс.Карт -...
DUMP-2013 Frontend - Возможности последних WEB-стандартов в API Яндекс.Карт -...DUMP-2013 Frontend - Возможности последних WEB-стандартов в API Яндекс.Карт -...
DUMP-2013 Frontend - Возможности последних WEB-стандартов в API Яндекс.Карт -...
 
проект Gpu digital lab швабе
проект Gpu digital lab швабепроект Gpu digital lab швабе
проект Gpu digital lab швабе
 
Обзор программных средств Майкрософт для графики и визуализации: коммерческой...
Обзор программных средств Майкрософт для графики и визуализации: коммерческой...Обзор программных средств Майкрософт для графики и визуализации: коммерческой...
Обзор программных средств Майкрософт для графики и визуализации: коммерческой...
 
"Погружение в Robolectric" Дмитрий Костырев (Avito)
"Погружение в Robolectric"  Дмитрий Костырев (Avito)"Погружение в Robolectric"  Дмитрий Костырев (Avito)
"Погружение в Robolectric" Дмитрий Костырев (Avito)
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в Django
 
Марина Степанова "Много объектов на карте"
Марина Степанова "Много объектов на карте"Марина Степанова "Много объектов на карте"
Марина Степанова "Много объектов на карте"
 
ObjectManager, или как работать с большим количеством объектов на карте, Мари...
ObjectManager, или как работать с большим количеством объектов на карте, Мари...ObjectManager, или как работать с большим количеством объектов на карте, Мари...
ObjectManager, или как работать с большим количеством объектов на карте, Мари...
 
Что API Карт забыл на сервере — Антон Корзунов
Что API Карт забыл на сервере — Антон КорзуновЧто API Карт забыл на сервере — Антон Корзунов
Что API Карт забыл на сервере — Антон Корзунов
 
Всеволод Шмыров, Яндекс
Всеволод Шмыров, ЯндексВсеволод Шмыров, Яндекс
Всеволод Шмыров, Яндекс
 
Пощупать 3д в браузере | Odessa Frontend Meetup #15
Пощупать 3д в браузере | Odessa Frontend Meetup #15Пощупать 3д в браузере | Odessa Frontend Meetup #15
Пощупать 3д в браузере | Odessa Frontend Meetup #15
 
Четвертое занятие курса iOS-разработки в ГУ-ВШЭ
Четвертое занятие курса iOS-разработки в ГУ-ВШЭЧетвертое занятие курса iOS-разработки в ГУ-ВШЭ
Четвертое занятие курса iOS-разработки в ГУ-ВШЭ
 
Делаем кроссбраузерные тесты поверх Webdriver
Делаем кроссбраузерные тесты поверх WebdriverДелаем кроссбраузерные тесты поверх Webdriver
Делаем кроссбраузерные тесты поверх Webdriver
 
Тестирование CSS-регрессий с Gemini — Сергей Татаринцев
Тестирование CSS-регрессий с Gemini — Сергей ТатаринцевТестирование CSS-регрессий с Gemini — Сергей Татаринцев
Тестирование CSS-регрессий с Gemini — Сергей Татаринцев
 
JavaScript. Уровень 3г. HTML5 API
JavaScript. Уровень 3г. HTML5 APIJavaScript. Уровень 3г. HTML5 API
JavaScript. Уровень 3г. HTML5 API
 
Squeek School #3
Squeek School #3Squeek School #3
Squeek School #3
 
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)
 

More from Ontico

One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...Ontico
 
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)Ontico
 
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)Ontico
 
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Ontico
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Ontico
 
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)Ontico
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Ontico
 
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...Ontico
 
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)Ontico
 
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)Ontico
 
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...Ontico
 
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...Ontico
 
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...Ontico
 
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)Ontico
 
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)Ontico
 
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)Ontico
 
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Ontico
 
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...Ontico
 
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...Ontico
 
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...Ontico
 

More from Ontico (20)

One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
 
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
 
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
 
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
 
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
 
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
 
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
 
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
 
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
 
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
 
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
 
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
 
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
 
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
 
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
 
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
 
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
 
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
 

Интерактивные 3D-карты своими руками / Александр Амосов (Avito)

  • 3. 3
  • 4. 4
  • 5. 5
  • 6. 6
  • 8. Почему 3D? • Это красиво 8
  • 9. Почему 3D? • Это красиво 9
  • 10. Почему 3D? • Это красиво • Это наглядно 10
  • 11. Почему 3D? • Это красиво • Это наглядно • Потому что я могу 11
  • 13. Создание модели • Найти моделлера (опционально) • Найти готовые модели (опционально) • Освоить 3D-редактор самому 13
  • 14. 14
  • 15. Blender • бесплатность • открытый код • постоянное развитие • кроссплатформенность • пользовательские скрипты на python 15
  • 16. 16
  • 18. 18
  • 19. 19
  • 20. 20
  • 21. import bpy geometry = bpy.data.meshes['place'] for obj in bpy.context.selected_objects: obj.rotation_euler.x = 0 obj.rotation_euler.y = 0 obj.data = geometry obj.location.z = 0 21
  • 22. 22
  • 24. 24
  • 25. 25
  • 26. 26
  • 27. OpenGL 1.5 OpenGL 2.0 OpenGL 3.3 OpenGL 4.5 OpenGL ES 1.1 OpenGL ES 2.0 OpenGL ES 3.0 Vulkan WebGL 1.0 WebGL 2.0 27 WebGL Next?
  • 28. 28
  • 29. 29
  • 30. 2D vs 3D [2] 30
  • 31. 2D 31 <canvas id="canvas" width="100" height="100"></canvas> <script> (function() { const canvas = document.getElementById('canvas'); const context = canvas.getContext('2d'); context.fillStyle = 'rgba(255, 0, 0, 1)'; context.fillRect(25, 25, 50, 50); }()); </script>
  • 32. 3D 32 <canvas id="canvas" width="100" height="100"></canvas> <script> (function() { const canvas = document.getElementById('canvas'); const gl = canvas.getContext('webgl'); // Инициализировать шейдеры // Создать программу // Создать вершинный буфер // Сохранить ссылку на буферный объект в атрибут // Вызвать отрисовку }()); </script>
  • 33. Вершинный шейдер 33 const vertexShaderSource = ` attribute vec4 position; void main() { gl_Position = position; } `; const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader);
  • 34. Фрагментный шейдер 34 const fragmentShaderSource = ` void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } `; const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, vertexShaderSource); gl.compileShader(fragmentShader);
  • 35. Программа 35 const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); gl.useProgram(program);
  • 36. Вершинный буфер 36 const vertices = new Float32Array([ -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5 ]); const vertexSize = 2; const vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); const attrPosition = gl.getAttribLocation(program, 'position'); gl.vertexAttribPointer(attrPosition, vertexSize, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(attrPosition);
  • 37. Отрисовка 37 const vertices = new Float32Array([ -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5 ]); const vertexSize = 2; // … gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertices.length / vertexSize);
  • 38. 38
  • 39. WebGL Programming Guide: Interactive 3D Graphics: Programming with WebGL Авторы: Коичи Мацуда, Роджер Ли 39
  • 41. WebGL Framework • Удобные абстракции • Краткий код • Никаких шейдеров (поначалу) 41
  • 42. var scene, camera, renderer, geometry, material, mesh; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = 1000; geometry = new THREE.BoxGeometry( 200, 200, 200 ); material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } ); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); } function animate() { requestAnimationFrame( animate ); mesh.rotation.y += 0.02; renderer.render( scene, camera ); } 42
  • 43. var scene, camera, renderer, geometry, material, mesh; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = 1000; geometry = new THREE.BoxGeometry( 200, 200, 200 ); material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } ); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); } function animate() { requestAnimationFrame( animate ); mesh.rotation.y += 0.02; renderer.render( scene, camera ); } 43
  • 44. 44
  • 45. 45
  • 46. var scene, camera, renderer, geometry, material, mesh; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = 1000; geometry = new THREE.BoxGeometry( 200, 200, 200 ); material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } ); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); } function animate() { requestAnimationFrame( animate ); mesh.rotation.y += 0.02; renderer.render( scene, camera ); } 46
  • 47. 47
  • 48. var scene, camera, renderer, geometry, material, mesh; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = 1000; geometry = new THREE.BoxGeometry( 200, 200, 200 ); material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } ); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); } function animate() { requestAnimationFrame( animate ); mesh.rotation.y += 0.02; renderer.render( scene, camera ); } 48
  • 49. var scene, camera, renderer, geometry, material, mesh; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = 1000; geometry = new THREE.BoxGeometry( 200, 200, 200 ); material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } ); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); } function animate() { requestAnimationFrame( animate ); mesh.rotation.y += 0.02; renderer.render( scene, camera ); } 49
  • 50. var scene, camera, renderer, geometry, material, mesh; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = 1000; geometry = new THREE.BoxGeometry( 200, 200, 200 ); material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } ); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); } function animate() { requestAnimationFrame( animate ); mesh.rotation.y += 0.02; renderer.render( scene, camera ); } 50
  • 51. var scene, camera, renderer, geometry, material, mesh; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = 1000; var loader = new THREE.ObjectLoader(); loader.load('model.json', function(mesh) { scene.add(mesh); }); ry = renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); } function animate() { requestAnimationFrame( animate ); mesh.rotation.y += 0.02; renderer.render( scene, camera ); } 51
  • 52. SVG Blender { "metadata": { "version": 4.4, "sourceFile": "model.blend", "generator": "io_three", "type": "Object" }, "geometries": [ ... ], "materials": [ ... ], "object": { ... } } JSON io_three 52
  • 55. Больше контроля 55 <script src="three/build/three.js"></script> <script src="three/examples/js/controls/OrbitControls.js"></script>
  • 56. var scene, camera, renderer, geometry, material, mesh; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = 1000; var loader = new THREE.ObjectLoader(); loader.load('model.json', function(mesh) { scene.add(mesh); }); renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); } function animate() { requestAnimationFrame( animate ); mesh.rotation.y += 0.02; renderer.render( scene, camera ); } 56
  • 57. var scene, camera, renderer, geometry, material, mesh; init(); animate(); function init() { scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = 1000; new THREE.OrbitControls(camera); var loader = new THREE.ObjectLoader(); loader.load('model.json', function(mesh) { scene.add(mesh); }); renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); } function animate() { requestAnimationFrame( animate ); mesh.rotation.y += 0.02; renderer.render( scene, camera ); } 57
  • 59. Interactive 3D Graphics Course With Three.js & WebGL https://www.udacity.com/course/interactive-3d-graphics--cs291 59
  • 61. Viewer 61 • Модель с запеченными тенями • Рейкастинг объектов • Спрайты для иконок
  • 64. Viewer UI Redux store 64 { type: 'SELECT_FLOOR', floor: 10 }
  • 66. 66
  • 67. Сглаживание 67 // WebGL: const gl = canvas.getContext("webgl", { antialias: true }); // three.js: const renderer = new THREE.WebGLRenderer({ antialias: true });
  • 68. На взлет 68 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); }
  • 69. Не рендерить все время 69 Начало движения камеры Конец движения камеры Запуск рендеринга Остановка рендеринга Изменение состояния приложения Отрендерить один кадр
  • 70. Raycasting 70 const raycaster = new THREE.Raycaster(); raycaster.setFromCamera(normalizedMouseCoordinates, camera); const intersects = raycaster.intersectObjects(objects);
  • 72. 72
  • 75. 75
  • 80. Instancing 80 • Сильно повышает производительность
  • 81. Instancing 81 • Сильно повышает производительность • Сложно https://goo.gl/zdaWZU
  • 82. 82
  • 85. Сжатые текстуры Плюсы: • В 4 раза меньше видеопамяти занимают Ограничения: • Разные форматы: DXT, PVRTC, ETC • Ухудшение картинки • Проблемы с прозрачностью • Больший объем файлов (но можно применить gzip) 85 https://goo.gl/swsgxR
  • 90. You are not alone 90
  • 91. Ссылки Курс по трехмерной графике на Udacity Книга "Программирование трехмерной графики" Примеры threejs Видео про рендеринг текста в WebGL (слайды) Видео про производительность WebGL (статья) 91

Editor's Notes

  1. no shaders
  2. Разобрать пример Добавить про controls
  3. Хотелось бы картинку как это происходит
  4. Меньше полигонов, текстуры проще, эффектов меньше