Декали (decal)

Пытался разобраться с декалями в Unity. Результат скорее отрицательный, но тоже результат. Возможно, кому-нибудь поможет.

Прежде всего, в Unity (доступно на выбор) три вида визуализации/рендеринга:

  1. Built-in rendering pipeline, или встроенный\стандартный\обычный;
  2. Universal Render Pipeline (URP) — универсальный — хорош для разных устройств;
  3. High Definition Render Pipeline (HDRP) — высокого разрешения — выжать всю мощь графического процессора;

Когда создаётся новый проект, тип рендеринга выбирается из этих трёх.

 

Декали в HDRP

Тут никаких проблем. В меню выбираем GameObject > Rendering > Decal Projector и настраиваем, как нужно. В документации всё хорошо описано, полно видео. Останавливаться нет смысла. У меня ноут не тянет это великолепие.

Декали в URP

Здесь грустнее. Встроенных возможностей («из коробки») нет, поэтому придётся настраивать материалы, шейдеры и пр. К счастью, есть умные люди, которые сделали крутой шейдер и выложили в сеть.

  • Качаем с гитхаба сам шейдер:
    https://github.com/ColinLeung-NiloCat/UnityURPUnlitScreenSpaceDecalShader
    добавляем в проект URP (в стандартном не будет работать).
  • На основании этого шейдера делаем материал (кликаем по шейдеру правой кнопкой и Create-Material). В качестве изображения можно использовать это:

    _SrcBlend устанавливаем в SrcAlfa — там так и написано (default = SrcAlfa);
    _DscBlend устанавливаем в OneMinusSrcAlfa — подсказка присутствует.
  • Создаём на сцене куб (Cube), кидаем на него материал. Из куба создаём префаб (закидываем его в Assets) и удаляем со сцены.
  • Добавляем на камеру скрипт, который будет раздавать дырки. Как альтернатива — можно создать пустой объект и на него накинуть скрипт.
    using UnityEngine;
    
    public class BulletHole : MonoBehaviour
    {
        public GameObject HolePrefab;   // префаб дырки
        private Camera cameraMain;      // кешируем камеру
    
        private void Start()
        {
            cameraMain = Camera.main;       
        }
    
        void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                RaycastHit hit;
                Ray ray = cameraMain.ScreenPointToRay(Input.mousePosition);
    
                if (Physics.Raycast(ray, out hit, 100))
                {
                    Instantiate(HolePrefab, hit.point, Quaternion.LookRotation(hit.normal));
                }
            }
        }
    }
    

    В HolePrefab закидываем префаб, который создали ранее.

Теперь, когда запустим проект, дырки будут.

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

Декали в Buil-in

Их нет. Всё печально. И шейдера крутого нет. По крайней мере я не нашёл. Но можно имитировать.

Шаги создания будут похожи на то, что написано выше для URP со своими различиями, но, чтобы не путаться, я опишу их полностью заново.

  • Копируем себе в файл с сайта доков шейдер Shader «Example/Decal». Там много примеров, нужен именно Example/Decal, выделяем, копипастим в новый шейдер проекта.
  • На основании этого шейдера делаем материал (кликаем по шейдеру правой кнопкой и Create-Material). В качестве изображения можно использовать это:
  • Создаём на сцене четырёхугольник (Quad), кидаем на него материал. Cоздаём префаб (закидываем его в Assets) и удаляем со сцены.
  • Добавляем на камеру скрипт, который будет раздавать дырки. Как альтернатива — можно создать пустой объект и на него накинуть скрипт.
    using UnityEngine;
    
    public class BulletHole : MonoBehaviour
    {
        public GameObject HolePrefab;   // префаб дырки
        private Camera cameraMain;      // кешируем камеру
    
        private void Start()
        {
            cameraMain = Camera.main;       
        }
    
        void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                RaycastHit hit;
                Ray ray = cameraMain.ScreenPointToRay(Input.mousePosition);
    
                if (Physics.Raycast(ray, out hit, 100))
                {
                    GameObject bh = Instantiate(HolePrefab, hit.point, Quaternion.LookRotation(-hit.normal));
                }
            }
        }
    }
    

    ! Разница со скриптом для URP в -hit.normal, или можно написать hit.normal * -1f
    В HolePrefab закидываем префаб, который создали ранее.
    На ровных поверхностях работает нормально, но вылезает за меш и неправильно отображается на кривых поверхностях, особенно в углах.

В итоге, я не получил того, что ожидал. Плюс к этому столкнулся с неправильным отображением материалов при конвертировании одного проекта в другой, например, стандартного в UPR. Все материалы стали розового цвета, пункт меню «Edit » Render Pipeline » Universal Render Pipeline » Upgrade Project Materials to UniversalRP Materials» не помог. То же самое было и с HDPR. Видимо, что-то я делал неправильно, но посмотрел, что в интернете многие сталкиваются с подобным, и не стал углубляться.

P.S. Дырки — это пример, забава. В качестве декали могут быть различные текстуры — повреждения, подтёки, надписи и пр., что очень улучшает восприятие игры.

Добавить комментарий