Skip to content

Commit

Permalink
Add god rays, fix bugs with change_node plugin, change warehouse floo…
Browse files Browse the repository at this point in the history
…r to concrete
  • Loading branch information
Steveplays28 committed Jun 12, 2022
1 parent 1cec3bf commit 2e01534
Show file tree
Hide file tree
Showing 12 changed files with 433 additions and 11 deletions.
88 changes: 88 additions & 0 deletions addons/SIsilicon.vfx.godrays/GodRays.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
tool
extends Spatial

var light : Light
export(float, 0, 2) var exposure := 0.5 setget set_exposure
export(float, EASE) var attenuation := 2.0 setget set_attenuation
export(float, 0, 2) var light_size := 0.5 setget set_light_size

var clouds : Texture setget set_clouds

var canvas : MeshInstance
var material := preload("GodRays.tres").duplicate() as ShaderMaterial

func _notification(what : int) -> void:
if what == NOTIFICATION_PARENTED:
if get_parent() is Light:
light = get_parent()
elif what == NOTIFICATION_UNPARENTED:
light = null
set_clouds(null)

func _ready() -> void:
if get_child_count() > 0 and get_child(0).owner == null:
remove_child(get_child(0))

var mesh := QuadMesh.new()
mesh.size = Vector2(2, 2)
mesh.custom_aabb = AABB(Vector3(1,1,1) * -300000, Vector3(1,1,1) * 600000)

canvas = MeshInstance.new()
canvas.name = "GodRay"
canvas.mesh = mesh
canvas.material_override = material
add_child(canvas)

material.setup_local_to_scene()

set_exposure(exposure)
set_attenuation(attenuation)
set_light_size(light_size)

set_clouds(null)

func _process(delta : float) -> void:
if not light:
material.set_shader_param("light_type", 0)
material.set_shader_param("light_pos", Vector3())
return

var is_directional := light is DirectionalLight

material.set_shader_param("light_type", not is_directional)
material.set_shader_param("light_color", light.light_color * light.light_energy)

if is_directional:
var direction := light.global_transform.basis.z
material.set_shader_param("light_pos", direction)
material.set_shader_param("size", light_size)
else:
var position := light.global_transform.origin
material.set_shader_param("light_pos", position)
material.set_shader_param("size", light_size * (light as OmniLight).omni_range)

material.set_shader_param("num_samples", ProjectSettings.get_setting("rendering/quality/godrays/sample_number"))
material.set_shader_param("use_pcf5", ProjectSettings.get_setting("rendering/quality/godrays/use_pcf5"))
material.set_shader_param("dither", ProjectSettings.get_setting("rendering/quality/godrays/dither_amount"))

func set_exposure(value : float) -> void:
exposure = value
material.set_shader_param("exposure", exposure)
if canvas:
canvas.visible = exposure != 0

func set_attenuation(value : float) -> void:
attenuation = value
material.set_shader_param("attenuate", attenuation)
if canvas:
canvas.visible = attenuation != 0

func set_light_size(value : float) -> void:
light_size = value
if canvas:
canvas.visible = light_size != 0

func set_clouds(value : Texture) -> void:
clouds = value
material.set_shader_param("clouds", value)
material.set_shader_param("use_clouds", value != null)
77 changes: 77 additions & 0 deletions addons/SIsilicon.vfx.godrays/GodRays.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions addons/SIsilicon.vfx.godrays/GodRays.svg.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[remap]

importer="texture"
type="StreamTexture"
path="res://.import/GodRays.svg-0e880633ec1b3300b7885fc8b84904ed.stex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://addons/SIsilicon.vfx.godrays/GodRays.svg"
dest_files=[ "res://.import/GodRays.svg-0e880633ec1b3300b7885fc8b84904ed.stex" ]

[params]

compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0
175 changes: 175 additions & 0 deletions addons/SIsilicon.vfx.godrays/GodRays.tres
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
[gd_resource type="ShaderMaterial" load_steps=2 format=2]

[sub_resource type="Shader" id=1]
code = "shader_type spatial;
render_mode unshaded, cull_disabled, skip_vertex_transform, blend_add;

uniform vec4 light_color: hint_color;
uniform vec3 light_pos;
uniform float size = 1.0;
uniform int light_type = 0; //0 = directional, 1 = omni

uniform float exposure: hint_range(0,2);
uniform float attenuate = 1.0;

uniform sampler2D clouds : hint_albedo;
uniform bool use_clouds = false;

uniform int num_samples = 100;
uniform float dither = 1.0;
uniform bool use_pcf5 = true;

const float PI = 3.141592653;
const float HALF_PI = PI/2.0;

varying mat4 inv_project_mat;
varying vec4 light_screen_pos;
varying vec3 camera_pos;
varying float far_plane;
varying float attenuate_size;

void vertex() {
light_screen_pos = INV_CAMERA_MATRIX * vec4(light_pos, float(light_type));
attenuate_size = 1.0 / length(light_screen_pos) * size;

light_screen_pos = PROJECTION_MATRIX * light_screen_pos;
light_screen_pos.xyz /= light_screen_pos.w;
light_screen_pos.xy = light_screen_pos.xy * 0.5 + 0.5;
light_screen_pos.z = -(INV_CAMERA_MATRIX * vec4(light_pos, float(light_type))).z;

camera_pos = CAMERA_MATRIX[3].xyz;
inv_project_mat = INV_PROJECTION_MATRIX;
vec4 _far_plane = (INV_PROJECTION_MATRIX * vec4(0,0,1,1));
far_plane = -_far_plane.z / _far_plane.w;

POSITION = vec4(VERTEX.xy, -1.0, 1.0);
}

vec3 uv_to_ray(vec2 uv, mat4 inv_cam_matrix) {
vec4 view_space_ray = inv_project_mat * vec4(uv * 2.0 - 1.0, 0, 1);
view_space_ray.xyz /= view_space_ray.w;
view_space_ray.w = 0.0;

view_space_ray = normalize(view_space_ray);
return (view_space_ray * inv_cam_matrix).xyz;
}

float depth_texture(sampler2D tex, vec2 uv) {
float depth = clamp(uv, 0.0, 1.0) == uv ? texture(tex, uv).r : 1.0;
vec4 upos = inv_project_mat * vec4(uv*2.0-1.0, depth*2.0-1.0, 1.0);
return -upos.z/upos.w;
}

vec4 texture_panorama(sampler2D tex, vec3 ray) {
float u = atan(ray.x, ray.z) / (2.0 * PI) + 0.5;
float v = asin(ray.y) / PI + 0.5;
return texture(tex, vec2(u, 1.0 - v));
}

float sun_light(sampler2D depth, vec3 ray_o, vec3 ray_d, vec2 uv, vec2 tex_Size) {
float light_depth = mix(light_screen_pos.z, far_plane, float(1-light_type));

float is_obstacle = float(depth_texture(depth, uv) < light_depth);

if(use_pcf5) {
is_obstacle += float(depth_texture(depth, uv + tex_Size*vec2(-1,0)) < light_depth);
is_obstacle += float(depth_texture(depth, uv + tex_Size*vec2(1,0)) < light_depth);
is_obstacle += float(depth_texture(depth, uv + tex_Size*vec2(0,1)) < light_depth);
is_obstacle += float(depth_texture(depth, uv + tex_Size*vec2(0,-1)) < light_depth);
is_obstacle /= 5.0;
}

if(use_clouds) {
float temp = texture_panorama(clouds, ray_d).a;
if(temp < 0.7) temp = 0.0;
is_obstacle = min(is_obstacle + temp, 1.0);
}

float sun = 0.0;
if(light_type == 0) {
sun = smoothstep(1.0, 0.0, acos(dot(light_pos, ray_d)) / HALF_PI / size);
} else if(light_type == 1) {
sun = smoothstep(1.0, 0.0, acos(dot(normalize(light_pos - ray_o), ray_d)) / HALF_PI / attenuate_size);
}

sun *= 1.0 - is_obstacle;

return max(sun, 0.0);
}

float variable_smoothstep(float x, float N) {
if(N > 0.0) {
return pow(x, N);
} else if(N < 0.0) {
if(x <= 0.5) {
return pow(2.0*x, -N) / 2.0;
} else {
return 1.0 - pow(2.0*(1.0-x), -N) / 2.0;
}
}

return 0.0;
}

uint hash(uint x) {
x = ((x >> uint(16)) ^ x) * uint(73244475);
x = ((x >> uint(16)) ^ x) * uint(73244475);
x = (x >> uint(16)) ^ x;
return x;
}

float rand_from_seed(inout uint seed) {
int k;
int s = int(seed);
if (s == 0)
s = 305420679;
k = s / 127773;
s = 16807 * (s - k * 127773) - 2836 * k;
if (s < 0)
s += 2147483647;
seed = uint(s);
return float(seed % uint(65536)) / 65535.0;
}

void fragment() {
if(length(light_color) <= 0.001)
discard;

vec2 pixel_size = 1.0 / vec2(textureSize(SCREEN_TEXTURE, 0));//vec2(dFdx(SCREEN_UV.x), dFdy(SCREEN_UV.y)) * 1.5;
vec2 screen_uv = SCREEN_UV;
vec2 delta_uv = (light_screen_pos.xy - screen_uv) / (float(num_samples));

float light = 0.0;
uint seed = hash(uint(FRAGCOORD.x + FRAGCOORD.y * float(textureSize(SCREEN_TEXTURE, 0).x)));
screen_uv += delta_uv * dither * rand_from_seed(seed);
for(int i = 0; i < num_samples; i++) {
vec3 ray = uv_to_ray(screen_uv, INV_CAMERA_MATRIX);
float sample = sun_light(DEPTH_TEXTURE, camera_pos, ray, screen_uv, pixel_size);

light += sample;
screen_uv += delta_uv;
}

vec3 light_dir = light_type == 0 ? light_pos : normalize(light_pos - camera_pos);
float facing_weight = dot(uv_to_ray(vec2(0.5), INV_CAMERA_MATRIX), light_dir);

ALBEDO = variable_smoothstep(light / float(num_samples), attenuate) * exposure * light_color.rgb * max(facing_weight * facing_weight, 0.0);

//vec3 ray = uv_to_ray(SCREEN_UV, INV_CAMERA_MATRIX);
//ALBEDO = vec3(sun_light(DEPTH_TEXTURE, camera_pos, ray, SCREEN_UV, pixel_size));
//ALBEDO = texture(clouds, SCREEN_UV).rgb;
}"

[resource]
render_priority = 14
shader = SubResource( 1 )
shader_param/light_color = null
shader_param/light_pos = null
shader_param/size = 1.0
shader_param/light_type = 0
shader_param/exposure = null
shader_param/attenuate = 1.0
shader_param/use_clouds = false
shader_param/num_samples = 100
shader_param/dither = 1.0
shader_param/use_pcf5 = true
Loading

0 comments on commit 2e01534

Please sign in to comment.