Что такое шейдеры материала unity
Использование и производительность встроенных шейдеров
Вопросы производительности
Есть несколько факторов, которые могут воздействовать на общую производительность в игре. На этой странице мы поговорим о вопросах производительности для встроенных шейдеров. Производительность шейдеров наиболее зависит от двух вещей: самого шейдера и какой режим рендеринга используется проектом или конкретной камерой. Для советов по производительности при написании своего шейдера смотрите страницу Производительность шейдеров ShaderLab.
Режимы рендеринга и производительность шейдеров
Из режимов рендеринга, поддерживаемых Unity, режимы отложенного освещения и вершинного освещения имеют наиболее предсказуемую производительность. В отложенном освещении каждый объект обычно рисуется дважды не зависимо от количества освещающих его источников света. В вершинном освещении каждый объект рисуется один раз. Таким образом, производительность в шейдерах при этом будет зависеть от того, как много текстур они используют и какие совершают расчеты.
Производительность шейдеров при упреждающем режиме рендеринга
При упреждающем типе рендеринга, производительность шейдера зависит и от самого шейдера, и от источников освещения в сцене. Следующий раздел поясняет это в деталях. Существует две основных (с точки зрения производительности) категории шейдеров: Vertex-Lit (вершинная подсветка) и Pixel-Lit (пиксельная подсветка).
Шейдеры Vertex-Lit в упреждающем режиме рендеринга всегда менее ресурсоёмки, чем Pixel-Lit шейдеры. Эти шейдеры работают с помощью расчёта освещения на вершинах меша, используя сразу все источники освещения. Поэтому, неважно сколько источников освещения освещают объект, он всё равно будет отрисован только один раз.
Pixel-Lit шейдеры рассчитывают итоговое освещение для каждого отрисовываемого пикселя. Из-за этого, объект должен быть отрисован один раз для получения освещения от окружения и от одного главного направленного источника света, и по одному разу для каждого дополнительного источника освещения, который его освещает. Это увеличивает нагрузку на CPU для обработки и отправки на графический адаптер команд, и нагрузку на GPU для обработки вершин и отрисовки пикселей. Пространство, занимаемое на экране попиксельно освещаемым объектом, также влияет на производительность отрисовки. Чем больше объект, тем больше придётся обработать пикселей и тем медленней будет проходить отрисовка.
Так что использование pixel lit шейдеров требует дополнительных ресурсов, но, зато, позволяет реализовать некоторые изумительные эффекты с помощью теней, карт нормалей, красивых отражаемых бликов и источников света с cookie текстурами (это лишь некоторые из возможностей).
Запомните, что можно форсировать тип рендеринга у источников освещения в пиксельный (“important”) или вершинный/SH (“not important”). Любой вершинный свет, попадающий на Pixel-Lit шейдер будет рассчитываться на основе вершин объекта или всего объекта, и не будет потреблять дополнительных ресурсов и выдавать эффекты, ассоциируемые с пиксельными источниками освещения.
Основа производительности шейдеров
Рассматривая встроенные шейдеры, они идут по мере увеличения сложности:
Mobile simplified shaders
Кроме того, в Unity существует несколько упрощённых шейдеров для использования на мобильных платформах, они расположены в категории “Mobile”. Эти шейдеры работают и на других платформах, так что если вам не мешают упрощения, которые в них внесены (например, усреднённые отражения, нет поддержки цветов для каждого материала и т.д.), попробуйте использовать их!
Some examples of changes that are common across the Mobile shaders are:
Shader — это не магия. Написание шейдеров в Unity. Введение
Всем привет! Меня зовут Дядиченко Григорий, и я основатель и CTO студии Foxsys. Сегодня хочется поговорить про шейдеры. Умение писать шейдеры (и в целом работать с рендером) очень важно при разработке под мобильные платформы или AR/VR, если хочется добиться крутой графики. Многие разработчики считают, что шейдеры — это магия. Что по ним мало хорошей информации, и что чтобы их писать нужно иметь, как мимимум, звание кандидата наук. Да, разработка шейдеров по своим принципам сильно отличается от клиентской разработки. Но основное понимать базовые принципы работы шейдеров, а так же знать их суть, чтобы в этом не было ничего магического и поиск информации по этой теме был простой задачей. Данная серия статей рассчитана на новичков, так что если вы разбираетесь в программировании шейдеров, данная серия вам не будет интересна. Всем же кто хочет разобраться в этой теме — добро пожаловать под кат!
Это вводная статья в которой я расскажу общие принципы написания шейдеров. Если тема будет интересна, то мы разберём уже подробнее в отдельных статьях: вершинные шейдеры, геометрические шейдеры, фрагментные/пиксельные шейдеры, трипланарные шейдеры, скринспейс эффекты и компьют шейдеры (OpenCL, СUDA и т.п.). И в целом всю ту магию, которую можно делать на GPU. Разбираться это будет в контексте стандартного рендер пайплайна Unity. Так LWRP и HDRP мне пока кажутся немного сыроватыми.
Что такое шейдер?
По сути это программа выполняемая на гпу, выходными данными которых является разная информация. В вершинных шейдерах — это параметры вершин меша. Пиксельные шейдеры выполняются попиксельно.
Для понимания того, как работают шейдеры нужно рассказать, что такое графический конвейер (graphic pipeline). Очень часто про эту тему говорят довольно сложными словами, но мы это немного упростим для понимания. Возьмём на примере OpenGL. В этом плане мне очень нравится эта картинка.
Если опустить детали связанные с освещением и т.п. То в целом с точки написания тех же Unlit шейдеров на hlsl суть такова. У нас есть в шейдере
где мы определяем, что вертексная часть шейдера будет писаться в функции vert, а фрагментная — в функции frag.
Структуры которые мы описываем в шейдере определяют какие данные мы будем забирать из меша и после обработки вертексным шейдером, которые висят на нашем MeshRenderer и MeshFilter объекте.
Дальше вертексный шейдер вычисляет получив на вход данные appdata и отдаёт результат в виде структуры v2f, которая дальнейшем пойдёт в фрагментный шейдер. Который в свою очередь уже рассчитает цвет пикселя. Так как информация v2f пишется только в вершины (которых меньше, чем пикселей), данные в фрагментной части интерполируются. Всё это можно представить как то, что vert считается в каждом вертексе независимо. Потом результат передаётся в фрагментную часть, где frag для каждого пикселя считается так же независимо. Так как вычисления производятся параллельно, в данных частях нет никакой информации о соседях (если не передавать её как-то хитро).
Более детально все нюансы, а так же множество примеров описаны в документации Unity docs.unity3d.com/Manual/SL-Reference.html
Языки программирования шейдеров
Дальше с точки зрения изучения шейдеров, когда эти языки уже не вызывают вопросов можно посмотреть какие возможности предоставляет сам по себе«UnityCG.cginc» и другие библиотеки написанные юнити, чтобы упростить себе работу.
Почему if в шейдерах — это плохо?
Тут важно понимать, как шейдеры исполняются на уровне железа и почему они такие быстрые, что могут выполнять миллионы операций не напрягаясь.
Основная идея графических процессоров — это максимальная параллельность вычислений. Тут нужно ввести такое понятие, как “волновой фронт”. По сути оно довольно простое, волновой фронт — это группа шейдеров выполняющая одну и туже последовательность операции. То есть с точки зрения гпу самый лучший вариант, когда в одно и тоже время выполняются одни и те же инструкции. Единственно различие в выполнении — это входные данные. Проблема ветвления в том, что может случиться ситуация, когда в одной группе шейдеров, шейдеры должны вызывать разные операции. Что в свою очередь приводит к созданию нового волнового фронта, копированию в него данных и т.п. А это очень дорого.
Там есть нюансы и исключения, но для того чтобы спокойно писать if, вы должны понимать, как он себя поведёт на целевой версии графического апи. Так как тот же самый OpenGL ES 2 или DX11 в этом плане сильно отличаются.
Зачем мне это знать, ведь есть нодовые редакторы?
Важно понимать, что нодовые редакторы — это в первую очередь инструмент для техникал артистов. Это специалисты, которые имеют экспертизу в математике, но в большей степени являются дизайнерами. Шейдеры типа wireframe (где требуется понимание барицентрических координат) или же преобразование к картезианским координатам, которое используется для хитрых проекций, в разы проще делать кодом, так же как и многие математические модели физических материалов. При этом с точки зрения шейдерного программиста вы по сути делаете кастомные ноды и инструменты для техникал артистов, чтобы творить реальную магию. Нодовые редакторы имеют ограниченный функционал с этой точки зрения. Поэтому важно уметь писать шейдеры на языках типа hlsl. Понимать то, как работает рендер и т.п.
Полезные ресурсы для изучения
С точки зрения изучения шейдерного программирования хорошим упражнением является переписывание шейдеров с www.shadertoy.com или glslsandbox.com. Кроме того существует крутой профиль специалиста из Unity, где можно посмотреть много интересного github.com/keijiro
Всё остальное — это математика и понимание физики эффектов. Это в чём-то похоже на смешивание ингредиентов, если не решается конкретная задача физического моделирования. Много любопытного можно сделать смешивая между собой шум, преломление, подповерхностное рассеивание света, каустику, эффект Френеля, реакцию диффузии и прочие физические свойства объектов. В целом шейдерное программирование это безусловно не элементарно, и там есть куда копать в глубину.
Если тема шейдеров будет интересно, то постараюсь выпустить серию на статей на эту тему, уже с конкретными примерами и туториалами на тему создания разных эффектов. Предлагайте в комментариях про что вам было бы интересно прочитать и какие темы изучить. Спасибо за внимание!
Все эффекты в статье — это запись эффектов шейдеров с shadertoy.
Использование и производительность встроенных шейдеров
Шейдеры в Unity используются через материалы, которые по существу комбинируют код шейдера с его параметрами, такими как текстуры. Глубокое объяснение связи шейдер / материал может быть найдено здесь.
Свойства материала показываются в инспекторе, когда будут выбраны или сам материал, или GameObject, который использует материал. Инспектор для материала выглядит так:
Вопросы производительности
Есть несколько факторов, которые могут воздействовать на общую производительность в игре. На этой странице мы поговорим о вопросах производительности для встроенных шейдеров. Производительность шейдеров наиболее зависит от двух вещей: самого шейдера и какой режим рендеринга используется проектом или конкретной камерой. Для советов по производительности при написании своего шейдера смотрите страницу Производительность шейдеров ShaderLab.
Режимы рендеринга и производительность шейдеров
Из режимов рендеринга, поддерживаемых Unity, режимы отложенного освещения и вершинного освещения имеют наиболее предсказуемую производительность. В отложенном освещении каждый объект обычно рисуется дважды не зависимо от количества освещающих его источников света. В вершинном освещении каждый объект рисуется один раз. Таким образом, производительность в шейдерах при этом будет зависеть от того, как много текстур они используют и какие совершают расчеты.
Производительность шейдеров при упреждающем режиме рендеринга
При упреждающем типе рендеринга, производительность шейдера зависит и от самого шейдера, и от источников освещения в сцене. Следующий раздел поясняет это в деталях. Существует две основных (с точки зрения производительности) категории шейдеров: Vertex-Lit (вершинная подсветка) и Pixel-Lit (пиксельная подсветка).
Шейдеры Vertex-Lit в упреждающем режиме рендеринга всегда менее ресурсоёмки, чем Pixel-Lit шейдеры. Эти шейдеры работают с помощью расчёта освещения на вершинах меша, используя сразу все источники освещения. Поэтому, неважно сколько источников освещения освещают объект, он всё равно будет отрисован только один раз.
Pixel-Lit шейдеры рассчитывают итоговое освещение для каждого отрисовываемого пикселя. Из-за этого, объект должен быть отрисован один раз для получения освещения от окружения и от одного главного направленного источника света, и по одному разу для каждого дополнительного источника освещения, который его освещает. Это увеличивает нагрузку на CPU для обработки и отправки на графический адаптер команд, и нагрузку на GPU для обработки вершин и отрисовки пикселей. Пространство, занимаемое на экране попиксельно освещаемым объектом, также влияет на производительность отрисовки. Чем больше объект, тем больше придётся обработать пикселей и тем медленней будет проходить отрисовка.
Так что использование pixel lit шейдеров требует дополнительных ресурсов, но, зато, позволяет реализовать некоторые изумительные эффекты с помощью теней, карт нормалей, красивых отражаемых бликов и источников света с cookie текстурами (это лишь некоторые из возможностей).
Запомните, что можно форсировать тип рендеринга у источников освещения в пиксельный (“important”) или вершинный/SH (“not important”). Любой вершинный свет, попадающий на Pixel-Lit шейдер будет рассчитываться на основе вершин объекта или всего объекта, и не будет потреблять дополнительных ресурсов и выдавать эффекты, ассоциируемые с пиксельными источниками освещения.
Основа производительности шейдеров
Рассматривая встроенные шейдеры, они идут по мере увеличения сложности:
Mobile simplified shaders
Кроме того, в Unity существует несколько упрощённых шейдеров для использования на мобильных платформах, они расположены в категории “Mobile”. Эти шейдеры работают и на других платформах, так что если вам не мешают упрощения, которые в них внесены (например, усреднённые отражения, нет поддержки цветов для каждого материала и т.д.), попробуйте использовать их!
Some examples of changes that are common across the Mobile shaders are:
Что такое шейдеры материала unity
Главная » Unity: Введение в шейдеры
Unity: Введение в шейдеры
Вы когда-нибудь задумывались о шейдерах в Unity? В этом уроке вы узнаете, что такое шейдеры, как отображать цвета вершин и как выполнять анимацию в шейдерах.
Версия: C# 7.3, Unity 2019.3, Unity
Unity оказывает большую помощь разработчикам игр, в том числе предлагает шейдеры, чтобы упростить создание сложных визуальных эффектов и анимации. Вы можете продвинуться довольно далеко, просто разбираясь со стандартными шейдерами, которые поставляются с Unity. Однако вы можете улучшить визуальные эффекты в своих проектах, написав собственные шейдеры.
В этом руководстве вы узнаете:
Чтобы попрактиковаться, вы будете полировать графику сцены необитаемого острова с помощью пользовательских шейдеров. Загрузите файлы проекта, нажав кнопку «Скачать материалы урока» вверху этого урока. В примере проекта представлены модели и текстуры, так что вы можете сосредоточиться на шейдерах.
Примечание. Некоторые модели и текстуры, которые использует начальный проект, взяты с сайтов Sharegc.com и Textures.com.
В примере проекта используется Unity 2019.3, хотя все, что описано в этом руководстве, должно работать и в более старых версиях.
Примечание. Это урок среднего уровня сложности, предполагающий, что вы уже знаете основы работы с Unity. Если вы новичок в Unity, начните с урока Введение в Unity: начало работы.
Что такое шейдеры?
Компьютерная графика, особенно 3D-графика, использует множество различных видов информации для построения визуальных элементов: сетки, текстуры, источники света и так далее. Эта информация передается графическому оборудованию, которое затем обрабатывает изображение и выводит его на экран.
Рендеринг — это то, что программисты называют процессом создания изображения, а шейдеры — это короткие программы, которые визуализируют графические данные. То есть шейдер — это программа, которая принимает сетки, текстуры и так далее. В качестве входных данных и генерирует изображение в качестве выходных данных.
Понимание типов шейдеров
Технически, отдельный шейдер не выводит изображение целиком и не всегда выполняет рендеринг. Скорее, существуют разные типы шейдеров, которые делают разные вещи.
Основным типом является пиксельный шейдер, названный по той очевидной причине, что он выводит пиксель. Другой распространенный термин — это фрагментный шейдер, поскольку каждый пиксель является фрагментом полного изображения.
Фрагментные шейдеры выводят цвет одного пикселя, который вычисляется на основе положения этого пикселя на многоугольнике. Программа запускается снова и снова, в основном параллельно, для генерации всех пикселей всех полигонов, обрабатываемых этим шейдером. Действительно, возможность одновременной обработки большего количества пикселей является важной частью того, как видеокарты ускоряют графику.
Есть также вершинные шейдеры, которые вы используете для вычисления положения вершин на изображении. Хотя входные данные представлены в трех измерениях, компьютеру необходимо определить, где появляются вершины в двух измерениях, прежде чем он сможет отобразить пиксели.
Вы можете добиться некоторых интересных визуальных эффектов, манипулируя данными, выводимыми с помощью вершинных шейдеров, но мы не будем рассматривать это в уроке.
Вычислительные шейдеры на самом деле ничего не обрабатывают, а представляют собой просто программы, работающие на видеооборудовании. Эти шейдеры являются недавним нововведением — более старое видеооборудование может даже не поддерживать их.
Как и в случае с фрагментными и вершинными шейдерами, вычислительный шейдер — это короткая программа, которую видеокарта запускает в массовом параллельном режиме. В отличие от других шейдеров, вычислительные шейдеры не выводят ничего визуального. Вместо этого они используют преимущества параллельной обработки на видеокартах для таких вещей, как майнинг криптовалюты. В этом руководстве вы не будете работать с вычислительными шейдерами.
Unity представляет еще один вид шейдеров — шейдер поверхности. Это шейдеры, которые выполняют расчеты освещения за вас, и вам нужно только написать код — помните, шейдер — это программа, — для обработки других свойств поверхности, таких как цвет и текстура.
Поверхностные шейдеры на самом деле являются фрагментными и вершинными шейдерами, но Unity генерирует код для обработки освещения. Это удобно, поскольку расчеты освещения очень сложны и часто стандартизируются для множества различных шейдеров.
И наконец, графические данные сообщают видеокарте, какой шейдер использовать с материалами. Когда вы будете изучать материалы, вы увидите меню вверху. Это меню выбирает, какой шейдер назначить материалу. Таким образом, когда графическое оборудование визуализирует многоугольник, оно запускает шейдер материала этого многоугольника.
Хорошо, достаточно объяснений. Пришло время написать шейдеры!
Написание пользовательского шейдера
Если вы еще этого не сделали, откройте начальный проект, затем откройте RW / Scenes / SampleScene. Вы увидите заранее построенную сцену необитаемого острова с позиционированными моделями, которым назначены материалы.
Существующая сцена не выглядит ужасной, но вы можете улучшить ее, по крайней мере, двумя способами: остров имеет твердые квадратные края, а вода полностью статична.
Вы можете решить обе проблемы с помощью пользовательских шейдеров. Однако, прежде чем решать эти проблемы, вам необходимо понять, как создавать шейдеры.
Для начала создайте ассет Surface Shader в папке Shaders, щелкнув правой кнопкой мыши и выбрав Create > Shader > Standard Surface Shader. Назовите его MyFirstShader.
Перейдите в папку Materials, выберите cartoon-sand и щелкните раскрывающийся список Shader в верхней части Inspector. Выберите Custom > MyFirstShader, чтобы переключить материал на этот шейдер.
Пока что ничего особенного в сцене не изменится, потому что вы не изменили код шейдера по умолчанию. Тем не менее, материал песка на острове теперь использует ваш собственный шейдер, а не стандартный шейдер, встроенный в Unity.
Рассмотрение шаблона по умолчанию для настраиваемого шейдера
Дважды нажмите на ассет Shader, чтобы открыть его в редакторе кода, и изучите код.
Шейдер состоит из различных разделов внутри основного блока кода шейдера.
Весь код находится внутри блока шейдера в фигурных скобках с именем Custom/MyFirstShader. Эта запись просто сообщает Unity, что показывать при просмотре меню шейдеров материала. Глядя на разные блоки кода…
Properties
В блоке Properties вверху вы объявляете различные определяемые пользователем свойства. Это значения, которые вы можете редактировать в инспекторе при выборе материала.
Подробное рассмотрение одной строки: сначала вы видите имя переменной, используемое в коде. Затем в круглых скобках вы определяете имя, которое будет отображаться в инспекторе. Также в круглых скобках указывается тип свойства: цвет, двухмерная текстура или диапазон чисел. Наконец, после знака = вы присваиваете свойству значение по умолчанию.
Блок SubShader
Блок кода Subshader — это то место, где находится большая часть кода шейдера. Первые две строчки в этом блоке объявляют идентифицирующие теги, распознаваемые Unity, котоыре устанавливают значение, используемое системой уровня детализации (LOD) Unity.
В этом случае идентифицирующие теги заявляют, что шейдер не является прозрачным. Технически может быть несколько блоков субшейдера, но в этом руководстве вы не будете углубляться в такой уровень сложности.
Блок CGPROGRAM
Эти строчки кода декларируют несколько важных аспектов, которым нужно следовать. Во-первых, они указывают, что следующий код использует язык Cg. Для написания шейдеров существует несколько разных языков программирования. До этого момента все использовалось на языке Unity, ShaderLab.
Между тем, директивы #pragma устанавливают значения конфигурации. Подробно рассмотрим первый: поверхность сообщает компилятору шейдеров, что это шейдер поверхности. Опять же, помните, что другие типы включают фрагментные и вершинные шейдеры.
surf — это название основной функции затенения, представленной ниже. Standard объявляет желаемую модель освещения — другие модели освещения включают Lambert и Blinn-Phong, но стандартное физическое освещение выглядит лучше всего. fullforwardshadows активирует динамические тени для этого шейдера.
Переменная свойства MainTex
Эта строчка объявляет переменную, соответствующую одному из свойств. Хотя это кажется немного избыточным, вы должны объявить здесь переменную, чтобы код Cg использовал это свойство.
Эти переменные могут быть одного из нескольких типов, включая sampler2D для изображения текстуры и fixed / half / float для чисел. Эти три числа являются числами возрастающей точности, и вы должны использовать наименьшую точность, которая работает.
Вы должны объявить все свойства как переменные в коде Cg. Вы можете увидеть другие имена свойств чуть позже в уроке. Почему в коде шаблона Unity они написаны отдельно друг от друга, а не в один единый список, остается загадкой, но это также не имеет особого значения.
Вводные данные и переменные свойства
Этот блок кода объявляет структуру данных с именем Input и перечисляет в ней значения. Единственными входными значениями в коде шаблона являются UV-координаты основной текстуры, но есть несколько входных значений, к которым шейдеры могут получить доступ. Графические данные передадут объявленные здесь входные значения в шейдер.
Главная функция шейдера
Unity предоставляет tex2D для поиска цвета в текстуре по заданной координате. При написании фрагментного шейдера необходимо явно включить библиотеку шейдеров Unity, но шейдеры поверхности включают библиотеку автоматически.
FallBack шейдер
После кода Cg вы объявляете резервный шейдер, хотя он и не требуется. Это указывает Unity использовать резервный шейдер, если графическое оборудование не может запускать какие-либо пользовательские субшейдеры, обычно потому, что это старая видеокарта, которая не поддерживает функции шейдера.
Хорошо, теперь, когда вы понимаете структуру кода шейдера, пора заняться визуальными настройками, указанными в начале кода шейдера.
Добавление цвета вершин в шейдер поверхности
Первая проблема, которую вы хотели исправить в этой сцене, заключалась в том, что у острова были твердые квадратные края.
Сейчас вы можете довольно четко видеть края сетки, но кажется, что настоящие пляжи переходят в цвет воды.
Есть много способов добиться этого в игре, но в одном простом подходе используется цвет вершин.
Чтобы понять, что такое цвета вершин, представьте, что «вершина» — это просто набор данных. Эти данные всегда включают положение вершины, но вы также можете включить дополнительные параметры.
Координаты текстуры являются обычным дополнением, при этом координаты (обозначенные буквами UV вместо XY) предоставляют числа, которые вы используете при работе с текстурами. Что ж, цвет — это еще один вариант, предоставляющий числа, которые вы используете при расчете цветового вывода шейдера.
Например, если вы присвоите вершине красный цвет, то многоугольник, использующий эту вершину, будет иметь красный оттенок. Более того, если вершины многоугольника имеют разные цвета, то эти цвета интерполируются по граням многоугольника.
Этому островному мешу уже назначены цвета вершин, но вы не можете их видеть, потому что стандартный шейдер Unity не обрабатывает цвета вершин.
В частности, вершины под водой имеют более темный оттенок, а остальные вершины острова белые. Эти цвета создали бы приятный градиент по краю пляжа, если бы они были видны, поэтому ваша следующая задача — написать собственный шейдер, который обрабатывает цвет вершин.
Создание пользовательского шейдера для цвета вершин
Создайте новый шейдер поверхности и назовите его LitVertexColor. Установите материалу cartoon-sand этот шейдер как используемый, а затем откройте ресурс шейдера, чтобы отредактировать код.
Вам нужно всего лишь сделать два небольших дополнения для цвета вершины. Сначала добавьте в структуру Input следующий код:
Далее включите vcolor в расчет цвета, который происходит в surf :
И это все! Сохраните шейдер и вернитесь в сцену Unity. После компиляции шейдера вы увидите, как края острова сливаются под водой.
Анимация текстуры воды
Теперь песок выглядит намного привлекательнее! Между тем, вы обнаружили еще одну проблему, заключающуюся в том, что вода полностью статична.
Вы можете изменить это с помощью другого настраиваемого шейдера, хотя на этот раз вам не нужно освещение. Помните, что поверхностные шейдеры обрабатывают освещение за вас, поэтому на этот раз вы не будете создавать поверхностные шейдеры.
Создание неосвещенного шейдера
Вместо этого создайте Unlit Shader с помощью контекстного меню: Create > Shader > Unlit Shader.
Назовите новый ассет шейдер CartoonWater и откройте его в редакторе кода.
Первым делом обновите имя шейдера в самом верху.
Затем добавьте некоторые дополнительные свойства для шейдера воды. Новый блок Properties должен выглядеть так:
Затем обновите раздел Tags и сразу после строки LOD 100 добавьте несколько новых параметров:
Теги по умолчанию предполагают непрозрачный материал, поэтому вы добавили и настроили некоторые флаги для поддержки прозрачности. В частности, обратите внимание, что отключение ZWrite означает, что вода не будет закрывать другие объекты в буфере глубины, в то время как вы устанавливаете Blend для использования альфа-значений.
Раньше вы работали с поверхностным шейдером, но теперь вы имеете дело с прямыми вершинными и фрагментными шейдерами. Таким образом, в то время как директива #pragma ранее объявляла функцию Surface Shading, на этот раз директивы #pragma объявляют функции Vertex и Fragment Shading.
Поверхностные шейдеры получают эти библиотеки автоматически, когда вы генерируете их код, но вам необходимо явно включить их для вершинных и фрагментных шейдеров.
UnityCG.cginc include в Unity содержит предопределенные переменные и вспомогательные функции.
Теперь взгляните на включенные структуры:
На этот раз есть две входные структуры вместо одной входной структуры для поверхностного шейдера. Вы вводите первую структуру в вершинный шейдер, который выводит вторую структуру. Эти выходные данные вершинного шейдера затем поступают на вход фрагментного шейдера.
Чуть ниже sampler2D _MainTex; В строке основного кода Cg добавьте следующие новые свойства:
Как и в предыдущем Surface Shader, вы должны объявить все свойства как переменные в Cg-коде. Вы будете использовать эти свойства, чтобы изменить текстуру и анимировать ее в основной функции шейдера.
Теперь в основной функции фрагмента шейдера, прямо вверху (над комментарием кода // sample the texture добавьте:
Эти две строки кода — основа анимированного водного эффекта. Этот код смещает UV-координаты, которые он получает, причем величина смещения изменяется со временем.
В результате получается волнообразная анимация текстуры. Между тем, обе строки кода делают по сути одно и то же, но в разных направлениях. Вы поймете и то, и другое, если подробно разберете одну строку.
Сначала код вызывает функцию тригонометрии, синус или косинус, так что значение будет меняться на повторяющейся волне. _AnimTiling масштабирует переданное число. Как следует из названия, _AnimTiling управляет мозаикой эффекта — в данном случае, воздействуя на частоту синусоидальной волны.
Затем вы добавляете время к переданному числу, заставляя возвращаемое значение перемещаться по синусоиде с течением времени. Код библиотеки из более раннего включает переменную, которая отслеживает время.
Наконец, чуть выше return col; в строке кода функции frag добавьте:
Теперь, когда вы написали свой шейдер, вы можете назначить его материалу cartoon-water.
По умолчанию поверхность воды не будет анимирована в режиме просмотра Scene, но будет отображаться в режиме просмотра Game, когда вы нажмете Play.
Куда двигаться дальше?
Вы можете скачать готовые файлы проекта, нажав кнопку «Скачать материалы урока» вверху урока.
Теперь вы знаете основы написания собственных шейдеров в Unity! Конечно, есть еще много чего, что стоит изучить, и хороший ресурс для изучения — это руководство по шейдерам Unity.
Помните ту удобную функцию шейдера, которую вы использовали ранее? Что ж, если вам интересно, какие вспомогательные функции доступны с этим включением, вы можете проверить их здесь.
Если вам интересно узнать о шейдерах с помощью Unity, ознакомьтесь с нашим другим руководством по Shader Graph в Unity здесь.
Надеюсь, вам понравился этот урок! Если у вас есть какие-либо вопросы, комментарии или предложения, не стесняйтесь оставлять их в комментариях.