Creando árboles

Este es un breve tutorial sobre cómo crear árboles y otros tipos de vegetación desde cero.

El objetivo es no centrarse en las técnicas de modelado (hay muchos tutoriales sobre eso), sino en cómo hacer que se vean bien en Godot.

../../_images/tree_sway.gif

Empieza con un árbol

Tomé este árbol de SketchFab:

../../_images/tree_base.png

https://sketchfab.com/models/ea5e6ed7f9d6445ba69589d503e8cebf

y lo abrí en Blender.

Pintar con Vertex Colors

Lo primero que puedes hacer es usar los colores de vértice para pintar cuánto se moverá el árbol cuando haya viento. Simplemente utiliza la herramienta de pintura de colores de vértice de tu programa de modelado 3D favorito y pinta algo como esto:

../../_images/tree_vertex_paint.png

Está un poco exagerado, pero la idea es que el color indica cuánto afecta el movimiento al viento a cada parte del árbol. Esta escala representa mejor esa relación:

../../_images/tree_gradient.png

Escribe un shader personalizado para las hojas

Este es un ejemplo simple de un shader para follajes:

shader_type spatial;
render_mode depth_draw_alpha_prepass, cull_disabled, world_vertex_coords;

Este es un shader espacial. No hay eliminación de caras delanteras o traseras (por lo que las hojas se pueden ver desde ambos lados), y se utiliza un pase de alfa previo para reducir los artefactos de profundidad que resultan del uso de transparencia (y las hojas proyectan sombras). Por último, para el efecto de balanceo, se recomienda utilizar coordenadas mundiales, de modo que el árbol se pueda duplicar, mover, etc. y seguirá funcionando junto con otros árboles.

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

Aquí, se lee la textura, así como un color de transmisión que se utiliza para agregar un poco de retroiluminación a las hojas, simulando el efecto de dispersión subsuperficial.

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;
}

Este es el código para crear el movimiento de las hojas. Es básico (simplemente usa una onda sinusoidal multiplicada por el tiempo y la posición del eje, pero funciona bien). Observa que la intensidad se multiplica por el color. Cada eje utiliza un pequeño factor de multiplicación cercano a 1.0 diferente para que los ejes no aparezcan sincronizados.

Finalmente todo lo que queda es el fragment shader:

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;
}

Y eso es prácticamente todo.

El shader del tronco es similar, excepto que no escribe en el canal alfa (por lo tanto, no se necesita un preprocesamiento alfa) y no requiere la transmisión para funcionar. Ambos shaders pueden mejorarse agregando mapeo de normales, AO y otros mapas.

Mejorando el shader

Hay muchos más recursos que puedes leer sobre cómo hacer esto. Ahora que conoces los conceptos básicos, te recomiendo leer el capítulo de GPU Gems3 sobre cómo Crysis hace esto (concéntrate principalmente en el código de movimiento, ya que muchas otras técnicas mostradas allí están obsoletas):

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