Шейдер для жука

10 октября 2014 г., 0:06:51

Шейдер для жука

снизу фотографии настоящих жуков, сверху — моя реализация

Продолжение предыдущей статьи, на этот раз пишем шейдер.

Иризация


Итак в чем же особенность панциря такого жука? Если смотреть на него под разными углами — он будет изменять свой цвет. Как компакт диск. Такой цвет удобнее всего представлять в цветовой модели HSV, а конкретно нас интересует параметр Hue или цветовой тон, который изменяется вот в таком диапазоне:
Шейдер для жука

Если взять угол между вектором направления взгляда и нормалью к поверхности панциря, то получим число, которое можно использовать в качестве параметра Hue в вышеописанной модели. С дополнительной корректировкой по диапазону можно добиться нужного результата. Так же диапазон можно корректировать через текстуру, об этой карте смещений я писал в предыдущей статье. Примерный алгоритм:

  1. Для текущего фрагмента определяем вектор направления взгляда eyeDir
  2. Вычисляем скалярное произведение между вектором направления взгляда и нормалью к поверхности angle=dot(normal, eyeDir)
  3. Дополнительный шаг для повышения реализма — возводим получившийся угол в квадрат angle=pow(angle, 2.0)
  4. Используем угол для определения тона, выбираем цветовой диапазон hue=angle*hueRange+hueAverage, где hueRange — диапазон, hueAverage — смещение
  5. Дополнительно вычисляем смещение для текущего фрагмента из соответствующей текстуры: hue-=shift
  6. Выбираем оставшиеся два параметра цветовой модели HSV и конвертируем ее в RGB: color=hsv2rgb(hue, saturation, value)


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

// код конвертации был взят отсюда: http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
vec3 hsv2rgb(float h, float s, float v) {
	vec4 k = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);
	vec3 p = abs(fract(vec3(h)+k.xyz)*6.0-k.www);
	return v*mix(k.xxx, clamp(p-k.xxx, 0.0, 1.0), s);
}

const float iridescenceOpacity = 0.6;
const float hsvSaturation = 0.7;
const float hsvValue = 0.8;
const float addIridescenceValue = 0.2;

void main() {
	...
	float hue = (1.0-pow(dot(normal, eyeDir), 2.0))*hueRange+hueAverage;
	hue -= (1.0-dataTex.a)*addIridescenceValue;
	vec3 diffuse = hsv2rgb(hue, hsvSaturation, hsvValue)*iridescenceOpacity;
	...
}


На этом собственно и заканчивается часть с определением переливающейся части цвета. Остальная часть цвета вычисляется стандартно на основе карт ao, отражений и освещенности. Как видно алгоритм простой и его можно применять практически к любой поверхности и материалу.

Хотя есть один нюанс — у жука на фотографии отражение окружения на панцире размыто. У меня в шейдере для отражений используется cubemap, что бы отражение было размытым можно размыть кубмапу или уменьшить ее разрешение или как сделал я использовать низкий мип-уровень. Так как в GLSL 1.1 нельзя обращаться к конкретному мипу из вершинного шейдера, установить его придется через параметр GL_TEXTURE_BASE_LEVEL функции glTexParameteri:

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 6);

Я использовал шестой уровень мипа, но все зависит от изначального разрешения текстуры и требуемой степени размытия. Честно говоря это не очень хороший способ размытия, так как на гранях кубмапы образуются полосы в виде резкой границы перехода цвета, но так как на жуке ярко выраженная рельефная поверхность — этого не заметно.
Кстати как вариант, можно еще использовать сферические гармоники.
Шейдер для жука

резкая граница

Еще вместо конвертирования цветовой модели, можно взять одномерную текстуру и делать выборку по ней, используя в качестве текстурной координаты вычисленный угол между наблюдателем и нормалью. Таким образом меняя текстурку можно менять цвет жука.

Полный шейдер
Вершинный:
#version 110

uniform mat4 matrixProj; //матарица проекции
uniform mat4 matrixView; //матрица вида

attribute vec3 vertex;
attribute vec3 normal;
attribute vec3 tangent;
attribute vec2 texCoord;

varying vec2 vTexCoord;
varying mat3 vTbn; //матрица тангент битангент нормаль
varying float zPos; // z-координата

void main() {
	vec4 pos = matrixProj*matrixView*vec4(vertex, 1.0);
	gl_Position = pos;
	vTexCoord = texCoord;
	zPos = pos.z;

	vec3 bitangent = cross(normal, tangent); // вычисляем битангент
	vTbn = mat3(tangent, bitangent, normal); // ...и матрицу
}

Фрагментный:
#version 110

uniform sampler2D texture; //текстура о которой я писал в предыдущей статье
uniform samplerCube envMap; //карта окружения
uniform vec3 light; //позиция источника света
uniform float bright; //общая яркость
uniform float focalDistance; //фокусное расстояние для блура
uniform float focalRange; //область фокуса
uniform vec3 eyeDir; //направление взгляда
uniform float hueAverage; //смещение для цветового тона, фактически начальная величина
uniform float hueRange; //диапазон тона

varying vec2 vTexCoord;
varying mat3 vTbn;
varying float zPos;

const float shadowOpacity = 0.7; //прозрачность затенения
const float envBright = 1.0; //яркость карты окружения
const float envLighting = -0.6;//яркость отражения
const float iridescenceOpacity = 0.6;//влияние иризации на цвет
const float hsvSaturation = 0.7; //насыщенность цвета
const float hsvValue = 0.8;//значение цвета
const float addIridescenceValue = 0.2;//влияние карты смещений на тон

vec3 hsv2rgb(float h, float s, float v) {
	vec4 k = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);
	vec3 p = abs(fract(vec3(h)+k.xyz)*6.0-k.www);
	return v*mix(k.xxx, clamp(p-k.xxx, 0.0, 1.0), s);
}

void main() {
	vec4 dataTex = texture2D(texture, vTexCoord);
	vec3 normal = normalize(vTbn*(vec3(dataTex.rg, 1.0)*2.0-1.0));//вытаскиваем нормаль из текстуры
	float lighting = clamp(dot(normal, light), 0.0, 1.0);//вычисляем освещенность

	float hue = (1.0-pow(dot(normal, eyeDir), 2.0))*hueRange+hueAverage;//вычисляем цветовой тон
	hue -= (1.0-dataTex.a)*addIridescenceValue;//делаем смещение на основе данных из текстуры
	vec3 diffuse = hsv2rgb(hue, hsvSaturation, hsvValue)*iridescenceOpacity;//конвертируем в RGB

	vec3 env = textureCube(envMap, reflect(-eyeDir, normal)).rgb;//вычисляем отражение
	diffuse += env*bright*envBright+envLighting;//корректировка отражения и добавление к основному цвету

	float shadow = lighting*dataTex.b*shadowOpacity+1.0-shadowOpacity;//вычисляем затенение на основе освещенности источником цвета и ао из текстуры

	gl_FragColor.rgb = shadow*diffuse;//добавляем тени
	gl_FragColor.a = clamp((focalDistance+zPos)/focalRange, -1.0, 1.0);//вычисляем и записываем значение размытия
}



Немного про GUI


Шейдер для жука


Мне было интересно попробовать такой способ:
Берется вот такая текстура:
Шейдер для жука

Она достаточно маленькая, хватит 16х16 пикселей. Любой прямоугольный элемент гуи имеет такую сетку:
Шейдер для жука

У этой сетки текстурные координаты задаются таким образом, что используя текстурку выше получается вот такой черно-белый спрайт:
Шейдер для жука

А теперь главное — каждый пиксель этого спрайта — это текстурная координата для одномерной текстуры, которая представляет из себя тему оформления элемента интерфейса. Чем то напоминает distance field. Например, для скриншота выше использовались такие полоски:
Шейдер для жука

Шейдер для жука

Шейдер для жука

У каждой полоски по три строки пикселей — для фона, нажатой кнопки и отпущенной.
Все текстуры должны использоваться с билинейной интерполяцией. Таким образом используя две очень маленькие текстурки можно добиться почти векторного качества элементов интерфейса, на любых DPI. Правда оформление получается во все стороны симметричное, нельзя, например, сделать падающие тени.

Пиксельный шейдер для рендера такого вида интерфейса
#version 110

uniform sampler2D guiMap; //спрайт с гуи-элементом
uniform sampler2D themeMap; //тема оформления
uniform float themeNum;//строка (v-координата текстуры) в теме оформления

varying vec2 vTexCoord;

void main() {
	float a = texture2D(guiMap, vTexCoord).r; //находим текстурную координату для темы 
	gl_FragColor = texture2D(themeMap, vec2(a, themeNum)); //берем цвет
}



Видео


Я добавил к блуру немного шума, чтобы эмитировать эффект film grain. Так же можно заметить недостаток такого эффекта размытия — небольшой ореол вокруг резких границ.

Скринкаст к сожалению получился без вертикальной синхронизации, несмотря на то, что она была включена.

Проблема
Система Kubuntu 12.04, включена вертикальная синхронизация в стандартных настройках. Можно дополнительно включить синхронизацию через Nvidia xserver settings. На мониторе у приложений никаких разрывов не наблюдаются, не наблюдаются и во время скринкаста, но если посмотреть полученную запись — видно что там есть разрывы. Видео записываю через avconv:
avconv -f x11grab -s 1280x720 -i :0.0+2240,185 -c:v libx264 -r 30 -vsync 2 -b 4000k -threads 8 -y 1.mp4
с параметром vsync игрался по всякому. Какие бы я настройки не выставлял, но при высокой нагрузке, даже при включенной синхронизации во всех настройках — появляются разрывы. Есть подозрение, что косяк в дровах от нвидии. Если кто-то с этим сталкивался и нашел решение проблемы — сообщите, пожалуйста. Прошу прощения за некачественное видео.



Исходники


Писал на C++ с использованием Qt версии 4.7.* или 4.8.*, тестировал на Kubuntu 12.04 и 14.04, Mac 10.8, видеокартах intel hd 4000, GeForce gtx560, Radeon HD 6750M.
Исходники: github.com/Torvald3d/Beetle
Модель жука (obj): github.com/Torvald3d/Beetle/tree/master/obj
Лицензия Creative Commons, однако в проекте есть HDR карты с этого сайта со всеми вытекающими последствиями, а так же код шейдера fxaa.frag, который был взят отсюда.

Ссылки





Похожие новости

21 января 2016 г., 0:22:57 MediaTek MT6595: впечатления от… чипсета

Некоторое время тому назад мне удалось вплотную ознакомиться с двумя флагманскими смартфонами, а именно Lenovo Vibe X2 и Meizu MX4. Сами по себе они очень разные, но есть у них и общая черта – чипсет MediaTek MT6595. Это первая в мире платформа с 8-ядерным процессором и встроенным LTE-модемом. Благодаря...

18 января 2016 г., 0:35:44 BlackBerry-Priv-Review-137

Не смотря на то, что BlackBerry Priv не имеет стерео-динамика, как BlackBerry Z30 и BlackBerry Passport, два предыдущих устройства компании, который отличались очень высоким качеством воспроизведения звука, он совершенно неожиданно оказался на высоте! Видео блоггер ItsmeJC записал видео, в котором вы...

26 декабря 2015 г., 6:45:39 Гаджеты 2016 года. Чего нам ждать в 2016 году?

Гаджеты 2016 года. Чего нам ждать в 2016 году? от Артур · Дек 25, 2015 15:20 Мир гаджетов регулярно пополняется новинками, 4K-дисплеи, 21-МП камеры, 10-ядерные процессоры, 4 ГБ оперативной памяти, фитнес-браслеты, анализирующие...

2 декабря 2015 г., 18:06:01 Mi Pad 2 в Antutu набрал свыше 85 000 баллов

Несколько дней назад Xiaomi представила долгожданное второе поколение планшета Mi Pad. Новинка порадовало ценой, но по характеристикам мнения разделились. Основная претензия к якобы не очень производительному чипу Intel Atom x5-Z8500 и скромным 2 ГБ RAM на сегодняшний день. После NVIDIA Tegra K1 у первого...

1 декабря 2015 г., 19:12:38

Несмотря на то, что NVIDIA запустила новый планшет только на прошлой неделе, известный, как NVIDIA Shield Tablet K1, старшая модель также удостоилась внимания прессы. Оригинальный Shield Tablet, получает обновление с поддержкой TWRP. TWRP — Team Win Recovery Project, программное обеспечение с открытым...


Похожие обзоры

17 декабря 2015 г., 16:10:44

Видео обзор ноутбука MSI GS40 6QE Phantom http://www.notik.ru/search_catalog/filter/brand/MSI/G/GS40.htm?from=youtube&utm_source=youtube&utm_medium=review&utm_campaign=video_review&utm_content=MSI_GS40 Купить MSI GS40 MSI GS40 6QE Phantom...

24 ноября 2015 г., 11:52:16

На нашем YouTube канале появились новые видеоролики, посвященные операционной системе Android. Вашему вниманию представляем Видеообзор смартфона BenQ F5, оснащенного 5-дюймовым HD дисплеем, четырехъядерным 1,2 ГГц процессором Qualcomm Snapdragon 400, 2 МП фронтальной камерой и 13 МП основной камерой,...

29 июня 2015 г., 11:47:10 Обзор Nokia N1

Введение Приобретение Microsoft подразделения Nokia — Devices & Services, стало одним из самых тяжелых технологических переломов. Тем не менее, Nokia имеет виды на рынок потребительских устройств и, совместно с Foxconn выпускает планшет Nokia N1. Новый планшет работает на Android, имеет полностью...

