Мы периодически встречаемся с друзьями из старой (древней) команды "Accept Corp".
SpeccyWiki: http://speccy.info/Accept_Corp
Вспоминаем былые времена, что творили на ZX Spectrum, немножко ностальгируем. Это всегда приятные встречи старых друзей.
К чему я это говорю? К тому что создание данного пост эффекта навеяно именно теми временами из 90х годов, когда появилась мода в Demo рендерить 3D сцены из блоков Chunky.
Как это выглядит:
Мы не будем останавливаться на моментах, описанных в предыдущей вводной статье: Unity3D: Simple post process effect
Пропустим очевидные манипуляции. К тому же в данном подходе много общего.
Сама суть эффекта заключается в следующем:
- результат эффекта будет монохромный, черные пиксели на белом фоне;
- размер исходных блоков chunky сделаем 4x4 пикселя;
- спрайты chunky будем выбирать из заранее подготовленной текстуры. Выглядит она как полоска 64x4 пикселя, логически это наши 16 спрайтов 4x4 пикселя:
Маленькая правда? :) Для наглядности увеличим картинку в 4 раза:
- число спрайтов 16 соответствует количеству оттенков белого, которые мы будем использовать. Так же это обусловлено рисунком, комбинациями пикселей в каждой градации;
- мы выбираем из текстуры экрана цвет, приводим к чёрно-белому, условно соответствующему очередному блоку;
- приводим значение градации к индексу спрайта в листе chunky;
- и выводим сам спрайт.
Где:
1) - Уже знакомое нам, по прошлой статье, приведение экранных координат к текстурным
2) - Управление яркостью картинки, нужное больше для баловства и немножко для тестов;
3) - Перевод в grayscale;
4) - Индекс спрайта в листе;
5) - Расчет координат спрайта в листе chunky;
6) - Вывод.
Для
наших экспериментов нам потребуется сцена, с объектами или картинками, не
важно, главное по пестрее. Я набросал такую:
На этой
сцене отлаживался не один пост эффект, поэтому все что на ней присутствует –
закономерно и не лишнее.
Подготовим
файлы. Мы будем работать с файлом шейдера и скриптом.
Начнем
с шейдера.
В папке Assets кликаем правой кнопкой мыши и выбираем:
Create->Shader-> NewImageEffectShader.
Нам
будет предложено на выбор несколько типов шейдеров, но это не так важно,
внутренности мы перепишем. Я переименовал созданный файл в «Pixelation».
Открываем и зачищаем от всего лишнего до такого вида:
Обратите внимание на то, что входные данные пиксельного
(фрагментного, привык я к терминологии HLSL) шейдера описывает структура
v2f_img. Ее вполне достаточно для нас.
Далее добавляем входные параметры шейдера и необходимый код
как в примере:
float2 BlockCount – количество кирпичиков на экране (псевдопикселей)
по X и Y;
float2 BlockSize – размеры кирпичиков тоже по X и Y;
Шейдер простой, вся суть в
функции floor. Из справки:
floor(x) - возвращает самое большое целое число, которое
является меньше чем или равным x.
Назначение и подготовку BlockCount и BlockSize рассмотрим в
скрипте эффекта.
Как создать новый скрипт я писать не буду, но стоит уточнить
вот что.
Нам потребуется импортировать некоторые стандартные ассеты,
а именно:
Assets->Import package->Effects
С точки зрения изучения пост эффектов нам интересен весь
пакет, в дальнейшем можно самостоятельно почитать типовые эффекты, входящие в
него. Но пока на нужен только ImageEffectBase.cs что бы наследовать от него
класс нашего скрипта.
В результате у нас должен
получиться вот такой код:
BlockCount – исходное количество блоков по горизонтали;
k – понятно из определения, коэффициент соотношения сторон
экрана;
count – вектор в который складываем расчетные значения
количества кирпичиков по горизонтали и вертикали;
size – расчетное значение размеров кирпичиков, основанное на
их количестве и коэффициенте соотношения сторон экрана.
Может
быть лишнее, но я хотел бы пояснить то, что в шейдере мы имеем дело с
текстурами размером (1f, 1f) не зависимо от их реальных размеров в пикселях. И
т.к. текстурные координаты носят относительный характер, то эту самую
относительность мы и выражаем в size. Для пущей очевидности замечу, что size
делает условные пикселы квадратными на всех разрешениях мониторов с разным
соотношением сторон.
Далее
файл скрипта перетаскиваем на объект нашей сцены - камеру, в поле скрипта
Shader перетаскиваем наш шейдер. Итог:
Скриптов для подсчета fps в Unity много. Способы подсчета основываются на различных исходных данных и принципах. На данный момент выбрал такой вариант:
using UnityEngine;
public class Fps : MonoBehaviour
{
private const float UpdateInterval = 1.0f;
private float _timeleft;
private float _lastTime;
private float _timeSpan;
private int _lastFrame;
private int _frames;
private float _fps;