Создание октакля из Medieval Craft. Урок 0

Создание октакля из Medieval Craft. Урок 0

Доброго времени суток, я расскажу о том, как создать портал в ад из Medieval Craft, aka октакль (восьмиконечная звезда в круге)

octacle

В этом, если так можно сказать, цикле туториалов, я расскажу об использовании самописных шейдеров, материалов и анимированных частиц в новом Inner Core. Сегодня мы разберёмся с написанием шейдеров и их подготовкой для Minecraft.

Видеокарты используют шейдеры для для определения окончательных параметров объекта или изображения, таких как позиция вершин, способ наложения текстуры и цвет отдельно взятых пикселей. Шейдеры делятся на несколько типов, но нам понадобится только два из них: вершинный и фрагментный. Вершинный шейдер оперирует с вершинами, текстурными координатами и параметрами, передаваемыми в шейдер извне. Фрагментный шейдер используется для по-пиксельного отображения картинки, он использует информацию из вершинного шейдера и оперирует текстурами. Шейдеры в Minecraft написаны на языке GLSL, очень рекомендую ознакомится хоть немного с этим языком здесь или, для тех, кто не знает эльфийского, здесь. Также есть сайт, где можно быстро проверить свой шейдер: shadertoy.com.

Проще всего использовать уже готовые шейдеры Майнкрафта, переписав их под свои нужды, что я и буду делать. Все шейдеры Майнкрафта лежат по пути /assets/shaders/glsl в его apk файле. В моде шейдеры должны располагаться в папке /res/custom-shaders/. Очень важно, чтобы перед названием файла шейдера была приставка вашего мода, чтобы гарантировать уникальность.
В качестве образца я буду использовать entity.vertex и entity.fragment. Для октакля мне понадобится только фрагментный шейдер, а в качестве вершинного шейдера будет entity.vertex. Поэтому, я создаю два файла — mc_octacle.shader и mc_octacle_fired.shader — для обычного октакля и для подожжённого октакля.

Начну работу над mc_octacle.shader. Как говорил знаменитый скульптор Огюст Роден «Я беру камень и отсекаю всё лишнее», так и я буду брать entity.fragment и отсекать всё лишнее:

// __multiversion__
// This signals the loading code to prepend either #version 100 or #version 300 es as apropriate.


#include "fragmentVersionCentroidUV.h"
#include "uniformEntityConstants.h"
#include "uniformShaderConstants.h"
#include "util.h"

LAYOUT_BINDING(0) uniform sampler2D TEXTURE_0;
LAYOUT_BINDING(1) uniform sampler2D TEXTURE_1;

varying vec4 light;
varying vec4 fogColor;

void main()
{
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}

Шейдер выше имеет выше всё необходимое для начала работы, но сам по себе не делает почти ничего — просто отображает на месте меша белый цвет. Функция main() вызывается каждый раз, когда видеокарте нужно вычислить цвет для пикселя. Для вывода цвета используется переменная gl_FragColor, ей нужно присвоить четырёхмерный вектор, представляющий каналы цвета rgba.
Чтобы получить цвет в конкретной точке текстуры я буду использовать texture2D. Первым параметром передаётся текстура, а вторым двухмерный вектор, представляющий собой двухмерный вектор в отрезке [0,1] по обеим осям, он нам уже дан в переменной uv. Возвращает эта функция цвет — четырёхмерный вектор rgba. Чтобы получить четвёртый параметр (то есть альфа канал) нужно получить поле w (xyzw).

void main()
{
    vec3 col = vec3(1.0, 1.0, 1.0);
    // Создаю идеально белый цвет
    vec3 alpha = texture2D(TEXTURE_0, uv).www;
    // Получаю альфа-канал текстуры.
    col*=alpha;
    // Перемножаю цвет и альфа-канал для применения маски.
    gl_FragColor = vec4(col,alpha*light.x);
    // Устанавливаю точке цвет
}

Здесь текстура используется как трафарет, который накладывается на полотно идеально белого цвета. Хотел бы отдельно остановится на фрагменте с перемножением цвета, и зачем это нужно. Допустим я задам кислотно зелёный цвет vec3(0.0, 1.0, 0.0) или оранжевый vec3(1.0, 1.0, 0.0). Как же получить цвет, который в два раза темнее данных? Очень просто! Просто умножить на vec3(0.5, 0.5, 0.5).
В последней строчке я создаю цвет у которого первые три канала — rgb такие же, как и у col. А что же альфа канал? Он равен альфе из текстуры, умноженной на light. light — это четырёхмерный вектор, отображающий свет и переданный из вершинного шейдера. Это нужно для того, чтобы октакль как-то реагировал на свет. Ещё, нужно объяснить почему я умножаю альфа канал, а не col. Просто потому, что так выглядит лучше. Слева пример с умножением rgb на light, а справа с умножением альфа-канала на light

Теперь займусь mc_octacle_fired.fragment. Для этого вместо идеально-белого col будет использован огненно-красный vec3(0.9, 0.5, 0.5). Так как мне не нужно учитывать освещение для горящего октакля я и не буду его учитывать:

void main()
{
    vec3 col = vec3(0.9, 0.5, 0.5);
    vec3 alpha = texture2D(TEXTURE_0, uv).www;
    col*=alpha;
    gl_FragColor = vec4(col,alpha);
}

На этом на сегодня всё, в следующем уроке я расскажу о подготовке ресурсов (спрайтов и материалов).

Запись опубликована в рубрике InnerCore. Добавьте в закладки постоянную ссылку.

Comments

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *