Случайны выбор дневника Раскрыть/свернуть полный список возможностей


Найдено 21558 сообщений
Cообщения с меткой

3d - Самое интересное в блогах

Следующие 30  »
iro4kan

Клипарт от babs-babs...осенний (код 1717)

Среда, 28 Сентября 2016 г. 10:46 (ссылка)

Это цитата сообщения babs-babs Оригинальное сообщение

shiela

1717

t color="red">babs.dreamland3 на Яндекс.Фотках





KIJK VERDER
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Почему не нужно преподавать 3ds Max детям в школе (и что нужно преподавать) – мнение Autodesk

Вторник, 27 Сентября 2016 г. 15:33 (ссылка)

Недавно мне попалась на глаза статья, повествующая о том, что детям должны преподавать в школе 3D технологии – был перечислен целый ряд продуктов, имеющих отношение к 3D – 3ds Max, Sketchup, Компас, Unity и др. Во-первых, спасибо большое ESolovey, мы в Autodesk согласны на 100 процентов, что 3D технологии преподавать очень нужно, и начинать лучше действительно со школы. Отдельное спасибо за рассказ о нескольких продуктах Autodesk – Max, Maya, Mudbox, TinkerCAD, Revit, Inventor. И, тем не менее, у нас есть, о чем предупредить учеников и их учителей, когда речь заходит о 3D, и есть что рассказать.











Дизайнеры или Инженеры? Некоторые предостережения


  1. Очень важно отделять 3D графику от 3D проектирования. Поскольку в школе дети учатся, чтобы обрести профессию, нужно понимать какой профессии мы их учим, преподавая те или иные науки. Преподавая 3D-графику, мы учим дизайнеров. Преподавая 3D-проектирование, мы учим инженеров.

  2. Дизайнеры, конечно, тоже нужны. Но потребность в инженерных кадрах ощущается намного острее. Мы можем судить об этом по нашим клиентам. Поэтому давайте исходить из того, что учить нужно либо инженеров, либо универсалов.

  3. В связи с этим я сейчас попробую классифицировать самые популярные инструменты по трем категориям – «графика», «проектирование» и «для индивидуального творчества».



a. 3D проектирование


  • Компас 3D

  • Solidworks

  • Inventor

  • Catia

  • NX

  • и др.



b. 3D графика


  • 3Ds Max

  • Maya

  • Mudbox

  • Blender

  • ZBrush

  • и др



c. 3D для индивидуального творчества


  • TinkerCAD

  • Линейка продуктов 123D

  • Sketchup

  • и др.



*Есть еще 3D САПР для архитектурного проектирования, но давайте оставим эту тему для отдельной статьи. Тема сложная и интересная, только у Autodesk есть целый ряд программных продуктов в этой области (Revit, Navisworks, Infraworks и др)

**Средства производства чертежей тоже пусть будут вне этого обзора. К ним относится в первую очередь AutoCAD (Формально его можно было бы отнести в предыдущую категорию, т.к. AutoCAD может делать и 3D (если это не AutoCAD LT), но все же в первую очередь это средство производства чертежей.)



Почему все вышеперечисленные инструменты не нужно преподавать в школе


  1. Да, инструменты для 3D графики также позволяют делать моделирование, но это изначально другие инструменты по своей сути. Очень хорошие инструменты, но другие. В 3ds Max не сделать изделие для промышленного выпуска (нет, если конечно задаться целью, то можно, в таком случае можно и в Paint нарисовать), зато можно сделать крутую визуализацию.

  2. Инструменты для индивидуального творчества можно было бы назвать «для начинающих». Но тут важно понимать, что развитие для этих начинающих возможно будет только с переходом на совсем иные продукты. Другими словами, эти продукты хороши для младших детей, но они никогда не станут профессиональными инструментами.

  3. Сложным софтом для 3D проектирования можно перегрузить детей



Правильные критерии выбора 3D инструментов для старшеклассников:


  1. должен учить в первую очередь 3D проектированию, а не только 3D графике

  2. прост в освоении

  3. полезен для будущей профессии (не детская игрушка)



Рекомендации Autodesk по инструментам:

Детям до 12-14 лет можно взять инструмент из списка «для индивидуального творчества».

Для старшеклассников самый подходящий инструмент – Fusion 360. Это относительно новый продукт в линейке Autodesk, поэтому на рынке он известен куда меньше чем 3ds Max, Inventor или AutoCAD, но у него есть свои преимущества:


  • Простота освоения – первый простой проект можно сделать за один урок

  • В то же время универсальность и широкий спектр возможностей:

    — Твердотельное и сплайновое моделирование

    — Сборки

    — Инженерный анализ

    — Рендеринг и анимация

    — Встроенные инструменты 3D печати

    — CAM-модуль (написание программ для ЧПУ станков)

  • Облачное ядро – ученик легко продолжит работу дома, т.к. все хранится в облаке

  • Минимальные требования к железу (все задачи, которые нагружают оборудование – рендеринг, анализ – могут совершаться через облако, при этом геометрия строится через клиент локально, т.е. система не требует непрерывного подключения к интернету)

  • Работает на PC, Mac, планшетах, есть также вьюер для мобильных





Сложности:

Продукт довольно новый, поэтому мало кто из преподавателей с ним знаком. Хотя в вузах его уже знают и любят. Самые передовые в этом смысле — МАМИ, ИТМО, МГХПА им Строганова. МГТУ им Баумана, Британская Школа Дизайна и еще ряд вузов – также использую, но менее активно. Чем мы можем помочь:

— Если вы преподаватель и у вас есть желание изучить этот продукт – пришлите мне письмо на Natalia.Raykova@autodesk.com. Мы периодически устраиваем обучающие мероприятия и локализуем учебные курсы, можем вас пригласить;

— Также можно найти бесплатный онлайн курс Зимней школы Fusion 360здесь;

— Скоро также будет локализован соответствующий курс на Udemy. Пока он доступен на английском языке.





На скриншоте изображен проект, который пользователь без опыта может сделать за первое занятие. Он рассматривается в первом модуле Зимней школы.



Как получить инструменты бесплатно:

Для учебных заведений Fusion 360 бесплатен, для стартапов, кстати, тоже (если продукт еще не продается и оборот не достиг 100 т. долл. в год) – надо просто скачать демо и активировать из интерфейса как образовательную или стартаперскую версию, для коммерческого использования стоит денег, но все равно значительно дешевле чем Max, AutoCAD или Inventor.



Вместо послесловия:

До сих пор не могу забыть случай, когда на одной выставке познакомилась с директором стартапа. Они разрабатывали один симпатичный персональный гаджет. На мой вопрос «в чем вы его проектировать будете?» говорит «мы уже спроектировали, я фрилансера нашел – он мне прислал модель, в 3ds Max, кажется». Я не выдаю разочарования и продолжаю диалог. Чуть позже он замечает «но мы еще не знаем, какая там будет батарейка и как ее туда разместить». Занавес.



*** Данный пост не ставит целью сравнить Autodesk с конкурентными решениями. Поскольку я являюсь сотрудником Autodesk, мое представление о позиционировании продуктов других производителей может быть неточным. Любые комментарии других компаний всячески приветствуются, при необходимости внесу уточнения


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/311148/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Перевод] Создание шейдеров на основе Babylon.js и WebGL: теория и примеры

Вторник, 27 Сентября 2016 г. 13:38 (ссылка)

Во время своего доклада на второй день конференции Build 2014 евангелисты Microsoft Стивен Гуггенхаймер и Джон Шевчук рассказали о реализации поддержки Babylon.js для Oculus Rift. Одним из ключевых пунктов их демонстрации было упоминание разработанной нами технологии имитации линз:





Я также присутствовал на докладе Фрэнка Оливье и Бена Констебля на тему использования графики в IE с применением Babylon.js.



Эти доклады напомнили мне об одном вопросе, который мне часто задают в отношении Babylon.js: «Что вы подразумеваете под шейдерами?» Я решил посвятить этому вопросу целую статью с целью объяснить принцип работы шейдеров и привести несколько примеров их основных типов.

Этот перевод является частью серии статей для разработчиков от компании Microsoft.



Теория



Прежде чем начинать наши опыты, нужно понять, как всё функционирует.



Работая с аппаратно ускоренной 3D графикой, мы имеем дело с двумя разными процессорами: центральным (CPU) и графическим (GPU). Графический процессор – это всего лишь разновидность крайне специализированного центрального процессора.



GPU – это конечный автомат, настраиваемый посредством CPU. К примеру, именно CPU дает GPU команду отображать линии вместо треугольников, включить прозрачность и т. д.



Как только все состояния будут настроены, CPU определит, что нужно рендерить, исходя из двух основных составляющих: геометрии, которая рассчитывается на основе списка точек или вершин (хранятся в массиве под названием буфер вершин), и списка индексов – граней или треугольников, которые хранятся в буфере индексов.



