Создание шейдерного эффекта 3D-принтера

Создание шейдерного эффекта 3D-принтера 3d печать
unity туториал,unity3d,программирование шейдеров,разработка игр,шейдеры

Создание шейдерного эффекта 3D-принтера

На этом семинаре будут воссозданы эффект трехмерные принтеры, используемые в таких играх, как Astroner и Annihilation of the Planets. Интересно. эффект Здесь показан процесс создания Объект. Несмотря на свою очевидную простоту, он имеет множество других, не менее незначительных сложностей.

Введение: первые попытки.

Воспроизведите это. эффекта Начните с чего-нибудь более простого. Например, с затенения, которое окрашивает объект по-разному в зависимости от его положения. Для этого необходимо иметь доступ к местоположению отрисованных пикселей в мире. Это можно сделать, добавив поле world в структуру input для затенения поверхности Unity 5

struct input< float2 uv_MainTex; float3 worldPos; >;

Затем цвет объекта можно изменить, используя координату y мирового расположения функции поверхности. Этого можно достичь, изменив Albedo структуры SurfaceOutputard.

float _constructy? fixed 4 _ConstructColour; void surf (input, Inout SurfaceOutputStandard o)< if (IN.worldPos.y < _ConstructY) < fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; >Иначе.< o.Albedo = _ConstructColor.rgb; o.Alpha = _ConstructColor.a; >o.Metallic = _Metallic; o.Smoothness = _Glossiness; >

Результатом является первое приближение к эффекту Astronea. Основная проблема в том, что затенение все еще выполняется на цветных участках.

Изображение

Вряд ли затенение поверхности.

В предыдущих семинарах по PBR и моделям освещения, создания Пользовательские модели освещения для затенения поверхностей. Неосвещенные тени всегда дают один и тот же цвет, независимо от внешнего освещения или точки зрения. Это может быть реализовано следующим образом.

#pragma Surface Surf linit full for probardshadows inline half4 lightingunlit (Surfaceoutput S, Half3 Lightdir, Half Atten)

Единственная задача — вернуть один компактный цвет. Как вы можете видеть, это упоминается в SurfaceOutput, используемом в Unity 4. Если вы хотите создать свои собственные модели PBB и глобального освещения, вам необходимо реализовать функцию, принимающую SurfaceOutputStandard в качестве входных данных; в Unity 5 для этого используется следующая функция

Inline half4 lightingunlit (surfaceoutputStandard s, half3 lightdir, unitygi gi)

Параметры GI здесь относятся к освещению мира, но наш шейдер Unlit не имеет задания. Этот подход работает, но есть серьезная проблема: Unity не позволяет Surface Shader выборочно изменять функциональность освещения. Стандартное ламбертовское освещение не может быть применено к нижней части объекта и в то же время верхняя часть объекта не будет освещена. Для всего объекта может быть назначена одна функция освещения. Способ рендеринга объекта в зависимости от его положения должен быть изменен под себя.

Изображение

Передача параметров функции освещения

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

int building?void surf(Input, Inout SurfaceOutputStandard o)< if (IN.worldPos.y < _ConstructY) < fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; building = 0; >Иначе.< o.Albedo = _ConstructColor.rgb; o.Alpha = _ConstructColor.a; building = 1; >o.Metallic = _Metallic; o.Smoothness = _Glossiness; >

Расширение стандартных функций освещения

Последняя проблема, с которой нам придется столкнуться, довольно сложна. Как было описано в предыдущем разделе, здания можно использовать для изменения способа расчета освещения. Часть объекта, которая в данный момент изготавливается, не будет освещена, но остальная часть объекта будет правильно рассчитана для освещения. Если вы хотите использовать PBR для своего материала, вы не можете переписать весь код для фотореалистичного освещения. Единственным логичным решением является вызов стандартных функций освещения, уже реализованных в Unity.

В традиционном стандарте поверхностных теней инструкция #Pragma определяет использование функции освещения PBR следующим образом.

#pragma Surface Surf Standard Fullforwardshadows

Легко заметить, что согласно стандартам именования Unity, используемая функция должна называться Lightingstandard. Эта функция находится в файле Unitypbslighting.cginc и может быть подключена по мере необходимости.

Мы хотим создать собственную функцию освещения под названием LightingCustom. В обычных условиях нам просто нужна стандартная функция PBR для унификации под названием Lightingstandard. Однако раньше вы бы использовали специфическую Lightingunlit.

Inline Half4 LightingCustom (SurfaceOutputStandard S, Half3 Lightdir, Unitygi GI)< if (!building) return LightingStandard(s, lightDir, gi); // Unity5 PBR return _ConstructColor; // Unlit >

Чтобы скомпилировать этот код, в Unity 5 необходимо определить отдельную функцию.

inline void lightingcustom_gi (SurfaceOutputStandard S, UnityGiinput Data, Inout UnityGI GI)

Эта функция используется для расчета влияния освещения на глобальное освещение, но для целей семинара она необязательна.

Результаты можно получить по мере необходимости.

Изображение

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

Обрезать геометрию

Самый простой способ добавить к затенению эффект Останавливает выполнение вершины геометрии; ключевое слово Discard может быть использовано для остановки проектирования любого пикселя в затенении. Может использоваться для рисования ограничений на вершине модели.

void surf (Input, Inout SurfaceOutputStandard o).< if (IN.worldPos.y >_ConstructY + _ConstructGap) discard; . >

Важно помнить, что это может оставить «дыры» в нашей геометрии. Срез по краям должен быть отключен, чтобы задняя часть объекта была полностью отрисована.

Отключенные разрезы

Изображение

Теперь наша главная проблема заключается в том, что объект выглядит полым. Это не просто мнение. На самом деле все трехмерные модели полые. Однако нам нужно создать иллюзию того, что объект на самом деле компактный. Этого можно легко добиться, раскрасив объект изнутри той же непрозрачной штриховкой. Объект по-прежнему полый, но полный.

Для этого просто нарисуйте треугольник задом наперед в камеру. Если вы не знакомы с векторной алгеброй, это может показаться сложным. На самом деле, этого очень легко добиться с помощью пошагового произведения: пошаговое произведение двух векторов показывает, насколько они «афитны». А это напрямую связано с углом между ними: если масштабируемое произведение двух векторов отрицательно, то угол между ними больше 90 градусов. Оригинал можно проверить, взяв масштабируемое произведение между ViewDir шейдера поверхности и нормалью треугольника. В отрицательном случае треугольник поворачивается в сторону от камеры. Это означает, что вы можете посмотреть на его обратную сторону и придать ему компактный цвет.

struct input< float2 uv_MainTex; float3 worldPos; float3 viewDir; >; void surf (input, Inout SurfaceOutputStandard o)< viewDir = IN.viewDir; . >Inline Half4 LightingCustom (SurfaceOutputStandard S, Half3 Lightdir, Unitygi GI)

Результаты показаны на рисунках ниже. Слева «обратная геометрия» отображается красным цветом. При использовании цвета поверх объекта он больше не выглядит полым.

Изображение

Эффект «волнистый».

Если вы заставляете планету исчезнуть, вы знаете, что при затенении на 3D-принтере используется эффект 3D-принтер затенения легкая рябь. Мы даже можем применить его и добавить в мир немного шума на место отрисованных пикселей. Этого можно добиться либо с помощью текстуры шума, либо с помощью непрерывной периодической функции. В следующем коде используется синусоидальная волна с произвольными параметрами.

void surf (Input, Inout SurfaceOutputStandard o).< float s = +sin((IN.worldPos.x * IN.worldPos.z) * 60 + _Time[3] + o.Normal) / 120; if (IN.worldPos.y >_ConstructY + s + _ConstructGap) discard; . >

Эти параметры можно регулировать вручную для создания красивой эффекта волнистости.

анимации.

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

Public class BuildingTimer: Monobehaviour< public Material material; public float minY = 0; public float maxY = 2; public float duration = 5; // Update is called once per frame void Update () < float y = Mathf.Lerp(minY, maxY, Time.time / duration); material.SetFloat("_ConstructY", y); >>

Наконец, обратите внимание, что модель, используемая на этом изображении, на несколько секунд кажется полой, потому что нижняя часть ускорителя не закрыта. Таким образом, объект на самом деле полый.

[Скачайте пакет Unity (код, шейдеры и 3D-модель), поддержав оригинальную статью за $10 на Patreon].

Оцените статью