Создание деревьев

Это краткое руководство о том, как создавать деревья и другие виды растительности с нуля.

The aim is to not focus on the modelling techniques (there are plenty of tutorials about that), but how to make them look good in Godot.

../../_images/tree_sway.gif

Начните с дерева

Я взял это дерево из SketchFab:

../../_images/tree_base.png

https://sketchfab.com/models/ea5e6ed7f9d6445ba69589d503e8cebf

и открыл его в Blender.

Рисование цветами вершин

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

../../_images/tree_vertex_paint.png

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

../../_images/tree_gradient.png

Напишите пользовательский шейдер для листьев

Это простой пример шейдера для листьев:

shader_type spatial;
render_mode depth_draw_alpha_prepass, cull_disabled, world_vertex_coords;

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

uniform sampler2D texture_albedo : hint_albedo;
uniform vec4 transmission : hint_color;

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

uniform float sway_speed = 1.0;
uniform float sway_strength = 0.05;
uniform float sway_phase_len = 8.0;

void vertex() {
    float strength = COLOR.r * sway_strength;
    VERTEX.x += sin(VERTEX.x * sway_phase_len * 1.123 + TIME * sway_speed) * strength;
    VERTEX.y += sin(VERTEX.y * sway_phase_len + TIME * sway_speed * 1.12412) * strength;
    VERTEX.z += sin(VERTEX.z * sway_phase_len * 0.9123 + TIME * sway_speed * 1.3123) * strength;
}

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

Наконец, все, что осталось, - это шейдер фрагментов:

void fragment() {
    vec4 albedo_tex = texture(texture_albedo, UV);
    ALBEDO = albedo_tex.rgb;
    ALPHA = albedo_tex.a;
    METALLIC = 0.0;
    ROUGHNESS = 1.0;
    TRANSMISSION = transmission.rgb;
}

И это практически все.

Шейдер trunk похож, за исключением того, что он не записывается в альфа-канал (поэтому не требуется предварительный альфа-пасс) и не требует передачи для работы. Оба шейдера можно улучшить, добавив нормальное отображение, AO и другие карты.

Улучшение шейдера

Есть много других ресурсов о том, как это сделать, которые вы можете прочитать. Теперь, когда вы знаете основы, рекомендуем прочитать главу из GPU Gems3 о том, как Crysis делает это (сосредоточьтесь в основном на коде sway, так как многие другие методы, показанные там, устарели):

https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch16.html