Наконец, CPU определит, как рендерить геометрию, и специально для этого задаст шейдеры для GPU. Шейдеры представляют собой фрагмент кода, выполняемого GPU для всех вершин и пикселей, которые нужно отрендерить.



Вершина – это своего рода точка в 3D пространстве (в отличие от точки в 2D пространстве).



Существует 2 вида шейдеров: вершинные и пиксельные (фрагментные) шейдеры.



Графический пайплайн



Прежде чем перейти непосредственно к шейдерам, сделаем еще одно небольшое отступление. Для отображения пикселей GPU получает из CPU данные геометрии.



С помощью буфера индексов, содержащего список индексов вершин, 3 вершины объединяются в треугольник. Каждая запись в буфере индексов соответствует номеру вершины в буфере вершин (это позволяет избежать дублирования вершин).



К примеру, буфер индексов на примере ниже – это список из двух граней: [1 2 3 1 3 4]. Первая грань содержит вершины 1, 2 и 3. Вторая грань содержит вершины 1, 3 и 4. Таким образом, в данном случае геометрия состоит из четырех вершин:





Vertex — Вершина

Vertex Buffer — Буфер вершин

Index Bufer — Буфер индексов

Face — Грань


Вершинный шейдер выполняется на каждой вершине треугольника. Основное предназначение вершинного шейдера – отобразить пиксель для каждой вершины (то есть выполнить проекцию 3D вершины на 2D экран).





Используя эти 3 пикселя (задающие параметры 2D треугольника на экране), GPU проанализирует все относящиеся к пикселю (по крайней мере, к его положению) значения и применит пиксельный шейдер, чтобы сгенерировать цвет для каждого пикселя данного треугольника.





То же самое выполняется для всех граней в буфере индексов.



GPU очень эффективен при выполнении параллельных процессов и поэтому без труда может обрабатывать множество граней одновременно, достигая при этом высокой производительности.



GLSL



Как было сказано ранее, для рендеринга треугольников графическому процессору потребуются 2 шейдера: вершинный и пиксельный. Оба пишутся на специальном языке под названием GLSL (Graphics Library Shader Language), который немного похож на C.



Специально для Internet Explorer 11 мы разработали компилятор, преобразовывающий GLSL в HLSL (High Level Shader Language) – шейдерный язык DirectX 11. Это позволило нам повысить безопасность кода шейдера:





Вот пример простого вершинного шейдера:



precision highp float;

// Attributes
attribute vec3 position;
attribute vec2 uv;

// Uniforms
uniform mat4 worldViewProjection;

// Varying
varying vec2 vUV;

void main(void) {
gl_Position = worldViewProjection * vec4(position, 1.0);

vUV = uv;
}




Структура вершинного шейдера



Вершинный шейдер содержит следующие элементы:




  • Атрибуты: Атрибут определяет часть вершины. По умолчанию вершина должна иметь, по крайней мере, данные о положении (vector3:x, y, z). Но вы, как разработчик, можете предоставить больше данных. К примеру, в коде выше есть vector2 под названием uv (координаты текстуры, позволяющие нам применять 2D текстуру на 3D объект).




  • Uniform-переменные: Определяются центральным процессором и используются шейдером. Единственная uniform-переменная, которая есть у нас в данном случае, – это матрица, используемая для проекции положения вершины (x, y, z) на экран (x, y).




  • Varying-переменные: Представляют собой значения, которые создаются вершинным шейдером и передаются в пиксельный. В нашем случае вершинный шейдер передаст в пиксельный шейдер значение vUV (простая копия uv). Следовательно, здесь определяются координаты текстуры и положение пикселя. GPU добавит эти значения, а использовать их будет непосредственно пиксельный шейдер.




  • main: Функция main() – это код, который выполняется в GPU для каждой вершины. Он должен как минимум давать значение для gl_position (положение текущей вершины на экране).



Как видно из примера выше, нет ничего сложного в вершинном шейдере. Он генерирует системную переменную (начинается на gl_) под названием gl_position, чтобы определить положение конкретного пикселя, а также задает varying-переменную под названием vUV.



Волшебство в основе матриц



Матрица в нашем шейдере называется worldViewProjection. Она проецирует положение вершины в переменную gl_position. Но как же нам получить значение этой матрицы? Поскольку это uniform-переменная, нам нужно определить её на стороне CPU (с помощью JavaScript).



Это трудный для понимания аспект работы с 3D графикой. Нужно неплохо разбираться в сложных математических вычислениях (или пользоваться 3D движком вроде Babylon.js, о чем мы поговорим позже).



