sky shader
Asked Answered
W

9

0

im trying to write a skyshader
heres what i have so far;

shader_type sky;
render_mode use_quarter_res_pass;



group_uniforms sky;
	uniform vec3 top_color : source_color = vec3( 0.1, 0.6, 1.0 );
	uniform vec3 bottom_color : source_color = vec3( 0.4, 0.8, 1.0 );


group_uniforms horizon;
	uniform vec3 horizon_color : source_color = vec3( 0.0, 0.7, 0.8 );
	uniform float horizon_blur : hint_range( 0.0, 1.0, 0.01 ) = 0.05;

group_uniforms sun; // First DirectionalLight3D will be the sun
	uniform vec3 sun_color : source_color = vec3( 10.0, 8.0, 1.0 );
	uniform float sun_size : hint_range( 0.01, 1.0 ) = 0.2;
	uniform float sun_blur : hint_range( 0.01, 20.0 ) = 10.0;

group_uniforms clouds;
	uniform vec3 clouds_edge_color : source_color = vec3( 0.8, 0.8, 0.98 );
	uniform vec3 clouds_main_color : source_color = vec3( 1.0, 1.0, 1.00 );
	uniform float clouds_speed : hint_range( 0.0, 20.0, 0.01 ) = 2.0;
	uniform float clouds_scale : hint_range( 0.0, 4.0, 0.01 ) = 1.0;
	uniform float clouds_cutoff : hint_range( 0.0, 1.0, 0.01 ) = 0.3;
	
	uniform float clouds_weight : hint_range( 0.0, 1.0, 0.01 ) = 0.0;
	uniform float clouds_blur : hint_range( 0.0, 1.0, 0.01 ) = 0.25;
	const mat2 m = mat2(vec2( 1.6, 1.2), vec2(-1.2, 1.6));


vec2 hash( vec2 p ) {
	p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));
	return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);
}
float noise( in vec2 p ) {
	const float K1 = 0.366025404; // (sqrt(3)-1)/2;
	const float K2 = 0.211324865; // (3-sqrt(3))/6;
	vec2 i = floor(p + (p.x + p.y)*K1);
	vec2 a = p - i + (i.x + i.y) * K2;
	vec2 o = (a.x > a.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
	vec2 b = a - o + K2;
	vec2 c = a - 1.0 + 2.0 * K2;
	vec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0 );
	vec3 n = h * h * h * h * vec3(dot(a, hash(i + 0.0)), dot(b, hash(i + o)), dot(c, hash(i + 1.0)));
	return dot(n, vec3(70.0));
}
float fbm(vec2 n) {
	float total = 0.0, amplitude = 0.1;
	for (int i = 0; i < 7; i++) {
		total += noise(n) * amplitude;
		n = m * n;
		amplitude *= 0.4;
	}
	return total;
}
void sky()
{
	float time = TIME;
	vec2 _sky_uv = EYEDIR.xz / sqrt( EYEDIR.y );
	
	float _eyedir_y = abs( sin( EYEDIR.y * PI * 0.5 ));

	//SKYCOLOR
	vec3 _sky_color = mix(bottom_color, top_color, _eyedir_y );
	_sky_color = mix( _sky_color, vec3( 0.0 ), clamp(( 0.7 - clouds_cutoff ) * clouds_weight, 0.0, 1.0 ));
	COLOR = _sky_color;

	//HORIZON
	float _horizon_amount = 0.0;
	if( EYEDIR.y < 0.0 )
	{
		_horizon_amount = clamp( abs( EYEDIR.y ) / horizon_blur, 0.0, 1.0 );
		vec3 _horizon_color = mix( horizon_color, _sky_color, 0.9 );
		_horizon_color = mix( _horizon_color, vec3( 0.0 ), ( 1.0 - clouds_cutoff ) * clouds_weight * 0.7 );
		COLOR = mix( COLOR, _horizon_color, _horizon_amount );
	}
	//SUN
	float _sun_distance = 0.0;
	if( LIGHT0_ENABLED )
	{
		_sun_distance = distance( EYEDIR, LIGHT0_DIRECTION );
		// Bigger sun near the horizon
		float _sun_size = sun_size + cos( LIGHT0_DIRECTION.y * PI ) * sun_size * 0.25;
		// Finding sun disc and edge blur
		float _sun_amount = clamp(( 1.0 - _sun_distance / _sun_size ) / sun_blur, 0.0, 1.0 );
		if( _sun_amount > 0.0 )
		{
			vec3 _sun_color = sun_color;
			_sun_amount *= 1.0 - _horizon_amount;
			// Leveling the "glow" in color
			if( _sun_color.r > 1.0 || _sun_color.g > 1.0 || _sun_color.b > 1.0 )
				_sun_color *= _sun_amount;
			COLOR = mix( COLOR, _sun_color, _sun_amount );
		}
	}
	//CLOUDS
	if( EYEDIR.y > 0.0 )
	{
		vec3 normal = normalize(EYEDIR);
		
		
		vec3 plane_intersect = normal / (normal.y + clouds_cutoff);
		
		vec2 p = plane_intersect.xz;
		p.y *= -1.0;
		vec2 uv = p;
		
		time = time * clouds_speed;
		float q = fbm(uv * clouds_scale * 0.5);
		
		//ridged noise shape
		float r = 0.0;
		time = TIME * clouds_speed * 0.3;
		uv *= clouds_scale;
		uv -= q - time;
		float weight = 0.8;
		for(int i = 0; i < 8; i++){
			r += abs(weight*noise( uv ));
			uv = m*uv + time;
			weight *= 0.7;
		}
		
		//noise shape
		float f = 0.0;
		time = TIME * clouds_speed * 0.4;
		uv = p;
		uv *= clouds_scale;
		uv -= q - time;
		weight = 0.7;
		for(int i = 0; i < 8; i++){
			f += weight*noise( uv );
			uv = m*uv + time;
			weight *= 0.6;
		}
		
		f *= r + f;
		
		//noise colour
		float c = 0.0;
		time = TIME * clouds_speed * 2.0;
		uv = p;
		uv *= clouds_scale * 1.5;
		uv -= q - time;
		weight = 0.4;
		for(int i = 0; i < 7; i++){
			c += weight*noise( uv );
			uv = m*uv + time;
			weight *= 0.6;
		}
		
		//noise ridge colour
		float c1 = 0.0;
		time = TIME * clouds_speed * 5.0;
		uv = p;
		uv *= clouds_scale * 3.0;
		uv -= q - time;
		weight = 0.4;
		for (int i = 0; i < 7; i++){
			c1 += abs(weight*noise( uv ));
			uv = m*uv + time;
			weight *= 0.6;
		}
		
		c += c1;
		
		
		
		
		float _clouds_amount = clamp( c, 0.0, 1.0 );
		_clouds_amount *= clamp( abs( EYEDIR.y ) / clouds_blur, 0.0, 1.0 );
		vec3 skycolour = COLOR;
		vec3 clouds = mix(clouds_edge_color,  clouds_main_color , pow( _clouds_amount,2.0) );
		COLOR = mix( skycolour, clouds , _clouds_amount);
	}
}

i really like this shader from shadertoy> https://www.shadertoy.com/view/tdSXzD
i would like to add raymarching to the clouds in my current shader, also stars and the aurora borealis.
i dont need dynamic time of day or turbidity.
could someone help adding those to the current shader?

im also wondering if raymarching is too heavy for performance on modern machines or not.
if so, could it be faked somehow?

Willams answered 30/5, 2023 at 9:7 Comment(0)
P
0

That shadertoy is insane. I wish people would release with licenses though, and write readable code. Most of the stuff on there might as well be in some alien script.

I've seen real time ray marching, but it definitely has a cost. You'll just have to decide if the sky is worth that much performance or if the game can handle it.

Pruter answered 30/5, 2023 at 10:47 Comment(0)
W
0

Pruter the code is unreadable yes, i thought it was me not understanding it lol, but it looks great!
sky isnt really a must to me to be extremely good, but it should look better than what i have now.
what are the ways to 'fake' shadows in order to avoid raymarching?

Willams answered 30/5, 2023 at 11:0 Comment(0)
P
0

I've never done a sky. It's just what I've seen other people posting, usually in Unity.

Pruter answered 30/5, 2023 at 11:32 Comment(0)
W
0

Pruter
found this on github about raymarching in godot and it works, no errors. but im not gonna use it. looks way too expensive to use

shader_type sky;
render_mode use_half_res_pass, use_quarter_res_pass;

uniform sampler3D worlnoise : filter_linear_mipmap, repeat_enable;
uniform sampler3D perlworlnoise : filter_linear_mipmap, repeat_enable;
uniform sampler2D weathermap : filter_linear_mipmap, repeat_enable;

uniform float _density : hint_range(0.01, 0.2) = 0.05;
uniform float cloud_coverage :hint_range(0.1, 1.0) = 0.25;
uniform float _time_scale :hint_range(0.0, 20.0) = 1.0;
uniform float _time_offset : hint_range(0.0, 1000.0, 0.5) = 0.0;

// Approximately earth sizes
const float g_radius = 6000000.0; //ground radius
const float sky_b_radius = 6001500.0;//bottom of cloud layer
const float sky_t_radius = 6004000.0;//top of cloud layer

uniform float rayleigh : hint_range(0, 64) = 2.0;
uniform vec4 rayleigh_color : source_color = vec4(0.26, 0.41, 0.58, 1.0);
uniform float mie : hint_range(0, 1) = 0.005;
uniform float mie_eccentricity : hint_range(-1, 1) = 0.8;
uniform vec4 mie_color : source_color = vec4(0.63, 0.77, 0.92, 1.0);

uniform float turbidity : hint_range(0, 1000) = 10.0;
uniform float sun_disk_scale : hint_range(0, 360) = 1.0;
uniform vec4 ground_color : source_color = vec4(1.0);
uniform float exposure : hint_range(0, 128) = 0.1;

const vec3 UP = vec3( 0.0, 1.0, 0.0 );

// Sun constants
const float SOL_SIZE = 0.00872663806;
const float SUN_ENERGY = 1000.0;

// optical length at zenith for molecules
const float rayleigh_zenith_size = 8.4e3;
const float mie_zenith_size = 1.25e3;

// From: https://www.shadertoy.com/view/4sfGzS credit to iq
float hash(vec3 p) {
	p  = fract( p * 0.3183099 + 0.1 );
	p *= 17.0;
	return fract(p.x * p.y * p.z * (p.x + p.y + p.z));
}

// Utility function that maps a value from one range to another. 
float remap(float originalValue,  float originalMin,  float originalMax,  float newMin,  float newMax) {
	return newMin + (((originalValue - originalMin) / (originalMax - originalMin)) * (newMax - newMin));
}

// Phase function
float henyey_greenstein(float cos_theta, float g) {
	const float k = 0.0795774715459;
	return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));
}

// Simple Analytic sky. In a real project you should use a texture
vec3 atmosphere(vec3 eye_dir) {
	float zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );
	float sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;
	float sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);

	// Rayleigh coefficients.
	float rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) );
	vec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001;
	// mie coefficients from Preetham
	vec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434;

	// optical length
	float zenith = acos(max(0.0, dot(UP, eye_dir)));
	float optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253));
	float rayleigh_scatter = rayleigh_zenith_size * optical_mass;
	float mie_scatter = mie_zenith_size * optical_mass;

	// light extinction based on thickness of atmosphere
	vec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter));

	// in scattering
	float cos_theta = dot(eye_dir, normalize(LIGHT0_DIRECTION));

	float rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0));
	vec3 betaRTheta = rayleigh_beta * rayleigh_phase;

	float mie_phase = henyey_greenstein(cos_theta, mie_eccentricity);
	vec3 betaMTheta = mie_beta * mie_phase;

	vec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5));
	// Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js
	Lin *= mix(vec3(1.0), pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * extinction, vec3(0.5)), clamp(pow(1.0 - zenith_angle, 5.0), 0.0, 1.0));

	// Hack in the ground color
	Lin  *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, eye_dir)));

	// Solar disk and out-scattering
	float sunAngularDiameterCos = cos(SOL_SIZE * sun_disk_scale);
	float sunAngularDiameterCos2 = cos(SOL_SIZE * sun_disk_scale*0.5);
	float sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);
	vec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;
	// Note: Add nightime here: L0 += night_sky * extinction

	vec3 color = (Lin + L0) * 0.04;
	color = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));
	color *= exposure;
	return color;
}

float GetHeightFractionForPoint(float inPosition) { 
	float height_fraction = (inPosition -  sky_b_radius) / (sky_t_radius - sky_b_radius); 
	return clamp(height_fraction, 0.0, 1.0);
}

vec4 mixGradients(float cloudType){
	const vec4 STRATUS_GRADIENT = vec4(0.02f, 0.05f, 0.09f, 0.11f);
	const vec4 STRATOCUMULUS_GRADIENT = vec4(0.02f, 0.2f, 0.48f, 0.625f);
	const vec4 CUMULUS_GRADIENT = vec4(0.01f, 0.0625f, 0.78f, 1.0f);
	float stratus = 1.0f - clamp(cloudType * 2.0f, 0.0, 1.0);
	float stratocumulus = 1.0f - abs(cloudType - 0.5f) * 2.0f;
	float cumulus = clamp(cloudType - 0.5f, 0.0, 1.0) * 2.0f;
	return STRATUS_GRADIENT * stratus + STRATOCUMULUS_GRADIENT * stratocumulus + CUMULUS_GRADIENT * cumulus;
}

float densityHeightGradient(float heightFrac, float cloudType) {
	vec4 cloudGradient = mixGradients(cloudType);
	return smoothstep(cloudGradient.x, cloudGradient.y, heightFrac) - smoothstep(cloudGradient.z, cloudGradient.w, heightFrac);
}

float intersectSphere(vec3 pos, vec3 dir,float r) {
    float a = dot(dir, dir);
    float b = 2.0 * dot(dir, pos);
    float c = dot(pos, pos) - (r * r);
	float d = sqrt((b*b) - 4.0*a*c);
	float p = -b - d;
	float p2 = -b + d;
    return max(p, p2) / (2.0 * a);
}

// Returns density at a given point
// Heavily based on method from Schneider
float density(vec3 pip, vec3 weather, float mip) {
	float time = TIME;
	vec3 p = pip;
	p.x += time * 10.0 * _time_scale + _time_offset;
	float height_fraction = GetHeightFractionForPoint(length(p));
	vec4 n = textureLod(perlworlnoise, p.xyz*0.00008, mip-2.0);
	float fbm = n.g*0.625+n.b*0.25+n.a*0.125;
	float g = densityHeightGradient(height_fraction, weather.r);
	float base_cloud = remap(n.r, -(1.0-fbm), 1.0, 0.0, 1.0);
	float weather_coverage = cloud_coverage*weather.b;
	base_cloud = remap(base_cloud*g, 1.0-(weather_coverage), 1.0, 0.0, 1.0);
	base_cloud *= weather_coverage;
	p.xy -= time * 40.0;
	vec3 hn = textureLod(worlnoise, p*0.001, mip).rgb;
	float hfbm = hn.r*0.625+hn.g*0.25+hn.b*0.125;
	hfbm = mix(hfbm, 1.0-hfbm, clamp(height_fraction*4.0, 0.0, 1.0));
	base_cloud = remap(base_cloud, hfbm*0.4 * height_fraction, 1.0, 0.0, 1.0);
	return pow(clamp(base_cloud, 0.0, 1.0), (1.0 - height_fraction) * 0.8 + 0.5);
}

vec4 march(vec3 pos,  vec3 end, vec3 dir, int depth) {
	const vec3 RANDOM_VECTORS[6] = {vec3( 0.38051305f,  0.92453449f, -0.02111345f),vec3(-0.50625799f, -0.03590792f, -0.86163418f),vec3(-0.32509218f, -0.94557439f,  0.01428793f),vec3( 0.09026238f, -0.27376545f,  0.95755165f),vec3( 0.28128598f,  0.42443639f, -0.86065785f),vec3(-0.16852403f,  0.14748697f,  0.97460106f)};
	float T = 1.0;
	float alpha = 0.0;
	float ss = length(dir);
	dir = normalize(dir);
	vec3 p = pos + hash(pos * 10.0) * ss;
	const float t_dist = sky_t_radius-sky_b_radius;
	float lss = (t_dist / 36.0);
	vec3 ldir = normalize(LIGHT0_DIRECTION);
	vec3 L = vec3(0.0);
	int count=0;
	float t = 1.0;
	float costheta = dot(ldir, dir);
	// Stack multiple phase functions to emulate some backscattering
	float phase = max(max(henyey_greenstein(costheta, 0.6), henyey_greenstein(costheta, (0.4 - 1.4 * ldir.y))), henyey_greenstein(costheta, -0.2));
	// Precalculate sun and ambient colors
	// This should really come from a uniform or texture for performance reasons
	vec3 atmosphere_sun = atmosphere(LIGHT0_DIRECTION) * LIGHT0_ENERGY * ss * 0.1;
	vec3 atmosphere_ambient = atmosphere(normalize(vec3(1.0, 1.0, 0.0)));
	vec3 atmosphere_ground = atmosphere(normalize(vec3(1.0, -1.0, 0.0)));
	
	const float weather_scale = 0.00006;
	float time = TIME * 0.003 * _time_scale + 0.005*_time_offset;
	vec2 weather_pos = vec2(time * 0.9, time);
	
	for (int i = 0; i < depth; i++) {
		p += dir * ss;
		vec3 weather_sample = texture(weathermap, p.xz * weather_scale + 0.5 + weather_pos).xyz;
		float height_fraction = GetHeightFractionForPoint(length(p));

		t = density(p, weather_sample, 0.0);
		float dt = exp(-_density*t*ss);
		T *= dt;
		vec3 lp = p;
		float lt = 1.0;
		float cd = 0.0;

		if (t > 0.0) { //calculate lighting, but only when we are in the cloud
			float lheight_fraction = 0.0;
			for (int j = 0; j < 6; j++) {
				lp += (ldir + RANDOM_VECTORS[j]*float(j))*lss;
				lheight_fraction = GetHeightFractionForPoint(length(lp));
				vec3 lweather = texture(weathermap, lp.xz * weather_scale + 0.5 + weather_pos).xyz;
				lt = density(lp, lweather, float(j));
				cd += lt;
			}
			
			// Take a single distant sample
			lp = p + ldir * 18.0 * lss;
			lheight_fraction = GetHeightFractionForPoint(length(lp));
			vec3 lweather = texture(weathermap, lp.xz * weather_scale + 0.5).xyz;
			lt = pow(density(lp, lweather, 5.0), (1.0 - lheight_fraction) * 0.8 + 0.5);
			cd += lt;
			
			// captures the direct lighting from the sun
			float beers = exp(-_density * cd * lss);
			float beers2 = exp(-_density * cd * lss * 0.25) * 0.7;
			float beers_total = max(beers, beers2);

			vec3 ambient = mix(atmosphere_ground, vec3(1.0), smoothstep(0.0, 1.0, height_fraction)) * _density * mix(atmosphere_ambient, vec3(1.0), 0.4) * (LIGHT0_DIRECTION.y);
			alpha += (1.0 - dt) * (1.0 - alpha);
			L += (ambient + beers_total * atmosphere_sun * phase * alpha) * T * t;
		}
	}
	return clamp(vec4(L, alpha), 0.0, 1.0);
}

void sky() {
	vec3 dir = EYEDIR;

	vec4 col = vec4(0.0);
	if (dir.y>0.0) {
		vec3 camPos = vec3(0.0, g_radius, 0.0);
		vec3 start = camPos + dir * intersectSphere(camPos, dir, sky_b_radius);
		vec3 end = camPos + dir * intersectSphere(camPos, dir, sky_t_radius);
		float shelldist = (length(end-start));
		// Take fewer steps towards horizon
		float steps = (mix(96.0, 54.0, clamp(dot(dir, vec3(0.0, 1.0, 0.0)), 0.0, 1.0)));
		vec3 raystep = dir * shelldist / steps;
		vec4 volume = march(start, end, raystep, int(steps));
		vec3 background = atmosphere(dir);
		// Draw cloud shape
		col = vec4(background*(1.0-volume.a)+volume.xyz, 1.0);
		// Blend distant clouds into the sky
		col.xyz = mix(clamp(col.xyz, vec3(0.0), vec3(1.0)), clamp(background, vec3(0.0), vec3(1.0)), smoothstep(0.6, 1.0, 1.0-dir.y));
	} else {
		col = vec4(atmosphere(dir), 1.0);
	}
	
	// Draw to quarter res buffer for reflections
	// Draw to half res buffer for main sky
	if (AT_QUARTER_RES_PASS && AT_CUBEMAP_PASS) {
		COLOR = col.xyz;
		ALPHA = 1.0;
	} else if (AT_HALF_RES_PASS && !AT_CUBEMAP_PASS) {
		COLOR = col.xyz;
		ALPHA = 1.0;
	} else if (AT_CUBEMAP_PASS) {
		COLOR = QUARTER_RES_COLOR.rgb;
	} else {
		COLOR = HALF_RES_COLOR.rgb; // Change to col.rgb for full resolution
	}
}
Willams answered 30/5, 2023 at 15:16 Comment(0)
P
0

If you make good use of the profiler you can probably comment out parts of it to measure the effect and thus optimize it.

Plumate answered 30/5, 2023 at 15:28 Comment(0)
W
0

heres my simple sky shader code;
it has basic; clouds, stars , moon or sun, 4 color skygradient

shader_type sky;
render_mode use_quarter_res_pass;



group_uniforms sky;
	uniform vec3 top_color : source_color = vec3( 0.12, 0.30, 0.38 );
	uniform vec3 mid_color : source_color = vec3( 0.23, 0.50, 0.63 );
	uniform vec3 bottom_color : source_color = vec3( 0.54, 1.0, 0.93 );


group_uniforms ground;
	uniform vec3 ground_color : source_color = vec3( 0.25, 0.19, 0.14 );

group_uniforms sun; // First DirectionalLight3D will be the sun
	uniform vec3 sun_color : source_color = vec3( 1.0, 1.0, 1.0 );
	uniform float sun_intesity : hint_range(1.0, 10.0, 0.5) = 10.0;
	uniform float sun_size : hint_range( 0.01, 1.0 ) = 0.1;
	uniform float sun_blur : hint_range( 0.01, 5.0 ) = 2.0;