23 июня 2015 г., 9:32:37 imac_site

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

10 июня 2015 г., 16:18:08

Игровой монитор – уже достаточно устоявшееся понятие, обычно включающее в себя быструю матрицу с минимальной задержкой ввода и высокой частотой обновления. В последнее же время к заветным параметрам «1 мс, 144 Гц» добавляется еще одна характеристика: поддержка технологии адаптивного изменения частоты...


Похожие отзывы

31 июля 2015 г., 17:35:46

Сегодня, 31 июля 2015 года, NVIDIA объявляет о добровольном отзыве 8-дюймовых планшетов SHIELD, проданных в период с июля 2014 по июль 2015 года для их замены. NVIDIA установила, что аккумуляторная батарея в этих планшетах может перегреваться и тем самым представлять угрозу возгорания. NVIDIA просит...

17 апреля 2015 г., 2:18:56 quadro M6000

В марте была представлена видеокарта NVIDIA Quadro M6000 для профессиональной работы с графикой. Она оснащена 12 Гбайт видеопамяти, а скорость вычислений одинарной точности составляет 7,0 терафлопс. Видеокарта поддерживает до четырёх 4K-мониторов. Архитектура Maxwell обеспечивает низкое энергопотребление. На...

17 февраля 2015 г., 12:30:51  Acer Iconia TAB a210 / a211 : Неплохой планшет на Android по ЗАВЫШЕНОЙ цене.

Достоинства: *доступная цена, usb порт, быстродействиеНедостатки: качество сборки, нет основной камеры сзади  Характеристики - Экран 10.1" (1280x800) емкостный Multi-Touch / nVidia Tegra 3 (1.2 ГГц) / RAM 1 ГБ / SSD 16 ГБ / Wi-Fi / Bluetooth / камера 2 Мп / Android 4.0 / вес 720 г / .   Купил планшет...

15 февраля 2015 г., 17:22:48

Достоинства: стильно выглядит, хорошая камера, хорошо ловит wi-fi и bluetoothНедостатки: быстро разряжается, очень сильно тормозит, плохая начинка Купил в июле 2013 года. Сначала очень понравился. Поскольку это мой первый смартфон, вначале его характеристики меня вполне устроили. Теперь по подробнее...

23 декабря 2014 г., 7:41:33 Google Nexus 9

Планшет Nexus 9, отзыв по которому вы найдете ниже, является устройством, которого все мы ждали долгое время. Это обновленный Nexus 7, это же перезагрузка для Nexus 10 и он же является долгожданным Nexus 8. Планшет, похоже, прошел сразу несколько внутренних итераций, в основном потому, что рынок планшетов...


Похожие инструкции

28 мая 2015 г., 21:31:02

  Планшет NVIDIA SHIELD Tablet LTE, Черный 940-81761-2505-200 28 990 р....

20 мая 2015 г., 18:02:55 [recovery mode] Сколько новичку можно заработать на YouTube в 2015 году?

Ваш сайт – это ваши правила, но и полностью ваши проблемы с его развитием. 15 SEO-экспертов в прошлой статье указали причины, мешающие продвижению новых ресурсов. Легкая ошибка – и пришествие трафика откладывается на неопределенный срок. А вместе с ним – и запланированный доход. Но ведь можно использовать...

11 мая 2015 г., 19:48:51

Привет, друзья! На прошлой неделе материалов на сайте вышло не так много, как хотелось, но это связано с праздниками. Среди новостей интересных было несколько, например, Vivo X5 Pro может получит сканер сетчатки глаза, стали известны характеристики Motorola Moto X третьего поколения и представлен безрамочный...

27 апреля 2015 г., 13:36:38

Добрый день, дорогие друзья! Неделя на сайте была насыщена интересными статьями и обзорами, поэтому предлагаю вам их все вспомнить, а что заинтересует — прочитать. В этом вам поможет дайджест публикаций прошлой недели. Новостей интересных было достаточно, например, Sony представила Xperia Z4, Xiaomi...

3 апреля 2015 г., 20:04:34 [recovery mode] Optimus G — 720p флагман

Так получилось, что мне дали на тест Optimus G. Видимо, мой обзор Nexus'а понравился. Девайс пробыл у меня достаточное количество времени, чтобы осознать плюсы и минусы, увидеть сильные стороны и слабые, понять, стоит-ли он своих денег и вообще привыкнуть к девайсу. Обойтись без сравнения с его прямым...

Упомянутые аппараты
vk.com/analogindex_ru
"Analog Index" © 2014 - 2015