Матрица worldViewProjection состоит из трех отдельных матриц:





В результате получается матрица, позволяющая преобразовывать 3D вершины в 2D пиксели, учитывая при этом позицию точки обзора и всё, что относится к положению, масштабу и повороту текущего объекта.



Задача 3D дизайнера – создать эту матрицу и поддерживать актуальность её данных.



И снова шейдеры



После того как вершинный шейдер выполнится на каждой вершине (то есть 3 раза), мы получим 3 пикселя с правильным значением vUV и gl_position. Далее GPU перенесет эти значения на каждый пиксель внутри треугольника, образованного тремя основными пикселями.



Затем к каждому пикселю будет применен пиксельный шейдер:



precision highp float;
varying vec2 vUV;
uniform sampler2D textureSampler;

void main(void) {
gl_FragColor = texture2D(textureSampler, vUV);
}


Структура пиксельного (или фрагментного) шейдера



По своей структуре пиксельный шейдер похож на вершинный:




  • Varying-переменные: Представляют собой значения, которые создаются вершинным шейдером и передаются в пиксельный шейдер. В нашем случае пиксельный шейдер получит из вершинного шейдера значение vUV.




  • Uniform-переменные: Определяются центральным процессором и используются шейдером. Единственная uniform-переменная, которая есть у нас в данном случае – это семплер, который нужен для считывания цветов текстуры.




  • main: Функция main – это код, который выполняется в GPU для каждого пикселя. Он должен как минимум давать значение для gl_FragColor (цвет текущего пикселя).



Этот пиксельный шейдер очень простой: он считывает цвет текстуры, используя координаты текстуры из вершинного шейдера (который, в свою очередь, получил их из вершины).



Вот что получилось в итоге. Рендеринг выполняется в реальном времени; вы можете двигать сферу мышкой.



Чтобы получить такой результат, нужно хорошенько поработать с кодом WebGL. Конечно, WebGL – это очень мощный API. Но он низкоуровневый, поэтому придется всё делать самостоятельно: от создания буфера до определения структуры вершин. Вам также нужно будет выполнять множество математических вычислений, настраивать состояния, управлять загрузкой текстуры и так далее.



Слишком сложно? BABYLON.ShaderMaterial спешит на помощь



Я знаю, о чем вы подумали: «Шейдеры – это, конечно, круто, но я не хочу разбираться во всех тонкостях WebGL и самостоятельно производить все вычисления».



Не проблема! Именно поэтому мы и создали Babylon.js.



Вот как выглядит код для той же сферы в Babylon.js. Для начала вам понадобится простая веб-страница:






















Шейдеры здесь задаются тегами script. В Babylon.js их также можно задавать в отдельных файлах формата .fx.



Babylon.js доступен для скачивания по ссылке здесь или в нашем репозитории на GitHub. Для получения доступа к объекту BABYLON.StandardMaterial нужна версия 1.11 и выше.



Наконец, основной JavaScript-код выглядит следующим образом:

«use strict»;



document.addEventListener("DOMContentLoaded", startGame, false);

function startGame() {
if (BABYLON.Engine.isSupported()) {
var canvas = document.getElementById("renderCanvas");
var engine = new BABYLON.Engine(canvas, false);
var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("Camera", 0, Math.PI / 2, 10, BABYLON.Vector3.Zero(), scene);

camera.attachControl(canvas);

// Creating sphere
var sphere = BABYLON.Mesh.CreateSphere("Sphere", 16, 5, scene);

var amigaMaterial = new BABYLON.ShaderMaterial("amiga", scene, {
vertexElement: "vertexShaderCode",
fragmentElement: "fragmentShaderCode",
},
{
attributes: ["position", "uv"],
uniforms: ["worldViewProjection"]
});
amigaMaterial.setTexture("textureSampler", new BABYLON.Texture("amiga.jpg", scene));

sphere.material = amigaMaterial;

engine.runRenderLoop(function () {
sphere.rotation.y += 0.05;
scene.render();
});
}
};


Как видно, я использую BABYLON.ShaderMaterial, чтобы избавиться от необходимости компилировать шейдеры, линковать их или управлять ими.



При создании объекта BABYLON.ShaderMaterial нужно указать элемент DOM, используемый для хранения шейдеров или базовое имя файлов, в которых находятся шейдеры. Для второго варианта потребуется также создать по файлу для каждого шейдера, используя следующий принцип именования: basename.vertex.fx и basename.fragment.fx. Затем нужно будет создать материал вроде этого:



var cloudMaterial = new BABYLON.ShaderMaterial("cloud", scene, "./myShader",
{
attributes: ["position", "uv"],
uniforms: ["worldViewProjection"]
});


Нужно также указать имена любых используемых атрибутов и uniform-переменных. Затем можно напрямую задать значения uniform-переменных и семплеров с помощью функций setTexture, setFloat, setFloats, setColor3, setColor4, setVector2, setVector3, setVector4 и setMatrix.



Довольно просто, правда?



Помните матрицу worldViewProjection? С Babylon.js и BABYLON.ShaderMaterial вам не придется о ней волноваться. Объект BABYLON.ShaderMaterial вычислит всё автоматически, так как мы объявляем матрицу в списке uniform-переменных.



Объект BABYLON.ShaderMaterial может самостоятельно управлять следующими матрицами:




  • world;

  • view;

  • projection;

  • worldView;

  • worldViewProjection.



Никаких сложных расчетов. К примеру, при каждом выполнении sphere.rotation.y += 0.05 матрица world данной сферы генерируется и передается в GPU.



CYOS: Создайте шейдер своими руками



Мы пойдем еще дальше и создадим страницу, на которой можно будет динамически редактировать шейдеры и наблюдать за результатом в реальном времени. Для этого нам понадобится прежний код, а также объект BABYLON.ShaderMaterial для компиляции и выполнения созданных шейдеров.



Я использовал для CYOS редактор кода под названием ACE. Он невероятно удобен и оснащен функцией подсветки синтаксиса.



В поле Templates можно выбирать предустановленные шейдеры, мы поговорим о них немного позже. Вы также можете изменить 3D объект, используемый для предпросмотра шейдеров в поле Meshes.



Кнопка Compile используется для создания нового объекта BABYLON.ShaderMaterial из шейдеров. Вот её код:




// Compile
shaderMaterial = new BABYLON.ShaderMaterial("shader", scene, {
vertexElement: "vertexShaderCode",
fragmentElement: "fragmentShaderCode",
},
{
attributes: ["position", "normal", "uv"],
uniforms: ["world", "worldView", "worldViewProjection"]
});

var refTexture = new BABYLON.Texture("ref.jpg", scene);
refTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
refTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;

var amigaTexture = new BABYLON.Texture("amiga.jpg", scene);

shaderMaterial.setTexture("textureSampler", amigaTexture);
shaderMaterial.setTexture("refSampler", refTexture);
shaderMaterial.setFloat("time", 0);
shaderMaterial.setVector3("cameraPosition", BABYLON.Vector3.Zero());
shaderMaterial.backFaceCulling = false;

mesh.material = shaderMaterial;


Подозрительно просто, правда? Итак, осталось только получить 3 предварительно вычисленных матрицы: world, worldView и worldViewProjection. Данные о вершинах будут содержать значения положения, нормали и координат текстур. Также загрузятся 2 следующие текстуры:





amiga.jpg





ref.jpg



А это renderLoop, где я обновляю 2 uniform-переменные:




  • переменную time – чтобы получать забавные анимации;

  • переменную cameraPosition – чтобы получать данные о положении камеры в шейдерах (что очень пригодится при расчете освещения);



engine.runRenderLoop(function () {
mesh.rotation.y += 0.001;

if (shaderMaterial) {
shaderMaterial.setFloat("time", time);
time += 0.02;

shaderMaterial.setVector3("cameraPosition", camera.position);
}

scene.render();
});


К тому же, CYOS теперь доступен и для Windows Phone благодаря проделанной нами работе для Windows Phone 8.1:





Basic



Начнем с базового шейдера в CYOS. Мы уже рассматривали нечто похожее. Этот шейдер высчитывает gl_position и использует координаты текстуры, чтобы получить цвет для каждого пикселя.



Чтобы высчитать положение пикселя, нужна матрица worldViewProjection и положение вершины:



precision highp float;

// Attributes
attribute vec3 position;
attribute vec2 uv;

// Uniforms
uniform mat4 worldViewProjection;

// Varying
varying vec2 vUV;

void main(void) {
gl_Position = worldViewProjection * vec4(position, 1.0);

vUV = uv;
}


Координаты текстуры (uv) передаются в пиксельный шейдер неизмененными.



Обратите внимание на первую строчку: precision mediump float; – её обязательно нужно добавить в вершинный и пиксельный шейдер для правильной работы в Chrome. Она отвечает за то, чтобы для улучшения производительности не использовались числа высокой точности.



С пиксельным шейдером всё обстоит еще проще: нужно всего лишь использовать координаты текстуры и получить цвет текстуры:



precision highp float;

varying vec2 vUV;

uniform sampler2D textureSampler;

void main(void) {
gl_FragColor = texture2D(textureSampler, vUV);
}


Как было видно ранее, uniform-переменная textureSampler заполнена текстурой amiga, поэтому результат выглядит так:





Black and white



Перейдем ко второму шейдеру, черно-белому. Он будет использовать параметры предыдущего, но в черно-белом режиме рендеринга. Оставим прежние настройки вершинного шейдера и внесем небольшие изменения в код пиксельного.



Самый простой способ добиться данного эффекта – взять всего один компонент, например, как показано ниже:



precision highp float;

varying vec2 vUV;

uniform sampler2D textureSampler;

void main(void) {
gl_FragColor = vec4(texture2D(textureSampler, vUV).ggg, 1.0);
}


Мы использовали .ggg вместо .rgb (в компьютерной графике эта операция называется swizzle). Но если нужно получить настоящий черно-белый эффект, лучше всего вычислить относительную яркость, которая учитывает все компоненты цвета:



precision highp float;

varying vec2 vUV;

uniform sampler2D textureSampler;

void main(void) {
float luminance = dot(texture2D(textureSampler, vUV).rgb, vec3(0.3, 0.59, 0.11));
gl_FragColor = vec4(luminance, luminance, luminance, 1.0);
}


Скалярное произведение вычисляется следующим образом:



result = v0.x * v1.x + v0.y * v1.y + v0.z * v1.z


В нашем случае:



luminance = r * 0.3 + g * 0.59 + b * 0.11 


(эти значения рассчитываются с учетом того, что человеческий глаз более чувствителен к зеленому цвету)





Cell shading



Следующий по списку – шейдер с заливкой ячеек, он немного сложнее.



В данном случае нам потребуется добавить в пиксельный шейдер положение вершины и нормаль к вершине. Вершинный шейдер будет выглядеть так:



precision highp float;

// Attributes
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;

// Uniforms
uniform mat4 world;
uniform mat4 worldViewProjection;

// Varying
varying vec3 vPositionW;
varying vec3 vNormalW;
varying vec2 vUV;

void main(void) {
vec4 outPosition = worldViewProjection * vec4(position, 1.0);
gl_Position = outPosition;

vPositionW = vec3(world * vec4(position, 1.0));
vNormalW = normalize(vec3(world * vec4(normal, 0.0)));

vUV = uv;
}


Учите, что данные положения вершины и нормали к вершине передаются неизмененными, потому нам также нужно применить матрицу world, чтобы учитывать вращение объекта.



Вот как будет выглядеть пиксельный шейдер:



precision highp float;

// Lights
varying vec3 vPositionW;
varying vec3 vNormalW;
varying vec2 vUV;

// Refs
uniform sampler2D textureSampler;

void main(void) {
float ToonThresholds[4];
ToonThresholds[0] = 0.95;
ToonThresholds[1] = 0.5;
ToonThresholds[2] = 0.2;
ToonThresholds[3] = 0.03;

float ToonBrightnessLevels[5];
ToonBrightnessLevels[0] = 1.0;
ToonBrightnessLevels[1] = 0.8;
ToonBrightnessLevels[2] = 0.6;
ToonBrightnessLevels[3] = 0.35;
ToonBrightnessLevels[4] = 0.2;

vec3 vLightPosition = vec3(0, 20, 10);

// Light
vec3 lightVectorW = normalize(vLightPosition - vPositionW);

// diffuse
float ndl = max(0., dot(vNormalW, lightVectorW));

vec3 color = texture2D(textureSampler, vUV).rgb;

if (ndl > ToonThresholds[0])
{
color *= ToonBrightnessLevels[0];
}
else if (ndl > ToonThresholds[1])
{
color *= ToonBrightnessLevels[1];
}
else if (ndl > ToonThresholds[2])
{
color *= ToonBrightnessLevels[2];
}
else if (ndl > ToonThresholds[3])
{
color *= ToonBrightnessLevels[3];
}
else
{
color *= ToonBrightnessLevels[4];
}

gl_FragColor = vec4(color, 1.);
}


Этот шейдер предназначен для симуляции света, поэтому, чтобы не вычислять плавное затенение по всей поверхности объекта, мы будем высчитывать интенсивность света на основе нескольких порогов яркости. Например, если интенсивность равна от 1 (максимум) до 0.95, цвет объекта, взятый из текстуры, будет накладываться напрямую, без изменений. Если же интенсивность будет от 0.95 до 0.5, к значению цвета будет применен множитель 0.8 и так далее.



В итоге процесс создания такого шейдера можно разбить на 4 шага:




  • Сначала объявляем пороги яркости и константы для каждой степени интенсивности.

  • Рассчитываем освещение на основе алгоритма Фонга (исходя из соображения, что источник света не движется).



vec3 vLightPosition = vec3(0, 20, 10);

// Light
vec3 lightVectorW = normalize(vLightPosition - vPositionW);

// diffuse
float ndl = max(0., dot(vNormalW, lightVectorW));


Интенсивность света, падающего на пиксель, зависит от угла между нормалью к вершине и направлением света.




  • Получаем цвет текстуры для пикселя.

  • Проверяем порог яркости и применяем константу соответствующей степени интенсивности.



В итоге мы получим нечто похожее на мультипликационный эффект:





Phong



Мы уже использовали алгоритм Фонга в предыдущем примере. Теперь рассмотрим его подробнее.



С вершинным шейдером всё будет довольно просто, так как основная часть работы придется на пиксельный:



precision highp float;

// Attributes
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;

// Uniforms
uniform mat4 worldViewProjection;

// Varying
varying vec3 vPosition;
varying vec3 vNormal;
varying vec2 vUV;

void main(void) {
vec4 outPosition = worldViewProjection * vec4(position, 1.0);
gl_Position = outPosition;

vUV = uv;
vPosition = position;
vNormal = normal;
}


Согласно алгоритму, нужно вычислить диффузную и зеркальную составляющие, используя направления света и нормаль к вершине:



precision highp float;

// Varying
varying vec3 vPosition;
varying vec3 vNormal;
varying vec2 vUV;

// Uniforms
uniform mat4 world;

// Refs
uniform vec3 cameraPosition;
uniform sampler2D textureSampler;

void main(void) {
vec3 vLightPosition = vec3(0, 20, 10);

// World values
vec3 vPositionW = vec3(world * vec4(vPosition, 1.0));
vec3 vNormalW = normalize(vec3(world * vec4(vNormal, 0.0)));
vec3 viewDirectionW = normalize(cameraPosition - vPositionW);

// Light
vec3 lightVectorW = normalize(vLightPosition - vPositionW);
vec3 color = texture2D(textureSampler, vUV).rgb;

// diffuse
float ndl = max(0., dot(vNormalW, lightVectorW));

// Specular
vec3 angleW = normalize(viewDirectionW + lightVectorW);
float specComp = max(0., dot(vNormalW, angleW));
specComp = pow(specComp, max(1., 64.)) * 2.;

gl_FragColor = vec4(color * ndl + vec3(specComp), 1.);
}


В предыдущем примере мы использовали только диффузную составляющую, так что осталось только добавить зеркальную. Эта картинка из статьи на Википедии объясняет принцип работы шейдера:





Автор: Brad Smith aka Rainwarrior



Результат:





Discard



Для этого типа шейдера я бы хотел ввести новое понятие: ключевое слово discard. Такой шейдер будет игнорировать любой пиксель не красного цвета, создавая в результате иллюзию полого объекта.



Вершинный шейдер будет в данном случае таким же, как и для базового шейдера:



precision highp float;

// Attributes
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;

// Uniforms
uniform mat4 worldViewProjection;

// Varying
varying vec2 vUV;

void main(void) {
gl_Position = worldViewProjection * vec4(position, 1.0);

vUV = uv;
}


Пиксельный шейдер будет проверять цвет каждого пикселя и использовать ключевое слово discard, когда, например, значение зеленого компонента будет слишком большим:



precision highp float;

varying vec2 vUV;

// Refs
uniform sampler2D textureSampler;

void main(void) {
vec3 color = texture2D(textureSampler, vUV).rgb;

if (color.g > 0.5) {
discard;
}

gl_FragColor = vec4(color, 1.);
}




Результат выглядит весьма забавно:





Wave



Пожалуй, мы уже наигрались с пиксельными шейдерами. Теперь мне хотелось бы уделить больше внимания вершинным шейдерам.



Для данного примера нам пригодится пиксельный шейдер с затенением по Фонгу.



В вершинном шейдере мы используем uniform-переменную под названием time, чтобы получить динамические значения. Эта переменная будет генерировать волну, в которой вершины будут менять свое положение:



precision highp float;

// Attributes
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;

// Uniforms
uniform mat4 worldViewProjection;
uniform float time;

// Varying
varying vec3 vPosition;
varying vec3 vNormal;
varying vec2 vUV;

void main(void) {
vec3 v = position;
v.x += sin(2.0 * position.y + (time)) * 0.5;

gl_Position = worldViewProjection * vec4(v, 1.0);

vPosition = position;
vNormal = normal;
vUV = uv;
}


Синус умножается на position.y, и это дает следующий результат:





Spherical Environment Mapping



На создание данного шейдера нас вдохновил этот прекрасный тутор. Рекомендую ознакомиться с ним самостоятельно, а затем посмотреть шейдер Wave в CYOS.





Fresnel



И напоследок мой любимый шейдер, Fresnel. Он меняет интенсивность в зависимости от угла между направлением просмотра и нормалью к вершине.



Вершинный шейдер здесь точно такой же, как и для шейдера с заливкой ячеек, и мы легко можем вычислить необходимое для пиксельного шейдера значение френелевского отражения (для определения направления просмотра данные нормали и положения камеры можно использовать):



precision highp float;

// Lights
varying vec3 vPositionW;
varying vec3 vNormalW;

// Refs
uniform vec3 cameraPosition;
uniform sampler2D textureSampler;

void main(void) {
vec3 color = vec3(1., 1., 1.);
vec3 viewDirectionW = normalize(cameraPosition - vPositionW);

// Fresnel
float fresnelTerm = dot(viewDirectionW, vNormalW);
fresnelTerm = clamp(1.0 - fresnelTerm, 0., 1.);

gl_FragColor = vec4(color * fresnelTerm, 1.);
}




Ваш шейдер



Думаю, теперь вы готовы создать собственный шейдер. Можете смело делиться результатами экспериментов в комментариях ниже.



Вот несколько дополнительных ссылок для тех, кто хочет изучить материал глубже:



» Репозиторий Babylon.js;

»Форум Babylon.js;

» CYOS;

» Статья о GLSL на Википедии;

» Документация по GLSL.


И еще несколько моих статей на ту же тему:



» Introduction to WebGL 3D with HTML5 and Babylon.JS;

» Cutting Edge Graphics in HTML.


А также уроки по JavaScript от нашей команды:



» Practical Performance Tips to Make your HTML/JavaScript Faster (серия уроков из семи частей, затрагивающая множество тем: от адаптивного дизайна до оптимизации производительности и казуальных игр);

» The Modern Web Platform Jump Start (основы HTML, CSS и JS);

» Developing Universal Windows App with HTML and JavaScript Jump Start (используйте уже написанный JS-код, чтобы создать приложение).


И, конечно же, вы всегда можете воспользоваться некоторыми нашими бесплатными инструментами для оптимизации работы в вебе: Visual Studio Community, пробную версию Azure и кроссбраузерные инструменты для тестирования на Mac, Linux или Windows.
Original source: habrahabr.ru.

https://habrahabr.ru/post/311138/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
kseniasamohina

Чем хорош самый популярный телевизор на MagaZilla?

Пятница, 24 Сентября 2016 г. 00:47 (ссылка)
md-eksperiment.org/post/201...-magazilla

Телевизор LG 55UF950V обладает весьма внушительными характеристиками: он имеет 4K-разрешение, встроенную аудиосистему мощностью 60 Вт и поддерживает воспроизведение 3D. И этими пунктами его преимущества не ограничиваются.
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
plushewa

Чем хорош самый популярный телевизор на MagaZilla?

Пятница, 24 Сентября 2016 г. 00:12 (ссылка)
md-eksperiment.org/post/201...-magazilla


Телевизор LG 55UF950V обладает весьма внушительными характеристиками: он имеет 4K-разрешение, встроенную аудиосистему мощностью 60 Вт и поддерживает воспроизведение 3D. И этими пунктами его преимущества не ограничиваются.

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
Понтифик_Иванов

Чем хорош самый популярный телевизор на MagaZilla?

Пятница, 24 Сентября 2016 г. 00:00 (ссылка)
md-eksperiment.org/post/201...-magazilla

Телевизор LG 55UF950V обладает весьма внушительными характеристиками: он имеет 4K-разрешение, встроенную аудиосистему мощностью 60 Вт и поддерживает воспроизведение 3D. И этими пунктами его преимущества не ограничиваются.
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество

Следующие 30  »

<3d - Самое интересное в блогах

Страницы: [1] 2 3 ..
.. 10

LiveInternet.Ru Ссылки: на главную|почта|знакомства|одноклассники|фото|открытки|тесты|чат
О проекте: помощь|контакты|разместить рекламу|версия для pda