group_uniforms clouds;
	uniform vec3 clouds_edge_color : source_color = vec3( 0.88, 0.92, 0.98 );
	uniform vec3 clouds_main_color : source_color = vec3( 0.54, 0.63, 0.67 );
	uniform float clouds_speed : hint_range( 0.0, 0.1, 0.005 ) = 0.01;
	uniform float clouds_scale : hint_range( 0.0, 4.0, 0.01 ) = 0.25;
	uniform float clouds_weight : hint_range( 0.0, 1.0, 0.01 ) = 0.5;
	uniform float clouds_blur : hint_range( 0.0, 1.0, 0.01 ) = 0.25;
	const mat2 m = mat2(vec2( 1.6, 1.2), vec2(-1.2, 1.6));


vec2 hash( vec2 p ) {
	p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));
	return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);
}
float noise( in vec2 p ) {
	const float K1 = 0.366025404; // (sqrt(3)-1)/2;
	const float K2 = 0.211324865; // (3-sqrt(3))/6;
	vec2 i = floor(p + (p.x + p.y)*K1);
	vec2 a = p - i + (i.x + i.y) * K2;
	vec2 o = (a.x > a.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
	vec2 b = a - o + K2;
	vec2 c = a - 1.0 + 2.0 * K2;
	vec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0 );
	vec3 n = h * h * h * h * vec3(dot(a, hash(i + 0.0)), dot(b, hash(i + o)), dot(c, hash(i + 1.0)));
	return dot(n, vec3(70.0));
}
float noise2d( in vec2 x)
{
	float xhash = cos(x.x * 37.0);
	float yhash = cos(x.y * 57.0);
	return fract (415.92653 * (xhash + yhash));
}
float NoisyStarField( in vec2 vSamplePos, float fThreshhold)
{
	float StarVal = noise2d( vSamplePos );
    if ( StarVal >= fThreshhold )
        StarVal = pow( (StarVal - fThreshhold)/(1.0 - fThreshhold), 6.0 );
    else
        StarVal = 0.0;
    return StarVal;
}
float random(vec2 co)
{
    return fract( sin( dot( co.xy, vec2( 12.9898, 78.233 ) ) ) * 43758.5453 );
}
float fbm(vec2 n) {
	float total = 0.0, amplitude = 0.1;
	for (int i = 0; i < 7; i++) {
		total += noise(n) * amplitude;
		n = m * n;
		amplitude *= 0.4;
	}
	return total;
}
void sky()
{
	float time = TIME;
//	vec2 _sky_uv = EYEDIR.xz / sqrt( EYEDIR.y );
	
	float _eyedir_y = abs( sin( EYEDIR.y * PI * 0.5 ));
	float topmask = abs(sin(EYEDIR.y * PI * 0.2));
	//SKYCOLOR
	vec3 _sky_color = vec3(1);
	_sky_color = mix(bottom_color, mid_color, _eyedir_y );
	_sky_color = mix (_sky_color,top_color, topmask * 2.0);
	COLOR = _sky_color;

	//HORIZON
	float _ground_amount = 0.0;
	if( EYEDIR.y < 0.0 )
	{
		 _ground_amount = clamp( abs( EYEDIR.y) /  _ground_amount, 0.0, 1.0 );
		vec3 _ground_color = mix( ground_color, _sky_color, 0.9 );
		COLOR = mix( COLOR, _ground_color,  _ground_amount );
	}
	//SUN
	float _sun_distance = 0.0;
	if( LIGHT0_ENABLED )
	{
		_sun_distance = distance( EYEDIR, LIGHT0_DIRECTION );
		// Bigger sun near the horizon
		float _sun_size = sun_size + cos( LIGHT0_DIRECTION.y * PI ) * sun_size * 0.25;
		// Finding sun disc and edge blur
		float _sun_amount = clamp(( 1.0 - _sun_distance / _sun_size ) / sun_blur, 0.0, 1.0 );
		vec3 _sun_color = sun_color;
		_sun_amount *= sun_intesity - _ground_amount;
		
		COLOR = mix( COLOR, _sun_color, _sun_amount );
	}
	

	//CLOUDS & STARS
	if( EYEDIR.y > 0.0 )
	{
		//skyUVs
		vec3 normal = normalize(EYEDIR);
		vec3 plane_intersect = normal / (normal.y);
			
		vec2 p = plane_intersect.xz;
		p.y *= -1.0;
		vec2 uv = p;
		//STARFIELD
		vec3 starsColor = vec3(0);
		vec2 starTile   = floor( uv * 10.0 );
    	vec2 starPos    = fract( uv * 10.0 ) * 2.0 - 1.0;
    	float starRand  = random( starTile + vec2( 1.0, 5.0 ) );
    	starRand = starRand > 0.9 ? starRand : 0.0;
		COLOR += 0.4 * vec3( 1.2, 2.0, 1.2 ) * starRand * exp( -20.0 * length( starPos));
		time = time * clouds_speed;
		float q = fbm(uv * clouds_scale * 0.5);
		
		//ridged noise shape
		float r = 0.0;
		time = TIME * clouds_speed * 0.3;
		uv *= clouds_scale;
		uv -= q - time;
		float weight = 0.8;
		for(int i = 0; i < 8; i++){
			r += abs(weight*noise( uv ));
			uv = m*uv + time;
			weight *= 0.7;
		}
		
		//noise shape
		float f = 0.0;
		time = TIME * clouds_speed * 0.2;
		uv = p;
		uv *= clouds_scale;
		uv -= q - time;
		weight = 0.7;
		for(int i = 0; i < 8; i++){
			f += weight*noise( uv );
			uv = m*uv + time;
			weight *= 0.6;
		}
		
		f *= r + f;
		
		//noise colour
		float c = 0.0;
		time = TIME * clouds_speed * 1.0;
		uv = p;
		uv *= clouds_scale * 1.5;
		uv -= q - time;
		weight = 0.4;
		for(int i = 0; i < 7; i++){
			c += weight*noise( uv );
			uv = m*uv + time;
			weight *= 0.6;
		}
		
		//noise ridge colour
		float c1 = 0.0;
		time = TIME * clouds_speed * 3.0;
		uv = p;
		uv *= clouds_scale * 3.0;
		uv -= q - time;
		weight = 0.4;
		for (int i = 0; i < 7; i++){
			c1 += abs(weight*noise( uv ));
			uv = m*uv + time;
			weight *= 0.6;
		}
		
		c += c1;
		
		
		
		
		float _clouds_amount = clamp( c, 0.0, 1.0 ) * clouds_weight;
		_clouds_amount *= clamp( abs( EYEDIR.y ) / clouds_blur, 0.0, 1.0 );
		vec3 skycolour = COLOR;
		vec3 clouds = mix(clouds_edge_color,  clouds_main_color , pow( _clouds_amount,1.0) );
		COLOR = mix( skycolour, clouds , _clouds_amount);
	}
}
Willams answered 30/5, 2023 at 16:37 Comment(0)
W
0

how do i apply some "color leveling" to the clouds noise, and use that to make the inside a darker color?

Willams answered 30/5, 2023 at 17:35 Comment(0)
L
0

Are you sure you need procedural sky in the first place? Maybe just a good looking environment texture could suffice.

Ray marching is too expensive if you want to run on variety of hardware. You can eventually have it as an on/off option. It'll also be quite time consuming to build a good looking volumetric clouds system. So I'd say it's not worth the effort. Better save precious gpu cycles (and your own time) for other things that are not mere background.

Lotus answered 30/5, 2023 at 18:41 Comment(0)
P
0

Lotus Are you sure you need procedural sky in the first place? Maybe just a good looking environment texture could suffice.

You could do the complex cloud simulation in Blender and bake it out as a HDR map. I looked into the process, it's involved but doable.

Pruter answered 30/5, 2023 at 22:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.