Basic Self-shadowing from Heightmap

Basic implementation of self shadowing using a heightmap texture and an arbitrary sun direction. Loosely based on this

Shader code
shader_type spatial; 
uniform sampler2D albedo : source_color;
uniform vec4 color : source_color = vec4(1.0);
uniform sampler2D normal : hint_normal;
uniform sampler2D heightmap : source_color;
uniform vec3 light_dir = vec3(0.5, -1.0, 0.2); //light direction
uniform float height_scale = 2.0;
uniform float shadow_strength = 0.8;
uniform int steps = 32; //num of ray steps
uniform float step_size = 0.004; //distance between samples

void fragment() {
    vec3 L = normalize(-light_dir);

    vec2 uv = UV;
    
    float h = texture(heightmap, uv).r * height_scale;

    vec2 light_uv_dir = normalize(L.xz) * step_size;

    float y_for_1_dist = L.y / length(L.xz);

    float light_height = h;
    float shadow = 1.0;

    //March in light direction
    for (int i = 0; i < steps; i++) {
        uv += light_uv_dir;

        if (uv.x < 0.0 || uv.y < 0.0 || uv.x > 1.0 || uv.y > 1.0)
            break;

        light_height += y_for_1_dist * step_size * 256.0;

        float sample_h = texture(heightmap, uv).r * height_scale;

        if (sample_h > light_height) {
            shadow = 1.0 - shadow_strength;
            break;
        }
    }

	ALBEDO = texture(albedo,UV).rgb * color.rgb * shadow;
	NORMAL_MAP = texture(normal,UV).rgb;
}
Tags
Height Map, Self Shadow, shadow, Test
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

2D Cel / Toon Shader v2 (Basic)

Basic Vector Sprite Upscaling

Basic Cloud Shader

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments