187 lines
4.6 KiB
Plaintext
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
|