godot-planet/assets/AtmosphereShader.tres

187 lines
4.6 KiB
Plaintext

[gd_resource type="ShaderMaterial" load_steps=2 format=2]
[sub_resource type="Shader" id=1]
code = "shader_type spatial; // Written by GLtracy, ported to Godot by SolarLiner
render_mode blend_add, depth_test_disable;
// math const
uniform float PI = 3.14159265359;
uniform float MAX = 100000.0;
uniform vec3 position = vec3(0.0);
// scatter const
uniform float length_scale = 1000.0;
uniform float ground_radius = 128.0;
uniform float atmosphere_radius = 128.05;
uniform vec4 scattering_cf: hint_color = vec4(0.105707, 0.375536, 0.92076, 1.0);
uniform float scattering_power = 35.92;
uniform float rayleight_cf: hint_range(0.001, 1.0) = 0.07;
uniform float mie_cf: hint_range(0.001, 1.0) = 0.04;
uniform int scatter_passes: hint_range(0, 10) = 1;
// ray intersects sphere
// e = -b +/- sqrt( b^2 - c )
vec2 ray_vs_sphere( vec3 p, vec3 dir, float r ) {
float b = dot( p, dir );
float c = dot( p, p ) - r * r;
float d = b * b - c;
if ( d < 0.0 ) {
return vec2( MAX, -MAX );
}
d = sqrt( d );
return vec2( -b - d, -b + d );
}
// Mie
// g : ( -0.75, -0.999 )
// 3 * ( 1 - g^2 ) 1 + c^2
// F = ----------------- * -------------------------------
// 8pi * ( 2 + g^2 ) ( 1 + g^2 - 2 * g * c )^(3/2)
float phase_mie( float g, float c, float cc ) {
float gg = g * g;
float a = ( 1.0 - gg ) * ( 1.0 + cc );
float b = 1.0 + gg - 2.0 * (-g) * c;
b *= sqrt( b );
b *= 2.0 + gg;
return ( 3.0 / 8.0 * PI ) * a / b;
}
// Rayleigh
// g : 0
// F = 3/16PI * ( 1 + c^2 )
float phase_ray( float cc ) {
return ( 3.0 / 16.0 * PI ) * ( 1.0 + cc );
}
float density( vec3 p, float ph ) {
float scale_height = (atmosphere_radius - ground_radius);
return exp( -max( (length( p ) - ground_radius)/scale_height, 0.0 ) / ph );
}
float optic( vec3 p, vec3 q, float ph ) {
vec3 s = ( q - p ) / float( scatter_passes );
vec3 v = p + s * 0.5;
float sum = 0.0;
for ( int i = 0; i < scatter_passes; i++ ) {
sum += density( v, ph );
v += s;
}
sum *= length( s );
return sum;
}
vec3 in_scatter(vec3 o, vec3 dir, vec2 e, vec3 l) {
float ph_ray = rayleight_cf;
float ph_mie = mie_cf;
vec3 k_ray = scattering_cf.rgb * scattering_power; //(0.105707, 0.375536, 0.92076)*35.9486
vec3 k_mie = vec3( 1. * scattering_power );
float k_mie_ex = 1.1;
vec3 sum_ray = vec3( 0.0 );
vec3 sum_mie = vec3( 0.0 );
float n_ray0 = 0.0;
float n_mie0 = 0.0;
float len = ( e.y - e.x ) / float( scatter_passes*100 );
vec3 s = dir * len;
vec3 v = o + dir * ( e.x + len * 0.5 );
for ( int i = 0; i < scatter_passes*100; i++) {
float d_ray = density( v, ph_ray ) * len;
float d_mie = density( v, ph_mie ) * len;
n_ray0 += d_ray;
n_mie0 += d_mie;
v += s;
/*vec2 e = ray_vs_sphere( v, l, R_INNER );
e.x = max( e.x, 0.0 );
if ( e.x < e.y ) {
continue;
}*/
vec2 f = ray_vs_sphere( v, l, atmosphere_radius );
vec3 u = v + l * f.y;
float n_ray1 = optic( v, u, ph_ray );
float n_mie1 = optic( v, u, ph_mie );
vec3 att = exp( - ( n_ray0 + n_ray1 ) * k_ray - ( n_mie0 + n_mie1 ) * k_mie * k_mie_ex );
sum_ray += d_ray * att;
sum_mie += d_mie * att;
}
float c = dot( dir, -l );
float cc = c * c;
vec3 scatter =
sum_ray * k_ray * phase_ray( cc ) +
sum_mie * k_mie * phase_mie( -0.78, c, cc );
return scatter;
}
// ray direction
vec3 ray_dir( float fov, vec2 size, vec2 pos ) {
vec2 xy = pos - size * 0.5;
float cot_half_fov = tan( radians( 90.0 - fov * 0.5 ) );
float z = size.y * 0.5 * cot_half_fov;
return normalize( vec3( xy, -z ) );
}
void vertex() {
VERTEX += NORMAL * (atmosphere_radius - ground_radius)/1.;
}
void light()
{
// default ray dir
vec3 dir = VIEW;
// default ray origin
vec3 eye = INV_CAMERA_MATRIX[3].xyz + (CAMERA_MATRIX*vec4(position, 0.0)).xyz;
// sun light dir
vec3 l = -LIGHT;
vec2 e = ray_vs_sphere( eye, dir, atmosphere_radius );
if ( e.x > e.y ) {
DIFFUSE_LIGHT = vec3(0.0);
return;
}
vec2 f = ray_vs_sphere( eye, dir, ground_radius );
e.y = min( e.y, f.x );
vec3 I = in_scatter(eye, dir, e, l);
//DIFFUSE_LIGHT = vec3( pow( I, vec3( 1.0 / 2.2 ) ));
DIFFUSE_LIGHT = I*LIGHT_COLOR;
}"
[resource]
shader = SubResource( 1 )
shader_param/PI = 3.14159
shader_param/MAX = 100000.0
shader_param/position = Vector3( 0, 0, 0 )
shader_param/length_scale = 1000.0
shader_param/ground_radius = 6.371
shader_param/atmosphere_radius = 6.471
shader_param/scattering_cf = Color( 0.14902, 0.4, 0.909804, 1 )
shader_param/scattering_power = 36.0
shader_param/rayleight_cf = 0.07
shader_param/mie_cf = 0.04
shader_param/scatter_passes = 2