Live Version:


GLSL / ShaderToy Code

#define S(a, b, t) smoothstep(a, b, t)

float createTaperBox(vec2 point, float bottomWidth, float topWidth, float yBottom, float yTop, float blur) {
    // Bottom edge    
    float m = S(-blur, blur, point.y - yBottom);
    // Top edge
    m *= S(blur, -blur, point.y - yTop);
    // Sides, mirrored
    point.x = abs(point.x);
    
    float w = mix(bottomWidth, topWidth, (point.y - yBottom) / (yTop - yBottom));
    m *= S(blur, -blur, point.x - w);
    
    return m;
}

vec4 createTree(vec2 uv, vec3 color, float blur) {
    
    // --- Trunk ---
    float m = createTaperBox(uv, 0.03, 0.03, -0.05, 0.25, blur);
    // --- Canopy 1 ---
    m += createTaperBox(uv, 0.2, 0.1, 0.25, 0.5, blur);
    // --- Canopy 2 ---
    m += createTaperBox(uv, 0.15, 0.05, 0.5, 0.75, blur);
    // --- Top ---
    m += createTaperBox(uv, 0.1, 0.0, 0.75, 1.0, blur);
    
    float shadow = createTaperBox(uv - vec2(0.2, 0.0), 0.1, 0.5, 0.15, 0.25, blur);
    shadow += createTaperBox(uv + vec2(0.25, 0.0), 0.1, 0.5, 0.45, 0.5, blur);
    shadow += createTaperBox(uv - vec2(0.2, 0.0), 0.1, 0.5, 0.7, 0.75, blur);
    color -= shadow * 0.8;
    //m = 1.0;
    
    return vec4(color, m);
}

float GetHeight(float x) {
    return sin(x * 0.435) + sin(x) * 0.3;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    // Move origin to the center
    vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    uv.x += iTime * 0.1;
	//uv.y += 0.5;
    uv *= 5.0;
    vec4 color = vec4(0.0);
    
    float blur = 0.005;
    
    float id = floor(uv.x);
    float n = fract(sin(id * 234.12) * 3854.3) * 2.0 - 1.0;
    float x = n * 0.3;
    float y = GetHeight(uv.x);
    // Ground
    color += S(blur, -blur, uv.y + y);
    
    y = GetHeight(id + 0.5 + x);
    
    uv.x = fract(uv.x) - 0.5;
    vec4 tree = createTree((uv - vec2(x, -y)) * vec2(1.0, 1.0 + n * 0.25), vec3(1.0), blur);
    
    // Visualize coords
    //color.rb = uv;
    
    color = mix(color, tree, tree.a);
    
    float thickness = 1.0 / iResolution.y;
    
    // See axes
    //if (abs(uv.x) < thickness) { color.g = 1.0; }
    //if (abs(uv.y) < thickness) { color.r = 1.0; }

    // Output to screen
    fragColor = color;
}

Tutorial I followed:


Resources:
ShaderToy

Leave a Reply

Your email address will not be published. Required fields are marked *