Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Creando árboles

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

The aim is to not focus on the modeling techniques (there are plenty of tutorials about that), but how to make them look good in 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

The first thing you may want to do is to use the vertex colors to paint how much the tree will sway when there is wind. Just use the vertex color painting tool of your favorite 3D modeling program and paint something like this:

../../_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

This is an example of a shader for leaves:

shader_type spatial;
render_mode depth_prepass_alpha, 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 : source_color;
uniform vec4 transmission : source_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