Celestial Shader 2

An improved version of my “Celestial Shader”. It’s still a very simple non-PBR sky shader. But now it has a simple sun, better clouds and a very simple day/night system.

For more details, please take a look to the sample/demo project (see below) on my github, or watch my youtube video (its in spanish). The demo project is the same that the previous shader, remember to change the shader in the material with the lastest improved version (celestial_improved_c.gdshader).

Shader code
shader_type sky;

uniform sampler2D sky_texture;
uniform float power = 0.2;
uniform float scale_a = 0.5;
uniform float scale_b = 0.3;
uniform float speed = 0.2;
uniform vec2 speed_a = vec2(0.1);
uniform vec2 speed_b = vec2(0.1);
uniform float density : hint_range(0.0, 2.0) = 0.9;
uniform float grayness : hint_range(0.0, 1.0) = 0.2;
uniform float cloud_light = 1.0;
uniform float cloud_distortion = 0.2;

uniform vec3 sky_color_a0 : source_color = vec3(0.5, 0.8, 1.0);
uniform vec3 sky_color_b0 : source_color = vec3(0.3, 0.5, 1.0);
uniform vec3 sky_color_a1 : source_color = vec3(0.125, 0.2, 0.25);
uniform vec3 sky_color_b1 : source_color = vec3(0.075, 0.125, 0.25);

uniform vec3 ground_color_a0 : source_color = vec3(1.0, 0.8, 0.5);
uniform vec3 ground_color_b0 : source_color = vec3(1.0, 0.5, 0.3);
uniform vec3 ground_color_a1 : source_color = vec3(0.25, 0.2, 0.125);
uniform vec3 ground_color_b1 : source_color = vec3(0.25, 0.125, 0.075);

uniform vec3 sun_color_a : source_color = vec3(1.0, 0.98, 0.025);
uniform vec3 sun_color_b : source_color = vec3(1.0, 0.5, 0.0);
uniform float sun_size = 0.995; 
uniform float sun_softness = 0.002;
uniform vec2 sunset_range = vec2(-0.1, 0.3);

float to_grayscale(vec3 color) {
	return dot(color, vec3(0.299, 0.587, 0.114));
}

vec3 do_ceil(vec3 eye, vec3 sun) {
	vec3 mix_0 = mix(sky_color_a0, sky_color_b0, eye.y);
	vec3 mix_1 = mix(sky_color_a1, sky_color_b1, eye.y);
	return mix(mix_1, mix_0, smoothstep(sunset_range.x, sunset_range.y, sun.y));
}

vec3 do_floor(vec3 eye, vec3 sun) {
	vec3 mix_0 = mix(ground_color_a0, ground_color_b0, -eye.y);
	vec3 mix_1 = mix(ground_color_a1, ground_color_b1, -eye.y);
	return mix(mix_1, mix_0, smoothstep(sunset_range.x, sunset_range.y, sun.y));
}

void sky() {
	float fade = pow(abs(EYEDIR.y), power);
	vec2 uv_a = (EYEDIR.xz / EYEDIR.y) * scale_a + TIME * speed_a * speed;
	vec2 uv_b = (EYEDIR.xz / EYEDIR.y) * scale_b + TIME * speed_b * speed;
	uv_b += texture(sky_texture, uv_a).rg * cloud_distortion;
	vec3 clouds_a = texture(sky_texture, uv_a).rgb * fade;
	vec3 clouds_b = texture(sky_texture, uv_b).rgb * fade;
	vec3 clouds = smoothstep(density, 2.0, clouds_a + clouds_b);
	vec3 sky_back = EYEDIR.y > 0.0 ? do_ceil(EYEDIR, LIGHT0_DIRECTION) : vec3(0.0);
	
	// sky + clouds
	vec3 sky_with_clouds = sky_back + clouds * cloud_light;
	
	// the sun is easy to calculate thanks to the dot product between EYEDIR and LIGHT0_DIRECTION
	float sun_dot = max(0.0, dot(EYEDIR, LIGHT0_DIRECTION)); 
	float sun = smoothstep(sun_size, sun_size + sun_softness, sun_dot);
	
	// draw the sun + sky
	COLOR = vec3(0.0);
	COLOR = EYEDIR.y > 0.0 ? mix(sky_with_clouds, vec3(to_grayscale(sky_with_clouds)), grayness) : COLOR;
	COLOR += sun * mix(sun_color_b, sun_color_a, smoothstep(sunset_range.x, sunset_range.y, LIGHT0_DIRECTION.y));
	
	// draw the ground over the sky
	COLOR = EYEDIR.y < 0.0 ? do_floor(EYEDIR, LIGHT0_DIRECTION) : COLOR; 	
}
Tags
clouds, day and night, sky, Sun
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.

More from ProfesorShader

Related shaders

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments