From 0914a21badc6671573f7f44984e8a1c042c16aae Mon Sep 17 00:00:00 2001 From: Moroz Michael Date: Sun, 12 Jan 2020 04:07:26 +0200 Subject: [PATCH] Global illumination and bug fixes --- game_folder/shaders/compute/MAIN.cfg | 18 +- game_folder/shaders/compute/ORIGINAL.cfg | 2 +- .../shaders/compute/main/Final_step.glsl | 4 +- .../compute/main/Illumination_step.glsl | 33 +- .../compute/main/Illumination_step_GI.glsl | 62 +++ .../shaders/compute/main/Shading_step.glsl | 16 +- .../main/global_illumination_step.glsl | 26 +- game_folder/shaders/compute/mainGI.cfg | 115 +++++ .../compute/original/original_shading.glsl | 7 +- .../post_processing/bilateral_filter.glsl | 63 +++ .../shaders/compute/utility/bloom.glsl | 2 +- .../compute/utility/distance_estimators.glsl | 2 +- .../shaders/compute/utility/shading.glsl | 113 ++--- .../auto_exposure_weighting.glsl | 31 ++ shaders/compute/main.cfg | 93 ++++ shaders/compute/main/Final_step.glsl | 78 +++ shaders/compute/main/Illumination_step.glsl | 54 +++ shaders/compute/main/Shading_step.glsl | 48 ++ .../main/global_illumination_step.glsl | 52 ++ shaders/compute/mainGI.cfg | 104 ++++ shaders/compute/multires_marching/MRRM1.glsl | 44 ++ shaders/compute/multires_marching/MRRM2.glsl | 64 +++ shaders/compute/neon.cfg | 14 + shaders/compute/neon/neon_shading.glsl | 28 ++ shaders/compute/noise/noise.glsl | 24 + shaders/compute/noise_test.cfg | 14 + shaders/compute/original.cfg | 47 ++ .../compute/original/original_functions.glsl | 198 ++++++++ .../compute/original/original_shading.glsl | 49 ++ .../compute/post_processing/Bloom_horiz.glsl | 72 +++ .../compute/post_processing/Bloom_vertic.glsl | 74 +++ .../compute/post_processing/downsampling.glsl | 38 ++ shaders/compute/utility/RNG.glsl | 240 ++++++++++ shaders/compute/utility/bloom.glsl | 6 + shaders/compute/utility/camera.glsl | 58 +++ .../compute/utility/distance_estimators.glsl | 257 ++++++++++ shaders/compute/utility/ray_marching.glsl | 224 +++++++++ shaders/compute/utility/shading.glsl | 448 ++++++++++++++++++ shaders/textures/1.png | Bin 0 -> 153006 bytes shaders/textures/2.png | Bin 0 -> 5757 bytes shaders/textures/readme.txt | 2 + src/Camera.cpp | 2 +- src/Camera.h | 6 +- src/Gamemodes.cpp | 1 + src/Settings.h | 4 +- 45 files changed, 2715 insertions(+), 122 deletions(-) create mode 100644 game_folder/shaders/compute/main/Illumination_step_GI.glsl create mode 100644 game_folder/shaders/compute/mainGI.cfg create mode 100644 game_folder/shaders/compute/post_processing/bilateral_filter.glsl create mode 100644 shaders/compute/auto_exposure/auto_exposure_weighting.glsl create mode 100644 shaders/compute/main.cfg create mode 100644 shaders/compute/main/Final_step.glsl create mode 100644 shaders/compute/main/Illumination_step.glsl create mode 100644 shaders/compute/main/Shading_step.glsl create mode 100644 shaders/compute/main/global_illumination_step.glsl create mode 100644 shaders/compute/mainGI.cfg create mode 100644 shaders/compute/multires_marching/MRRM1.glsl create mode 100644 shaders/compute/multires_marching/MRRM2.glsl create mode 100644 shaders/compute/neon.cfg create mode 100644 shaders/compute/neon/neon_shading.glsl create mode 100644 shaders/compute/noise/noise.glsl create mode 100644 shaders/compute/noise_test.cfg create mode 100644 shaders/compute/original.cfg create mode 100644 shaders/compute/original/original_functions.glsl create mode 100644 shaders/compute/original/original_shading.glsl create mode 100644 shaders/compute/post_processing/Bloom_horiz.glsl create mode 100644 shaders/compute/post_processing/Bloom_vertic.glsl create mode 100644 shaders/compute/post_processing/downsampling.glsl create mode 100644 shaders/compute/utility/RNG.glsl create mode 100644 shaders/compute/utility/bloom.glsl create mode 100644 shaders/compute/utility/camera.glsl create mode 100644 shaders/compute/utility/distance_estimators.glsl create mode 100644 shaders/compute/utility/ray_marching.glsl create mode 100644 shaders/compute/utility/shading.glsl create mode 100644 shaders/textures/1.png create mode 100644 shaders/textures/2.png create mode 100644 shaders/textures/readme.txt diff --git a/game_folder/shaders/compute/MAIN.cfg b/game_folder/shaders/compute/MAIN.cfg index 1055c61d..593f8add 100644 --- a/game_folder/shaders/compute/MAIN.cfg +++ b/game_folder/shaders/compute/MAIN.cfg @@ -5,7 +5,7 @@ #################################################### #shader name multires_marching/MRRM1.glsl -#global size +#global work-group number width/(8*MRRM_scale) height/(8*MRRM_scale) #texture resolution @@ -16,7 +16,7 @@ height/MRRM_scale #################################################### #shader name multires_marching/MRRM2.glsl -#global size +#global work-group number width/8 height/8 #texture resolution @@ -27,18 +27,18 @@ height #################################################### #shader name #half res shadows and AO main/Illumination_step.glsl -#global size +#global work-group number width/(shadow_scale*8) height/(shadow_scale*8) #texture resolution width/shadow_scale height/shadow_scale #output texture number -1 +2 #################################################### #shader name main/Shading_step.glsl -#global size +#global work-group number width/8 height/8 #texture resolution @@ -49,7 +49,7 @@ height #################################################### #shader name post_processing/downsampling.glsl -#global size +#global work-group number width/(8*bloom_scale) height/(8*bloom_scale) #texture resolution @@ -60,7 +60,7 @@ height/bloom_scale #################################################### #shader name post_processing/Bloom_horiz.glsl -#global size +#global work-group number width/(bloom_scale*128) height/bloom_scale #texture resolution @@ -71,7 +71,7 @@ height/bloom_scale #################################################### #shader name post_processing/Bloom_vertic.glsl -#global size +#global work-group number width/bloom_scale height/(bloom_scale*128) #texture resolution @@ -82,7 +82,7 @@ height/bloom_scale #################################################### #shader name main/Final_step.glsl -#global size +#global work-group number width/8 height/8 #texture resolution diff --git a/game_folder/shaders/compute/ORIGINAL.cfg b/game_folder/shaders/compute/ORIGINAL.cfg index 4f8179de..c4f38bde 100644 --- a/game_folder/shaders/compute/ORIGINAL.cfg +++ b/game_folder/shaders/compute/ORIGINAL.cfg @@ -32,7 +32,7 @@ height/(shadow_scale*8) width/shadow_scale height/shadow_scale #output texture number -1 +2 #################################################### #shader name original/original_shading.glsl diff --git a/game_folder/shaders/compute/main/Final_step.glsl b/game_folder/shaders/compute/main/Final_step.glsl index 39ce8b89..fe927b80 100644 --- a/game_folder/shaders/compute/main/Final_step.glsl +++ b/game_folder/shaders/compute/main/Final_step.glsl @@ -15,10 +15,10 @@ shared vec4 de_sph[1][1]; #include #include -#define DOF_samples 60 +#define DOF_samples 50 #define DOF -#define RA 5. +#define RA 3.5 const float GA = 2.399; const mat2 rot = mat2(cos(GA),sin(GA),-sin(GA),cos(GA)); diff --git a/game_folder/shaders/compute/main/Illumination_step.glsl b/game_folder/shaders/compute/main/Illumination_step.glsl index 8493814e..ce28f044 100644 --- a/game_folder/shaders/compute/main/Illumination_step.glsl +++ b/game_folder/shaders/compute/main/Illumination_step.glsl @@ -3,9 +3,10 @@ #define block_size 64 layout(local_size_x = group_size, local_size_y = group_size) in; -layout(rgba32f, binding = 0) uniform image2D illumination; -layout(rgba32f, binding = 1) uniform image2D DE_input; -layout(rgba32f, binding = 2) uniform image2D color_HDR; //calculate final color +layout(rgba32f, binding = 0) uniform image2D illuminationDirect; +layout(rgba32f, binding = 1) uniform image2D illuminationGI; +layout(rgba32f, binding = 2) uniform image2D DE_input; +layout(rgba32f, binding = 3) uniform image2D color_HDR; //calculate final color //make all the local distance estimator spheres shared shared vec4 de_sph[group_size][group_size]; @@ -13,15 +14,14 @@ shared vec4 de_sph[group_size][group_size]; #include #include -///Half-resolution illumination step - +///Low-resolution illumination step void main() { ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); - vec2 img_size = vec2(imageSize(illumination)); + vec2 img_size = vec2(imageSize(illuminationDirect)); vec2 pimg_size = vec2(imageSize(DE_input)); vec2 step_scale = img_size/pimg_size; @@ -38,17 +38,22 @@ void main() { pos = sph; dir.w += td; - vec4 illum = vec4(0); + vec4 illumDIR = vec4(0); + vec4 illumGI = vec4(1.); if(pos.w < max(2*fovray*td, MIN_DIST) && SHADOWS_ENABLED) { - pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; - pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; - pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; - illum.x = shadow_march(pos, normalize(vec4(LIGHT_DIRECTION,0)), MAX_DIST, LIGHT_ANGLE); + //marching towards a point at a distance = to the pixel cone radius from the object + float pix_cone_rad = 2.*fovray*td/step_scale.x; + pos.xyz += (DE(pos.xyz) - pix_cone_rad)*dir.xyz; + pos.xyz += (DE(pos.xyz) - pix_cone_rad)*dir.xyz; + pos.xyz += (DE(pos.xyz) - pix_cone_rad)*dir.xyz; - //illum.y = ambient_occlusion(pos, norm); + illumDIR.xyz = sky_color(LIGHT_DIRECTION)*shadow_march(pos, normalize(vec4(LIGHT_DIRECTION,0)), MAX_DIST, LIGHT_ANGLE); } - illum.w = td; - imageStore(illumination, global_pos, illum); + illumDIR.w = td; + illumGI.w = td; + + imageStore(illuminationDirect, global_pos, illumDIR); + imageStore(illuminationGI, global_pos, illumGI); } \ No newline at end of file diff --git a/game_folder/shaders/compute/main/Illumination_step_GI.glsl b/game_folder/shaders/compute/main/Illumination_step_GI.glsl new file mode 100644 index 00000000..f0720211 --- /dev/null +++ b/game_folder/shaders/compute/main/Illumination_step_GI.glsl @@ -0,0 +1,62 @@ +#version 430 +#define group_size 8 +#define block_size 64 + +layout(local_size_x = group_size, local_size_y = group_size) in; +layout(rgba32f, binding = 0) uniform image2D global_illum; +layout(rgba32f, binding = 1) uniform image2D illuminationDirect; +layout(rgba32f, binding = 2) uniform image2D illuminationGI; +layout(rgba32f, binding = 3) uniform image2D DE_input; +layout(rgba32f, binding = 4) uniform image2D color_HDR; //calculate final color + +//make all the local distance estimator spheres shared +shared vec4 de_sph[group_size][group_size]; + +#include +#include + +///Low-resolution illumination step + +void main() { + + ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); + ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); + + vec2 img_size = vec2(imageSize(illuminationDirect)); + vec2 pimg_size = vec2(imageSize(DE_input)); + float GIscale = (vec2(imageSize(global_illum)) / img_size).x; + vec2 step_scale = img_size/pimg_size; + + ivec2 prev_pos = min(ivec2((vec2(global_pos)/step_scale) + 0.5),ivec2(pimg_size)-1); + + ray rr = get_ray(vec2(global_pos)/img_size); + vec4 pos = vec4(rr.pos,0); + vec4 dir = vec4(rr.dir,0); + vec4 var = vec4(0); + + vec4 sph = imageLoad(DE_input, prev_pos); + float td = dot(dir.xyz, sph.xyz - pos.xyz);//traveled distance + + pos = sph; + dir.w += td; + + vec4 illumDIR = vec4(0); + vec4 illumGI = vec4(0); + + if(pos.w < max(2*fovray*td, MIN_DIST) && SHADOWS_ENABLED) + { + //marching towards a point at a distance = to the pixel cone radius from the object + float pix_cone_rad = 2.*fovray*td/step_scale.x; + pos.xyz += (DE(pos.xyz) - pix_cone_rad)*dir.xyz; + pos.xyz += (DE(pos.xyz) - pix_cone_rad)*dir.xyz; + pos.xyz += (DE(pos.xyz) - pix_cone_rad)*dir.xyz; + + illumGI = bilinear_surface(global_illum, td, GIscale, vec2(global_pos)*GIscale); + illumDIR.xyz = sky_color(LIGHT_DIRECTION)*shadow_march(pos, normalize(vec4(LIGHT_DIRECTION,0)), MAX_DIST, LIGHT_ANGLE); + } + illumDIR.w = td; + illumGI.w = td; + + imageStore(illuminationDirect, global_pos, illumDIR); + imageStore(illuminationGI, global_pos, illumGI); +} \ No newline at end of file diff --git a/game_folder/shaders/compute/main/Shading_step.glsl b/game_folder/shaders/compute/main/Shading_step.glsl index ea915300..538c4816 100644 --- a/game_folder/shaders/compute/main/Shading_step.glsl +++ b/game_folder/shaders/compute/main/Shading_step.glsl @@ -4,10 +4,11 @@ #define block_size 64 layout(local_size_x = group_size, local_size_y = group_size) in; -layout(rgba32f, binding = 0) uniform image2D illumination; //shadows -layout(rgba32f, binding = 1) uniform image2D color_output; -layout(rgba32f, binding = 2) uniform image2D DE_input; -layout(rgba32f, binding = 3) uniform image2D color_HDR; //calculate final color +layout(rgba32f, binding = 0) uniform image2D illuminationDirect; +layout(rgba32f, binding = 1) uniform image2D illuminationGI; +layout(rgba32f, binding = 2) uniform image2D color_output; +layout(rgba32f, binding = 3) uniform image2D DE_input; +layout(rgba32f, binding = 4) uniform image2D color_HDR; //calculate final color //make all the local distance estimator spheres shared @@ -20,7 +21,7 @@ void main() { ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); vec2 img_size = vec2(imageSize(color_HDR)); - float res_ratio = imageSize(illumination).x/img_size.x; + float res_ratio = imageSize(illuminationDirect).x/img_size.x; vec4 sph = imageLoad(DE_input, global_pos); @@ -31,12 +32,13 @@ void main() { float td = dot(dir.xyz, sph.xyz - pos.xyz);//traveled distance - vec4 illum = bilinear_surface(illumination, td, 3*td*fovray/res_ratio, vec2(global_pos)*res_ratio); + vec4 illumDIR = bilinear_surface(illuminationDirect, td, 3*td*fovray/res_ratio, vec2(global_pos)*res_ratio); + vec4 illumGI = bilinear_surface(illuminationGI, td, 3*td*fovray/res_ratio, vec2(global_pos)*res_ratio); //vec4 illum = interp(illumination, vec2(global_pos)*res_ratio); pos = sph; dir.w += td; - vec3 color = shading(pos, dir, fovray, illum.x); + vec3 color = shading(pos, dir, fovray, illumDIR.xyz, illumGI.xyz); //color = vec3(illum.x); vec3 prev_color = imageLoad(color_HDR, global_pos).xyz; if(!isnan(color.x) && !isnan(color.y) && !isnan(color.z)) diff --git a/game_folder/shaders/compute/main/global_illumination_step.glsl b/game_folder/shaders/compute/main/global_illumination_step.glsl index f7b59346..0cc0d4b7 100644 --- a/game_folder/shaders/compute/main/global_illumination_step.glsl +++ b/game_folder/shaders/compute/main/global_illumination_step.glsl @@ -3,9 +3,10 @@ #define block_size 64 layout(local_size_x = group_size, local_size_y = group_size) in; -layout(rgba32f, binding = 0) uniform image2D DE_input; -layout(rgba32f, binding = 1) uniform image2D color_HDR; //calculate final color -layout(rgba32f, binding = 2) uniform image2D illumination; +layout(rgba32f, binding = 0) uniform image2D global_illum; +layout(rgba32f, binding = 1) uniform image2D normals; +layout(rgba32f, binding = 2) uniform image2D DE_input; +layout(rgba32f, binding = 3) uniform image2D color_HDR; //calculate final color //make all the local distance estimator spheres shared shared vec4 de_sph[group_size][group_size]; @@ -20,7 +21,7 @@ void main() { ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); - vec2 img_size = vec2(imageSize(illumination)); + vec2 img_size = vec2(imageSize(global_illum)); vec2 pimg_size = vec2(imageSize(DE_input)); vec2 step_scale = img_size/pimg_size; @@ -38,15 +39,18 @@ void main() { dir.w += td; vec4 illum = vec4(0); - + vec4 norm = vec4(1,0,0,0); if(pos.w < max(2*fovray*td, MIN_DIST) && SHADOWS_ENABLED) { - pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; - pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; - pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; - - illum.xyz = ambient_light(pos); + //marching towards a point at a distance = to the pixel cone radius from the object + float pix_cone_rad = 10.*fovray*td/step_scale.x; + pos.xyz += (DE(pos.xyz) - pix_cone_rad)*dir.xyz; + pos.xyz += (DE(pos.xyz) - pix_cone_rad)*dir.xyz; + pos.xyz += (DE(pos.xyz) - pix_cone_rad)*dir.xyz; + norm = calcNormal(pos.xyz, 0.1*pix_cone_rad); + illum.xyz = ambient_light(pos.xyz, pix_cone_rad); } illum.w = td; - imageStore(illumination, global_pos, illum); + imageStore(global_illum, global_pos, illum); + imageStore(normals, global_pos, norm); } \ No newline at end of file diff --git a/game_folder/shaders/compute/mainGI.cfg b/game_folder/shaders/compute/mainGI.cfg new file mode 100644 index 00000000..c140a5f7 --- /dev/null +++ b/game_folder/shaders/compute/mainGI.cfg @@ -0,0 +1,115 @@ +#############MAIN SHADER PIPELINE################### +#number of main textures(1 depth map, 2 HDR color) +#this should be first, at least 2 textures +2 +#################################################### +#shader name +multires_marching/MRRM1.glsl +#global work-group number +width/(8*MRRM_scale) +height/(8*MRRM_scale) +#texture resolution +width/MRRM_scale +height/MRRM_scale +#output texture number +3 +#################################################### +#shader name +multires_marching/MRRM2.glsl +#global work-group number +width/8 +height/8 +#texture resolution +width +height +#output texture number +0 +#################################################### +#shader name #6x downscaled GI +main/global_illumination_step.glsl +#global work-group number +width/(8*6) +height/(8*6) +#texture resolution +width/6 +height/6 +#output texture number +2 +#################################################### +#shader name +post_processing/bilateral_filter.glsl +#global work-group number +width/(8*6) +height/(8*6) +#texture resolution +width/6 +height/6 +#output texture number +1 +#################################################### +#shader name #half res shadows and AO +main/Illumination_step_GI.glsl +#global work-group number +width/(shadow_scale*8) +height/(shadow_scale*8) +#texture resolution +width/shadow_scale +height/shadow_scale +#output texture number +2 +#################################################### +#shader name +main/Shading_step.glsl +#global work-group number +width/8 +height/8 +#texture resolution +width +height +#output texture number +1 +#################################################### +#shader name +post_processing/downsampling.glsl +#global work-group number +width/(8*bloom_scale) +height/(8*bloom_scale) +#texture resolution +width/bloom_scale +height/bloom_scale +#output texture number +1 +#################################################### +#shader name +post_processing/Bloom_horiz.glsl +#global work-group number +width/(bloom_scale*128) +height/bloom_scale +#texture resolution +width/bloom_scale +height/bloom_scale +#output texture number +2 +#################################################### +#shader name +post_processing/Bloom_vertic.glsl +#global work-group number +width/bloom_scale +height/(bloom_scale*128) +#texture resolution +width/bloom_scale +height/bloom_scale +#output texture number +1 +#################################################### +#shader name +main/Final_step.glsl +#global work-group number +width/8 +height/8 +#texture resolution +width +height +#output texture number +1 +#################################################### \ No newline at end of file diff --git a/game_folder/shaders/compute/original/original_shading.glsl b/game_folder/shaders/compute/original/original_shading.glsl index 9925fcc9..abd02d31 100644 --- a/game_folder/shaders/compute/original/original_shading.glsl +++ b/game_folder/shaders/compute/original/original_shading.glsl @@ -5,9 +5,10 @@ layout(local_size_x = group_size, local_size_y = group_size) in; layout(rgba32f, binding = 0) uniform image2D illumination; //shadows -layout(rgba32f, binding = 1) uniform image2D color_output; -layout(rgba32f, binding = 2) uniform image2D DE_input; -layout(rgba32f, binding = 3) uniform image2D color_HDR; //calculate final color +layout(rgba32f, binding = 1) uniform image2D illuminationGI; //global illum +layout(rgba32f, binding = 2) uniform image2D color_output; +layout(rgba32f, binding = 3) uniform image2D DE_input; +layout(rgba32f, binding = 4) uniform image2D color_HDR; //calculate final color //make all the local distance estimator spheres shared diff --git a/game_folder/shaders/compute/post_processing/bilateral_filter.glsl b/game_folder/shaders/compute/post_processing/bilateral_filter.glsl new file mode 100644 index 00000000..bc327502 --- /dev/null +++ b/game_folder/shaders/compute/post_processing/bilateral_filter.glsl @@ -0,0 +1,63 @@ +#version 430 +//4*4 ray bundle +#define group_size 8 +#define buffer_size 64 + +layout(local_size_x = group_size, local_size_y = group_size) in; +layout(rgba32f, binding = 0) uniform image2D before; +layout(rgba32f, binding = 1) uniform image2D before_normal; +layout(rgba32f, binding = 2) uniform image2D after; +layout(rgba32f, binding = 3) uniform image2D DE_input; + +//bilateral blur... +//4 pixel radius +#define blur_R 5 + +vec3 getpos(vec2 p, vec2 rr) +{ + return imageLoad(DE_input, ivec2(p*rr)).xyz; +} + +vec3 getnorm(vec2 p) +{ + return imageLoad(before_normal, ivec2(p)).xyz; +} + +#include + +void main() { + ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); + ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); + + vec2 img_size = vec2(imageSize(before)); + + vec2 res_ratio = vec2(imageSize(DE_input))/img_size; + + vec4 sum = vec4(0); + float norm = 0.; + + ray rr = get_ray(vec2(global_pos)/img_size); + vec4 pos = vec4(rr.pos,0); + vec4 dir = vec4(rr.dir,0); + vec4 var = vec4(0); + + vec3 cpos = getpos(global_pos, res_ratio); + vec3 cnorm = getnorm(global_pos); + float td = dot(dir.xyz, cpos - pos.xyz);//traveled distance + float DX = fovray*td; + + for(int i = -blur_R; i <= blur_R; i++) + { + for(int j = -blur_R; j <= blur_R; j++) + { + vec3 dpos = (getpos(global_pos + vec2(i,j),res_ratio) - cpos)/td; + vec3 dnorm = getnorm(global_pos + vec2(i,j)) - cnorm; + float weight = exp(- 600.*dot(dpos,dpos) - 8.*dot(dnorm,dnorm)); + sum += weight*imageLoad(before, ivec2(global_pos) + ivec2(i,j)); + norm += weight; + } + } + sum /= norm; + + imageStore(after, global_pos, sum); +} \ No newline at end of file diff --git a/game_folder/shaders/compute/utility/bloom.glsl b/game_folder/shaders/compute/utility/bloom.glsl index 379bf814..e48b66ff 100644 --- a/game_folder/shaders/compute/utility/bloom.glsl +++ b/game_folder/shaders/compute/utility/bloom.glsl @@ -1,6 +1,6 @@ vec3 bloom_treshold(vec3 color, float exposure) { - color = clamp(color*exposure, 0, 100)/exposure; + color = clamp(color*exposure, 0, 5)/exposure; vec3 mapped = Camera.bloomintensity*exposure*pow(color,vec3(2.)); return mapped; } \ No newline at end of file diff --git a/game_folder/shaders/compute/utility/distance_estimators.glsl b/game_folder/shaders/compute/utility/distance_estimators.glsl index 857af706..d28472ec 100644 --- a/game_folder/shaders/compute/utility/distance_estimators.glsl +++ b/game_folder/shaders/compute/utility/distance_estimators.glsl @@ -17,7 +17,7 @@ uniform float time; uniform float PBR_METALLIC; uniform float PBR_ROUGHNESS; -layout(rgba8, binding = 4) uniform image2D color_flag; +layout(rgba8, binding = 5) uniform image2D color_flag; ///Original MM distance estimators diff --git a/game_folder/shaders/compute/utility/shading.glsl b/game_folder/shaders/compute/utility/shading.glsl index 3f211f15..8f91a807 100644 --- a/game_folder/shaders/compute/utility/shading.glsl +++ b/game_folder/shaders/compute/utility/shading.glsl @@ -96,6 +96,8 @@ float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) } ///END PBR functions + +#include const float Br = 0.0025; const float Bm = 0.0003; const float g = 0.9800; @@ -105,19 +107,20 @@ const vec3 Km = Bm / pow(nitrogen, vec3(0.84)); vec3 sky_color(in vec3 pos) { + pos = normalize(pos); // Atmosphere Scattering vec3 fsun = LIGHT_DIRECTION; - float brightnees = exp(-sqrt(pow(min(5*(pos.y-0.1),0),2)+0.1)); + float brightnees = exp(-sqrt(pow(abs(min(5*(pos.y-0.01),0)),2)+0.)); if(pos.y < 0) { - pos.y = 0; - pos.xyz = normalize(pos.xyz); + pos.y = 0.; + pos = normalize(pos); } float mu = dot(normalize(pos), normalize(fsun)); vec3 extinction = mix(exp(-exp(-((pos.y + fsun.y * 4.0) * (exp(-pos.y * 16.0) + 0.1) / 80.0) / Br) * (exp(-pos.y * 16.0) + 0.1) * Kr / Br) * exp(-pos.y * exp(-pos.y * 8.0 ) * 4.0) * exp(-pos.y * 2.0) * 4.0, vec3(1.0 - exp(fsun.y)) * 0.2, -fsun.y * 0.2 + 0.5); vec3 sky_col = brightnees* 3.0 / (8.0 * 3.14) * (1.0 + mu * mu) * (Kr + Km * (1.0 - g * g) / (2.0 + g * g) / pow(1.0 + g * g - 2.0 * g * mu, 1.5)) / (Br + Bm) * extinction; - sky_col = 0.4*clamp(sky_col,0,10); + sky_col = 0.4*clamp(sky_col,0.001,15.); return pow(sky_col,vec3(1.f/gamma_sky)); } @@ -125,7 +128,7 @@ vec3 ambient_sky_color(in vec3 pos) { float y = pos.y; pos.xyz = normalize(vec3(1,0,0)); - return sky_color(pos)*exp(-abs(y)); + return 0.5*sky_color(pos)*exp(-abs(y)); } vec4 ambient_occlusion(in vec4 pos, in vec4 norm, in vec4 dir) @@ -136,7 +139,7 @@ vec4 ambient_occlusion(in vec4 pos, in vec4 norm, in vec4 dir) vec3 direction = normalize(norm.xyz); vec3 ambient_color = ambient_sky_color(norm.xyz); //step out - pos.xyz += 0.03*dir.w*direction; + pos.xyz += 0.04*dir.w*direction; //march in the direction of the normal for(int i = 0; i < AMBIENT_MARCHES; i++) { @@ -152,28 +155,31 @@ vec4 ambient_occlusion(in vec4 pos, in vec4 norm, in vec4 dir) } //Global illumination approximation, loicvdb's shader https://www.shadertoy.com/view/3t3GWH used as reference -#define GIStrength .3 +#define GIStrength .45 #define AOStrength .3 +#define precision 1.01 #define AmbientLightSteps 14 -vec3 ambient_light(vec3 pos) + + +vec3 ambient_light(vec3 pos, float d) { vec3 pos0 = pos; float dist0 = DE(pos); - vec3 normal = calcNormal(pos, MIN_DIST).xyz, gi, al = vec3(0.0); + vec3 normal = calcNormal(pos, d).xyz, gi = vec3(0.), al = vec3(0.0); float ao = 1., dist = dist0; - vec3 lcolor = ambient_sky_color(LIGHT_DIRECTION); + vec3 lcolor = sky_color(LIGHT_DIRECTION); for(int i = 0; i < AmbientLightSteps; i++){ float expectedDist = dist * (1. + .8); - dist = DE(pos); + dist = max(DE(pos),MIN_DIST); float weight = AOStrength*(1.-float(i)/float(AmbientLightSteps)); //more weight to first samples - ao *= pow(clamp(dist/expectedDist, 0., 1.0), weight); - normal = normalize(calcNormalA(pos, dist)+1.5*normal); //"smoothed" normal to avoid artifacts - pos += normal * .8*dist; //slightly shorter to avoid artifacts + ao *= pow(clamp(dist/max(max(expectedDist, d),MIN_DIST), 0., 1.0), weight); + normal = normalize(calcNormalA(pos, dist) + (hash33(pos)-0.5)); + pos += normal/precision*dist; //slightly shorter to avoid artifacts al += ambient_sky_color(normal); - if(i == 6 || i == 13) gi += ao*lcolor*shadow_march(vec4(pos, MIN_DIST), vec4(LIGHT_DIRECTION,0), 10., LIGHT_ANGLE); // two GI samples + if(i == 6 || i == 13) gi += ao*lcolor*shadow_march(vec4(pos, MIN_DIST), vec4(normalize(LIGHT_DIRECTION),0), 10., 0.3); // two GI samples } gi *= GIStrength/2.0; - return gi + al/float(AmbientLightSteps) * ao; + return gi + al * ao / float(AmbientLightSteps); } @@ -182,13 +188,16 @@ vec3 refraction(vec3 rd, vec3 n, float p) { return p * (rd - dot_nd * n) + sqrt(1.0 - (p * p) * (1.0 - dot_nd * dot_nd)) * n; } -vec3 lighting(vec4 color, vec2 pbr, vec4 pos, vec4 dir, vec4 norm, vec3 refl, vec3 refr, float shadow) +vec3 lighting(vec4 color, vec2 pbr, vec4 pos, vec4 dir, vec4 norm, vec3 refl, vec3 refr, vec3 direct, vec3 GI) { vec3 albedo = color.xyz; albedo = pow(albedo,vec3(1.f/gamma_material)); //square it to make the fractals more colorfull vec4 ambient_color = ambient_occlusion(pos, norm, dir); - + if(GI == vec3(0.)) + GI = ambient_color.xyz; + else + GI *= 0.5*ambient_color.xyz + 0.5*length(ambient_color.xyz)*sqrt(0.3333); float metallic = pbr.x; vec3 F0 = vec3(0.04); F0 = mix(F0, albedo, metallic); @@ -198,42 +207,16 @@ vec3 lighting(vec4 color, vec2 pbr, vec4 pos, vec4 dir, vec4 norm, vec3 refl, ve vec3 V = -dir.xyz; vec3 N = norm.xyz; - { //ambient occlusion contribution - float roughness = max(pbr.y,0.5); - vec3 L = normalize(N); - vec3 H = normalize(V + L); - vec3 radiance = ambient_color.xyz; - - // cook-torrance brdf - float NDF = DistributionGGX(N, H, roughness); - float G = GeometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - vec3 numerator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0); - vec3 specular = numerator / max(denominator, 0.001); - - // add to outgoing radiance Lo - float NdotL = max(dot(N, L), 0.0); - Lo += (kD * albedo / PI + specular) * radiance * NdotL; - } - if(!SHADOWS_ENABLED) { - shadow = ambient_color.w; + direct = ambient_color.xyz; } - - vec3 sun_color = sky_color(LIGHT_DIRECTION); { //light contribution float roughness = pbr.y; vec3 L = normalize(LIGHT_DIRECTION); vec3 H = normalize(V + L); - vec3 radiance = sun_color*shadow*(0.8+0.2*ambient_color.w); + vec3 radiance = direct*(0.9+0.1*ambient_color.w); // cook-torrance brdf float NDF = DistributionGGX(N, H, roughness); @@ -252,12 +235,12 @@ vec3 lighting(vec4 color, vec2 pbr, vec4 pos, vec4 dir, vec4 norm, vec3 refl, ve float NdotL = max(dot(N, L), 0.0); Lo += (kD * albedo / PI + specular) * radiance * NdotL; } - /* - { //light reflection, GI imitation - float roughness = max(PBR_ROUGHNESS,0.5); - vec3 L = normalize(-LIGHT_DIRECTION); + + { //light reflection, global illumination + float roughness = 0.95; + vec3 L = normalize(N); vec3 H = normalize(V + L); - vec3 radiance = 0.35*sun_color*ambient_color.w*(1-ambient_color.w); + vec3 radiance = GI; // cook-torrance brdf float NDF = DistributionGGX(N, H, roughness); @@ -275,7 +258,7 @@ vec3 lighting(vec4 color, vec2 pbr, vec4 pos, vec4 dir, vec4 norm, vec3 refl, ve // add to outgoing radiance Lo float NdotL = max(dot(N, L), 0.0); Lo += (kD * albedo / PI + specular) * radiance * NdotL; - }*/ + } if(color.w>0.5) // if marble { @@ -311,10 +294,8 @@ vec3 lighting(vec4 color, vec2 pbr, vec4 pos, vec4 dir, vec4 norm, vec3 refl, ve return Lo; } -vec3 shading_simple(in vec4 pos, in vec4 dir, float fov, float shadow) +vec3 shading_simple(in vec4 pos, in vec4 dir, float fov, vec3 direct, float k) { - - if(pos.w < max(16*fovray*dir.w, MIN_DIST)) { //calculate the normal @@ -329,12 +310,10 @@ vec3 shading_simple(in vec4 pos, in vec4 dir, float fov, float shadow) { //optimize color sampling vec3 cpos = pos.xyz - pos.w*norm.xyz; - //cpos = cpos - DE(cpos)*norm.xyz; - //cpos = cpos - DE(cpos)*norm.xyz; vec4 color; vec2 pbr; scene_material(cpos, color, pbr); - return lighting(color, pbr, pos, dir, norm, vec3(0), vec3(0), shadow); + return lighting(color, pbr, pos, dir, norm, vec3(0), vec3(0), direct, vec3(k)); } } else @@ -344,15 +323,15 @@ vec3 shading_simple(in vec4 pos, in vec4 dir, float fov, float shadow) } -vec3 render_ray(in vec4 pos, in vec4 dir, float fov) +vec3 render_ray(in vec4 pos, in vec4 dir, float fov, float k) { vec4 var = vec4(0,0,0,1); ray_march(pos, dir, var, fov); - float shadow = shadow_march(pos, vec4(LIGHT_DIRECTION,0), 10., LIGHT_ANGLE); - return shading_simple(pos, dir, fov, shadow); + vec3 direct = sky_color(LIGHT_DIRECTION)*shadow_march(pos, vec4(LIGHT_DIRECTION,0), 10., LIGHT_ANGLE); + return shading_simple(pos, dir, fov, direct, k); } -vec3 shading(in vec4 pos, in vec4 dir, float fov, float shadow) +vec3 shading(in vec4 pos, in vec4 dir, float fov, vec3 direct, vec3 GI) { if(pos.w < max(2*fovray*dir.w, MIN_DIST)) { @@ -368,15 +347,13 @@ vec3 shading(in vec4 pos, in vec4 dir, float fov, float shadow) { //optimize color sampling vec3 cpos = pos.xyz - norm.w*norm.xyz; - // cpos = cpos - DE(cpos)*norm.xyz; - // cpos = cpos - DE(cpos)*norm.xyz; - // cpos = cpos - DE(cpos)*norm.xyz; vec4 color; vec2 pbr; scene_material(cpos, color, pbr); vec3 refl = vec3(0); vec3 refr = vec3(0); if(color.w>0.5) // if marble { + //Calculate refraction vec3 n = normalize(iMarblePos - cpos.xyz); vec3 q = refraction(dir.xyz, n, 1.0 / 1.5); vec3 p2 = pos.xyz + (dot(q, n) * 2. * iMarbleRad) * q; @@ -385,7 +362,7 @@ vec3 shading(in vec4 pos, in vec4 dir, float fov, float shadow) vec4 p_temp = vec4(p2+ n*fov*dir.w*2.5, 0); vec4 r_temp = vec4(q, dir.w); - refr = render_ray(p_temp, r_temp, fov*1.5); + refr = render_ray(p_temp, r_temp, fov*1.5, length(GI)); //Calculate reflection n = -normalize(iMarblePos - cpos.xyz); @@ -393,10 +370,10 @@ vec3 shading(in vec4 pos, in vec4 dir, float fov, float shadow) p_temp = vec4(pos.xyz + n*fov*dir.w*2., 0); r_temp = vec4(q, dir.w); - refl = render_ray(p_temp, r_temp, fov*1.5); + refl = render_ray(p_temp, r_temp, fov*1.5, length(GI)); } - return lighting(color, pbr, vec4(cpos, pos.w), dir, norm, refl, refr, shadow); + return lighting(color, pbr, vec4(cpos, pos.w), dir, norm, refl, refr, direct, GI); } } else diff --git a/shaders/compute/auto_exposure/auto_exposure_weighting.glsl b/shaders/compute/auto_exposure/auto_exposure_weighting.glsl new file mode 100644 index 00000000..1454a0f6 --- /dev/null +++ b/shaders/compute/auto_exposure/auto_exposure_weighting.glsl @@ -0,0 +1,31 @@ +#version 430 + +/// DO NOT CHANGE +#define group_size 16 + +layout(local_size_x = group_size, local_size_y = group_size) in; + +layout(rgba8, binding = 0) uniform image2D final_color; +layout(rgba32f, binding = 1) uniform image2D DE_input; +layout(rgba32f, binding = 2) uniform image2D output_w; + +#include + +void main() { + ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); + ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); + vec2 img_size = vec2(imageSize(final_color)); + + vec4 sph = imageLoad(DE_input, global_pos); + + ray rr = get_ray(vec2(global_pos)/img_size); + vec4 pos = vec4(rr.pos,0); + vec4 dir = vec4(rr.dir,0); + + float td = dot(dir.xyz, sph.xyz - pos.xyz);//depth + + vec4 color = imageLoad(final_color, global_pos); + float weight = pow(max(1.0 - length(vec2(global_pos)/img_size - 0.5), 0.f),6); + weight *= sqrt(abs(1.f/(td + Camera.size + 1e-5))); + imageStore(output_w, global_pos, vec4(max(color.x,max(color.y,color.z))*weight, weight, 0, 1)); +} \ No newline at end of file diff --git a/shaders/compute/main.cfg b/shaders/compute/main.cfg new file mode 100644 index 00000000..1055c61d --- /dev/null +++ b/shaders/compute/main.cfg @@ -0,0 +1,93 @@ +#############MAIN SHADER PIPELINE################### +#number of main textures(1 depth map, 2 HDR color) +#this should be first, at least 2 textures +2 +#################################################### +#shader name +multires_marching/MRRM1.glsl +#global size +width/(8*MRRM_scale) +height/(8*MRRM_scale) +#texture resolution +width/MRRM_scale +height/MRRM_scale +#output texture number +3 +#################################################### +#shader name +multires_marching/MRRM2.glsl +#global size +width/8 +height/8 +#texture resolution +width +height +#output texture number +0 +#################################################### +#shader name #half res shadows and AO +main/Illumination_step.glsl +#global size +width/(shadow_scale*8) +height/(shadow_scale*8) +#texture resolution +width/shadow_scale +height/shadow_scale +#output texture number +1 +#################################################### +#shader name +main/Shading_step.glsl +#global size +width/8 +height/8 +#texture resolution +width +height +#output texture number +1 +#################################################### +#shader name +post_processing/downsampling.glsl +#global size +width/(8*bloom_scale) +height/(8*bloom_scale) +#texture resolution +width/bloom_scale +height/bloom_scale +#output texture number +1 +#################################################### +#shader name +post_processing/Bloom_horiz.glsl +#global size +width/(bloom_scale*128) +height/bloom_scale +#texture resolution +width/bloom_scale +height/bloom_scale +#output texture number +2 +#################################################### +#shader name +post_processing/Bloom_vertic.glsl +#global size +width/bloom_scale +height/(bloom_scale*128) +#texture resolution +width/bloom_scale +height/bloom_scale +#output texture number +1 +#################################################### +#shader name +main/Final_step.glsl +#global size +width/8 +height/8 +#texture resolution +width +height +#output texture number +1 +#################################################### \ No newline at end of file diff --git a/shaders/compute/main/Final_step.glsl b/shaders/compute/main/Final_step.glsl new file mode 100644 index 00000000..240e4bfb --- /dev/null +++ b/shaders/compute/main/Final_step.glsl @@ -0,0 +1,78 @@ +#version 430 +//4*4 ray bundle +#define group_size 8 +#define buffer_size 64 + +layout(local_size_x = group_size, local_size_y = group_size) in; +layout(rgba32f, binding = 0) uniform image2D bloom; +layout(rgba8, binding = 1) uniform image2D final_color; +layout(rgba32f, binding = 2) uniform image2D DE_input; +layout(rgba32f, binding = 3) uniform image2D color_HDR; + +//?? +shared vec4 de_sph[1][1]; + +#include +#include + +#define DOF_samples 50 +#define DOF + +#define RA 2.5 +const float GA = 2.399; +const mat2 rot = mat2(cos(GA),sin(GA),-sin(GA),cos(GA)); + +//DOF radius camera distance dependence +float radius(float w) +{ + return (Camera.bokeh+0.001)*(max(w-Camera.focus,0.001)+max(Camera.size-w,1e-3))/(abs(w)+1e-3); // the angle +} + +float convol_kernel(float w1, float w2, float rad) +{ + float r1 = radius(w1); + float r2 = radius(w2); + float cent_p = step((rad-1.),r1); + float this_p = step((rad-1.),r2); + return pow(r2,-0.5)*(this_p*cent_p+step(r1,r2)*step(w2,w1)*this_p); +} + +vec3 dof(vec2 uv) +{ + float rad =RA/sqrt(DOF_samples); + vec2 img_size = vec2(imageSize(color_HDR)); + vec2 pixel=vec2(img_size.x)*0.001, angle=vec2(0,rad); + vec4 acc=vec4(0); + vec4 center = imageLoad(color_HDR, ivec2(uv+pixel*(rad-1.)*angle)); + acc += convol_kernel(center.w, center.w, rad)*vec4(center.xyz,1.); + rad=1.; + if(Camera.bokeh > 0.1) for (int j=0;j +#include + +///Half-resolution illumination step + + +void main() { + + ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); + ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); + + vec2 img_size = vec2(imageSize(illumination)); + vec2 pimg_size = vec2(imageSize(DE_input)); + vec2 step_scale = img_size/pimg_size; + + ivec2 prev_pos = min(ivec2((vec2(global_pos)/step_scale) + 0.5),ivec2(pimg_size)-1); + + ray rr = get_ray(vec2(global_pos)/img_size); + vec4 pos = vec4(rr.pos,0); + vec4 dir = vec4(rr.dir,0); + vec4 var = vec4(0); + + vec4 sph = imageLoad(DE_input, prev_pos); + float td = dot(dir.xyz, sph.xyz - pos.xyz);//traveled distance + + pos = sph; + dir.w += td; + + vec4 illum = vec4(0); + + if(pos.w < max(2*fovray*td, MIN_DIST) && SHADOWS_ENABLED) + { + pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; + pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; + pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; + illum.x = shadow_march(pos, normalize(vec4(LIGHT_DIRECTION,0)), MAX_DIST, LIGHT_ANGLE); + + //illum.y = ambient_occlusion(pos, norm); + } + illum.w = td; + imageStore(illumination, global_pos, illum); +} \ No newline at end of file diff --git a/shaders/compute/main/Shading_step.glsl b/shaders/compute/main/Shading_step.glsl new file mode 100644 index 00000000..ea915300 --- /dev/null +++ b/shaders/compute/main/Shading_step.glsl @@ -0,0 +1,48 @@ +#version 430 +//4*4 ray bundle +#define group_size 8 +#define block_size 64 + +layout(local_size_x = group_size, local_size_y = group_size) in; +layout(rgba32f, binding = 0) uniform image2D illumination; //shadows +layout(rgba32f, binding = 1) uniform image2D color_output; +layout(rgba32f, binding = 2) uniform image2D DE_input; +layout(rgba32f, binding = 3) uniform image2D color_HDR; //calculate final color + + +//make all the local distance estimator spheres shared +shared vec4 de_sph[group_size][group_size]; + +#include +#include + +void main() { + ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); + ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); + vec2 img_size = vec2(imageSize(color_HDR)); + float res_ratio = imageSize(illumination).x/img_size.x; + vec4 sph = imageLoad(DE_input, global_pos); + + + ray rr = get_ray(vec2(global_pos)/img_size); + vec4 pos = vec4(rr.pos,0); + vec4 dir = vec4(rr.dir,0); + vec4 var = vec4(0); + + float td = dot(dir.xyz, sph.xyz - pos.xyz);//traveled distance + + vec4 illum = bilinear_surface(illumination, td, 3*td*fovray/res_ratio, vec2(global_pos)*res_ratio); + //vec4 illum = interp(illumination, vec2(global_pos)*res_ratio); + pos = sph; + dir.w += td; + + vec3 color = shading(pos, dir, fovray, illum.x); + //color = vec3(illum.x); + vec3 prev_color = imageLoad(color_HDR, global_pos).xyz; + if(!isnan(color.x) && !isnan(color.y) && !isnan(color.z)) + { + //color = prev_color*Camera.mblur + (1-Camera.mblur)*color; //blur + imageStore(color_HDR, global_pos, vec4(color.xyz, td)); + imageStore(color_output, global_pos, vec4(color.xyz, td)); + } +} \ No newline at end of file diff --git a/shaders/compute/main/global_illumination_step.glsl b/shaders/compute/main/global_illumination_step.glsl new file mode 100644 index 00000000..f7b59346 --- /dev/null +++ b/shaders/compute/main/global_illumination_step.glsl @@ -0,0 +1,52 @@ +#version 430 +#define group_size 8 +#define block_size 64 + +layout(local_size_x = group_size, local_size_y = group_size) in; +layout(rgba32f, binding = 0) uniform image2D DE_input; +layout(rgba32f, binding = 1) uniform image2D color_HDR; //calculate final color +layout(rgba32f, binding = 2) uniform image2D illumination; + +//make all the local distance estimator spheres shared +shared vec4 de_sph[group_size][group_size]; + +#include +#include + +///Half-resolution global illumination step + +void main() { + + ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); + ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); + + vec2 img_size = vec2(imageSize(illumination)); + vec2 pimg_size = vec2(imageSize(DE_input)); + vec2 step_scale = img_size/pimg_size; + + ivec2 prev_pos = min(ivec2((vec2(global_pos)/step_scale) + 0.5),ivec2(pimg_size)-1); + + ray rr = get_ray(vec2(global_pos)/img_size); + vec4 pos = vec4(rr.pos,0); + vec4 dir = vec4(rr.dir,0); + vec4 var = vec4(0); + + vec4 sph = imageLoad(DE_input, prev_pos); + float td = dot(dir.xyz, sph.xyz - pos.xyz);//traveled distance + + pos = sph; + dir.w += td; + + vec4 illum = vec4(0); + + if(pos.w < max(2*fovray*td, MIN_DIST) && SHADOWS_ENABLED) + { + pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; + pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; + pos.xyz += (DE(pos.xyz) - 2.*fovray*td/step_scale.x)*dir.xyz; + + illum.xyz = ambient_light(pos); + } + illum.w = td; + imageStore(illumination, global_pos, illum); +} \ No newline at end of file diff --git a/shaders/compute/mainGI.cfg b/shaders/compute/mainGI.cfg new file mode 100644 index 00000000..7e4dc631 --- /dev/null +++ b/shaders/compute/mainGI.cfg @@ -0,0 +1,104 @@ +#############MAIN SHADER PIPELINE################### +#number of main textures(1 depth map, 2 HDR color) +#this should be first, at least 2 textures +3 +#################################################### +#shader name +multires_marching/MRRM1.glsl +#global size +width/(8*MRRM_scale) +height/(8*MRRM_scale) +#texture resolution +width/MRRM_scale +height/MRRM_scale +#output texture number +3 +#################################################### +#shader name +multires_marching/MRRM2.glsl +#global size +width/8 +height/8 +#texture resolution +width +height +#output texture number +0 +#################################################### +#shader name #8x downscaled GI +main/global_illumination_step.glsl +#global size +width/(8*8) +height/(8*8) +#texture resolution +width/8 +height/8 +#output texture number +0 +#################################################### +#shader name #half res shadows and AO +main/Illumination_step.glsl +#global size +width/(shadow_scale*8) +height/(shadow_scale*8) +#texture resolution +width/shadow_scale +height/shadow_scale +#output texture number +1 +#################################################### +#shader name +main/Shading_step.glsl +#global size +width/8 +height/8 +#texture resolution +width +height +#output texture number +1 +#################################################### +#shader name +post_processing/downsampling.glsl +#global size +width/(8*bloom_scale) +height/(8*bloom_scale) +#texture resolution +width/bloom_scale +height/bloom_scale +#output texture number +1 +#################################################### +#shader name +post_processing/Bloom_horiz.glsl +#global size +width/(bloom_scale*128) +height/bloom_scale +#texture resolution +width/bloom_scale +height/bloom_scale +#output texture number +2 +#################################################### +#shader name +post_processing/Bloom_vertic.glsl +#global size +width/bloom_scale +height/(bloom_scale*128) +#texture resolution +width/bloom_scale +height/bloom_scale +#output texture number +1 +#################################################### +#shader name +main/Final_step.glsl +#global size +width/8 +height/8 +#texture resolution +width +height +#output texture number +1 +#################################################### \ No newline at end of file diff --git a/shaders/compute/multires_marching/MRRM1.glsl b/shaders/compute/multires_marching/MRRM1.glsl new file mode 100644 index 00000000..1ebab7c0 --- /dev/null +++ b/shaders/compute/multires_marching/MRRM1.glsl @@ -0,0 +1,44 @@ +#version 430 +#define group_size 8 +#define block_size 64 + +layout(local_size_x = group_size, local_size_y = group_size) in; +layout(rgba32f, binding = 0) uniform image2D DE_output; //calculate final DE spheres +layout(rgba32f, binding = 1) uniform image2D DE2_output; +layout(rgba32f, binding = 2) uniform image2D var_output; +layout(rgba32f, binding = 3) uniform image2D DE_input; +layout(rgba32f, binding = 4) uniform image2D color_HDR; //calculate final color + +//make all the local distance estimator spheres shared +shared vec4 de_sph[group_size][group_size]; + +#include +#include + +///The first step of multi resolution ray marching + +void main() { + ivec2 global_pos = ivec2(gl_GlobalInvocationID.x,gl_GlobalInvocationID.y); + int local_indx = int(gl_LocalInvocationIndex); + vec2 img_size = vec2(imageSize(DE_output)); + //if within the texture + + //initialize the ray + ray rr = get_ray(vec2(global_pos)/img_size); + vec4 pos = vec4(rr.pos,0); + vec4 dir = vec4(rr.dir,0); + vec4 var = vec4(0); + float res_ratio = float(imageSize(color_HDR).x/imageSize(DE_output).x); + fovray *= res_ratio; + dir.w = 4*Camera.size; + ray_march_limited(pos, dir, var, 2.*fovray); + + vec4 pos1 = pos; + + normarch(pos1); + + //save the DE spheres + imageStore(DE_output, global_pos, pos); + imageStore(DE2_output, global_pos, pos1); + imageStore(var_output, global_pos, var); +} \ No newline at end of file diff --git a/shaders/compute/multires_marching/MRRM2.glsl b/shaders/compute/multires_marching/MRRM2.glsl new file mode 100644 index 00000000..ff244ab6 --- /dev/null +++ b/shaders/compute/multires_marching/MRRM2.glsl @@ -0,0 +1,64 @@ +#version 430 +//4*4 ray bundle +#define group_size 8 +#define block_size 64 +#define RBM1 0 + +layout(local_size_x = group_size, local_size_y = group_size) in; +layout(rgba32f, binding = 0) uniform image2D DE_input; +layout(rgba32f, binding = 1) uniform image2D DE2_input; +layout(rgba32f, binding = 2) uniform image2D var_input; +layout(rgba32f, binding = 3) uniform image2D DE_output; //calculate final DE spheres + +//make all the local distance estimator spheres shared +shared vec4 de_sph[group_size][group_size]; + +#include +#include + +///The second step of multi resolution ray marching + +void main() { + ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); + ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); + vec2 img_size = vec2(imageSize(DE_output)); + vec2 pimg_size = vec2(imageSize(DE_input)); + vec2 MRRM_step_scale = img_size/pimg_size; + //if within the texture + + ivec2 prev_pos = min(ivec2((vec2(global_pos)/MRRM_step_scale) + 0.5),ivec2(pimg_size)-1); + //initialize the ray + vec4 sph = imageLoad(DE_input, prev_pos); + vec4 sph_norm = imageLoad(DE2_input, prev_pos); + + #if(RBM1) + de_sph[local_indx.x][local_indx.y] = sph; + memoryBarrierShared(); + #endif + + ray rr = get_ray(vec2(global_pos)/img_size); + vec4 pos = vec4(rr.pos,0); + vec4 dir = vec4(rr.dir,0); + vec4 var = imageLoad(var_input, prev_pos); + + float td = dot(dir.xyz, sph.xyz - pos.xyz);//traveled distance + + //first order, MRRM + pos.xyz += dir.xyz*td;//move local ray beginning inside the DE sphere + dir.w += td; + + //calculate new best pos, second order, MRRBM + #if(RBM1) + barrier(); + pos.w = find_furthest_intersection(dir.xyz, pos.xyz, local_indx); + #else + pos.w = sphere_intersection(dir.xyz, pos.xyz, sph); + pos.w = max(pos.w, sphere_intersection(dir.xyz, pos.xyz, sph_norm)); + #endif + + + ray_march_continue(pos, dir, var, fovray); + + //save the DE spheres + imageStore(DE_output, global_pos, pos); +} \ No newline at end of file diff --git a/shaders/compute/neon.cfg b/shaders/compute/neon.cfg new file mode 100644 index 00000000..712c5eb1 --- /dev/null +++ b/shaders/compute/neon.cfg @@ -0,0 +1,14 @@ +#number of main textures(HDR color and position map) // this should be first +0 +##################################################### +#shader name +neon/neon_shading.glsl +#global size +width/8 +height/8 +#texture resolution +width +height +#output texture number +1 +##################################################### \ No newline at end of file diff --git a/shaders/compute/neon/neon_shading.glsl b/shaders/compute/neon/neon_shading.glsl new file mode 100644 index 00000000..cf027bfc --- /dev/null +++ b/shaders/compute/neon/neon_shading.glsl @@ -0,0 +1,28 @@ +#version 430 +//4*4 ray bundle +#define group_size 8 +#define block_size 64 + +layout(local_size_x = group_size, local_size_y = group_size) in; +layout(rgba8, binding = 0) uniform image2D final_color; + +//make all the local distance estimator spheres shared +shared vec4 de_sph[group_size][group_size]; + +#include +#include + +void main() { + ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); + ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); + vec2 img_size = vec2(imageSize(final_color)); + + ray rr = get_ray(vec2(global_pos)/img_size); + vec4 pos = vec4(rr.pos,0); + vec4 dir = vec4(rr.dir,0); + vec4 var = vec4(0); + + vec3 color = NEON_shading(pos, dir); + + imageStore(final_color, global_pos, vec4(HDRmapping(color,1.), 1)); +} \ No newline at end of file diff --git a/shaders/compute/noise/noise.glsl b/shaders/compute/noise/noise.glsl new file mode 100644 index 00000000..9626da6c --- /dev/null +++ b/shaders/compute/noise/noise.glsl @@ -0,0 +1,24 @@ +#version 430 +//4*4 ray bundle +#define group_size 8 +#define buffer_size 64 + +layout(local_size_x = group_size, local_size_y = group_size) in; +layout(rgba8, binding = 0) uniform image2D final_color; //final output texture 1 (used as final color) +//global, always the last ones +layout(rgba32f, binding = 1) uniform image2D DE_input; //global tex +layout(rgba32f, binding = 2) uniform image2D color_HDR; //global tex + +#define PI 3.14159265 +#include + +void main() { + ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); + vec2 img_size = vec2(imageSize(color_HDR)); + + vec2 uv = vec2(global_pos)/img_size; + + //vec3 col = 0.5*perlin4(25*uv).xyz + 0.5; + vec3 col = blue3(300.*uv, float(iFrame)*0.2); + imageStore(final_color, global_pos, vec4(col, 1)); +} \ No newline at end of file diff --git a/shaders/compute/noise_test.cfg b/shaders/compute/noise_test.cfg new file mode 100644 index 00000000..e5f22a3e --- /dev/null +++ b/shaders/compute/noise_test.cfg @@ -0,0 +1,14 @@ +#number of main textures(HDR color and position map) // this should be first +2 +##################################################### +#shader name +noise/noise.glsl +#global size +width/8 +height/8 +#texture resolution +width +height +#output texture number +1 +##################################################### \ No newline at end of file diff --git a/shaders/compute/original.cfg b/shaders/compute/original.cfg new file mode 100644 index 00000000..4f8179de --- /dev/null +++ b/shaders/compute/original.cfg @@ -0,0 +1,47 @@ +#number of main textures(HDR color and position map) // this should be first +2 +#################################################### +#shader name +multires_marching/MRRM1.glsl +#global size +width/(8*MRRM_scale) +height/(8*MRRM_scale) +#texture resolution +width/MRRM_scale +height/MRRM_scale +#output texture number +3 +#################################################### +#shader name +multires_marching/MRRM2.glsl +#global size +width/8 +height/8 +#texture resolution +width +height +#output texture number +0 +#################################################### +#shader name #half res shadows and AO +main/Illumination_step.glsl +#global size +width/(shadow_scale*8) +height/(shadow_scale*8) +#texture resolution +width/shadow_scale +height/shadow_scale +#output texture number +1 +#################################################### +#shader name +original/original_shading.glsl +#global size +width/8 +height/8 +#texture resolution +width +height +#output texture number +1 +#################################################### \ No newline at end of file diff --git a/shaders/compute/original/original_functions.glsl b/shaders/compute/original/original_functions.glsl new file mode 100644 index 00000000..ddc79d97 --- /dev/null +++ b/shaders/compute/original/original_functions.glsl @@ -0,0 +1,198 @@ +#define DIFFUSE_ENABLED 0 +#define DIFFUSE_ENHANCED_ENABLED 1 +#define FILTERING_ENABLE 0 +#define FOCAL_DIST 1.73205080757 +#define FOG_ENABLED 0 +#define SHADOW_DARKNESS 0.7 +#define SHADOW_SHARPNESS 10.0 +#define SPECULAR_HIGHLIGHT 40 +#define SPECULAR_MULT 0.25 +#define SUN_ENABLED 1 +#define SUN_SHARPNESS 2.0 +#define SUN_SIZE 0.004 +#define BACKGROUND_COLOR vec3(0.6,0.8,1.0) + + +vec3 sky_color_orig(vec3 dir) +{ + vec3 col = BACKGROUND_COLOR; + + //Background specular + #if SUN_ENABLED + float sun_spec = dot(dir, LIGHT_DIRECTION) - 1.0 + SUN_SIZE; + sun_spec = min(exp(sun_spec * SUN_SHARPNESS / SUN_SIZE), 1.0); + col.xyz += LIGHT_COLOR * sun_spec; + #endif + + return col; +} + +vec3 lighting_original(vec4 color, vec2 pbr, vec4 pos, vec4 dir, vec4 norm, vec3 refl, vec3 refr, float shadow) +{ + color.xyz *= 2.; + vec3 col = vec3(0.); + //Get if this point is in shadow + float k = shadow; + vec4 ambient_color = ambient_occlusion(pos, norm, dir); + if(!SHADOWS_ENABLED) + { + k = ambient_color.w; + } + vec3 n = norm.xyz; + //Get specular + #if SPECULAR_HIGHLIGHT > 0 + vec3 reflected = dir.xyz - 2.0*dot(dir.xyz, n) * n; + float specular = max(dot(reflected, LIGHT_DIRECTION), 0.0); + specular = pow(specular, SPECULAR_HIGHLIGHT); + col.xyz += specular * LIGHT_COLOR * (k * SPECULAR_MULT); + #endif + + //Get diffuse lighting + #if DIFFUSE_ENHANCED_ENABLED + k = min(k, SHADOW_DARKNESS * 0.5 * (dot(n, LIGHT_DIRECTION) - 1.0) + 1.0); + #elif DIFFUSE_ENABLED + k = min(k, dot(n, LIGHT_DIRECTION)); + #endif + + //Don't make shadows entirely dark + k = max(k, 1.0 - SHADOW_DARKNESS); + col.xyz += color.xyz * LIGHT_COLOR * k; + + //Add small amount of ambient occlusion + col.xyz *= 0.5 + 0.5*ambient_color.w; + + //Add fog effects + #if FOG_ENABLED + float b = dir.w / MAX_DIST; + col.xyz = (1.0 - b) * col.xyz + b * BACKGROUND_COLOR; + #endif + + vec3 V = -dir.xyz; + vec3 N = norm.xyz; + + if(color.w>0.5) // if marble + { + col *= 0.; + vec3 n = norm.xyz; + vec3 q = dir.xyz - n*(2*dot(dir.xyz,n)); + //Combine for final marble color + if(MARBLE_MODE == 0) + { + //glass + vec3 F0 = vec3(0.03); + vec3 L = normalize(q); + vec3 H = normalize(V + L); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + col += kS*refl + kD*refr; + } + else if(MARBLE_MODE > 0) + { + //metal + vec3 F0 = vec3(0.6); + vec3 L = normalize(q); + vec3 H = normalize(V + L); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + col += kS*refl; + } + } + + return col; +} + + + +vec3 shading_simple_orig(in vec4 pos, in vec4 dir, float fov, float shadow) +{ + if(pos.w < max(16*fovray*dir.w, MIN_DIST)) + { + //calculate the normal + float error = 0.5*fov*dir.w; + vec4 norm = calcNormal(pos.xyz, max(MIN_DIST, error)); + norm.xyz = normalize(norm.xyz); + if(norm.w < -error) + { + return COL(pos.xyz).xyz; + } + else + { + //optimize color sampling + vec3 cpos = pos.xyz - pos.w*norm.xyz; + //cpos = cpos - DE(cpos)*norm.xyz; + //cpos = cpos - DE(cpos)*norm.xyz; + + vec4 color; vec2 pbr; + scene_material(cpos, color, pbr); + return lighting_original(color, pbr, pos, dir, norm, vec3(0), vec3(0), shadow); + } + } + else + { + return sky_color_orig(dir.xyz); + } +} + + +vec3 render_ray_orig(in vec4 pos, in vec4 dir, float fov) +{ + vec4 var = vec4(0,0,0,1); + ray_march(pos, dir, var, fov); + float shadow = shadow_march(pos, vec4(LIGHT_DIRECTION,0), 10., LIGHT_ANGLE); + return shading_simple_orig(pos, dir, fov, shadow); +} + +vec3 shading_orig(in vec4 pos, in vec4 dir, float fov, float shadow) +{ + if(pos.w < max(2*fovray*dir.w, MIN_DIST)) + { + //calculate the normal + float error = 0.5*fov*dir.w; + vec4 norm = calcNormal(pos.xyz, max(MIN_DIST, error)); + norm.xyz = normalize(norm.xyz); + if(norm.w < -error) + { + return COL(pos.xyz).xyz; + } + else + { + //optimize color sampling + vec3 cpos = pos.xyz - norm.w*norm.xyz; + vec4 color; vec2 pbr; + scene_material(cpos, color, pbr); + vec3 refl = vec3(0); + vec3 refr = vec3(0); + if(color.w>0.5) // if marble + { + vec3 n = normalize(iMarblePos - cpos.xyz); + vec3 q = refraction(dir.xyz, n, 1.0 / 1.5); + vec3 p2 = pos.xyz + (dot(q, n) * 2. * iMarbleRad) * q; + n = normalize(p2 - iMarblePos); + q = (dot(q, dir.xyz) * 2.0) * q - dir.xyz; + vec4 p_temp = vec4(p2+ n*fov*dir.w*2.5, 0); + vec4 r_temp = vec4(q, dir.w); + + refr = render_ray_orig(p_temp, r_temp, fov*1.5); + + //Calculate reflection + n = -normalize(iMarblePos - cpos.xyz); + q = dir.xyz - n*(2*dot(dir.xyz,n)); + p_temp = vec4(pos.xyz + n*fov*dir.w*2., 0); + r_temp = vec4(q, dir.w); + + refl = render_ray_orig(p_temp, r_temp, fov*2.); + } + + return lighting_original(color, pbr, vec4(cpos, pos.w), dir, norm, refl, refr, shadow); + } + } + else + { + return sky_color_orig(dir.xyz); + } + +} \ No newline at end of file diff --git a/shaders/compute/original/original_shading.glsl b/shaders/compute/original/original_shading.glsl new file mode 100644 index 00000000..9925fcc9 --- /dev/null +++ b/shaders/compute/original/original_shading.glsl @@ -0,0 +1,49 @@ +#version 430 +//4*4 ray bundle +#define group_size 8 +#define block_size 64 + +layout(local_size_x = group_size, local_size_y = group_size) in; +layout(rgba32f, binding = 0) uniform image2D illumination; //shadows +layout(rgba32f, binding = 1) uniform image2D color_output; +layout(rgba32f, binding = 2) uniform image2D DE_input; +layout(rgba32f, binding = 3) uniform image2D color_HDR; //calculate final color + + +//make all the local distance estimator spheres shared +shared vec4 de_sph[group_size][group_size]; + +#include +#include +#include + +void main() { + ivec2 global_pos = ivec2(gl_GlobalInvocationID.xy); + ivec2 local_indx = ivec2(gl_LocalInvocationID.xy); + vec2 img_size = vec2(imageSize(color_HDR)); + float res_ratio = imageSize(illumination).x/img_size.x; + vec4 sph = imageLoad(DE_input, global_pos); + + + ray rr = get_ray(vec2(global_pos)/img_size); + vec4 pos = vec4(rr.pos,0); + vec4 dir = vec4(rr.dir,0); + vec4 var = vec4(0); + + float td = dot(dir.xyz, sph.xyz - pos.xyz);//traveled distance + + vec4 illum = bilinear_surface(illumination, td, 3*td*fovray/res_ratio, vec2(global_pos)*res_ratio); + //vec4 illum = interp(illumination, vec2(global_pos)*res_ratio); + pos = sph; + dir.w += td; + + vec3 color = shading_orig(pos, dir, fovray, illum.x); + + vec3 prev_color = imageLoad(color_HDR, global_pos).xyz; + if(!isnan(color.x) && !isnan(color.y) && !isnan(color.z)) + { + //color = prev_color*Camera.mblur + (1-Camera.mblur)*color; //blur + imageStore(color_HDR, global_pos, vec4(color.xyz, td)); + imageStore(color_output, global_pos, vec4(color.xyz, 1.)); + } +} \ No newline at end of file diff --git a/shaders/compute/post_processing/Bloom_horiz.glsl b/shaders/compute/post_processing/Bloom_horiz.glsl new file mode 100644 index 00000000..5a32f3c0 --- /dev/null +++ b/shaders/compute/post_processing/Bloom_horiz.glsl @@ -0,0 +1,72 @@ +#version 430 +//4*4 ray bundle +#define group_size 128 +#define buffer_size 256 + +layout(local_size_x = group_size, local_size_y = 1) in; +layout(rgba32f, binding = 0) uniform image2D color_input; //calculate bloom +layout(rgba32f, binding = 1) uniform image2D blurred_hor1; //calculate bloom +layout(rgba32f, binding = 2) uniform image2D blurred_hor2; //calculate bloom +layout(rgba32f, binding = 3) uniform image2D DE_input; +layout(rgba32f, binding = 4) uniform image2D color_HDR; //calculate final color + +#include +#include + +shared vec3 color_buffer[buffer_size]; + +int safe_coord(int x, vec2 img_size) +{ + if(x >= 0 && x + +int safe_coord(int y, vec2 img_size) +{ + if(y >= 0 && y 1 || res_ratio.y > 1) + { + for(int i = 0; i < res_ratio.x; i++) + { + for(int j = 0; j < res_ratio.y; j++) + { + sum += imageLoad(high_res, ivec2(global_pos*res_ratio) + ivec2(i,j)); + } + } + sum /= res_ratio.x*res_ratio.y; + } + else + { + sum = imageLoad(high_res, global_pos); + } + + imageStore(low_res, global_pos, sum); +} \ No newline at end of file diff --git a/shaders/compute/utility/RNG.glsl b/shaders/compute/utility/RNG.glsl new file mode 100644 index 00000000..24233fba --- /dev/null +++ b/shaders/compute/utility/RNG.glsl @@ -0,0 +1,240 @@ +#define SQRT2 1.4142135 +#define SQRT3 1.7320508 +#define SQRT5 2.2360679 +#define PERLIN_SCALE 3 + +uniform float iFrame; + +// HASH STUFF + +// Hash without Sine +// MIT License... +/* Copyright (c)2014 David Hoskins. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +//---------------------------------------------------------------------------------------- +// 1 out, 1 in... +float hash(float p) +{ + p = fract(p * .1031); + p *= p + 33.33; + p *= p + p; + return fract(p); +} + +//---------------------------------------------------------------------------------------- +// 1 out, 2 in... +float hash12(vec2 p) +{ + vec3 p3 = fract(vec3(p.xyx) * .1031); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + +//---------------------------------------------------------------------------------------- +// 1 out, 3 in... +float hash13(vec3 p3) +{ + p3 = fract(p3 * .1031); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + +//---------------------------------------------------------------------------------------- +// 2 out, 1 in... +vec2 hash21(float p) +{ + vec3 p3 = fract(vec3(p) * vec3(.1031, .1030, .0973)); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.xx+p3.yz)*p3.zy); + +} + +//---------------------------------------------------------------------------------------- +/// 2 out, 2 in... +vec2 hash22(vec2 p) +{ + vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973)); + p3 += dot(p3, p3.yzx+33.33); + return fract((p3.xx+p3.yz)*p3.zy); + +} + +//---------------------------------------------------------------------------------------- +/// 2 out, 3 in... +vec2 hash23(vec3 p3) +{ + p3 = fract(p3 * vec3(.1031, .1030, .0973)); + p3 += dot(p3, p3.yzx+33.33); + return fract((p3.xx+p3.yz)*p3.zy); +} + +//---------------------------------------------------------------------------------------- +// 3 out, 1 in... +vec3 hash31(float p) +{ + vec3 p3 = fract(vec3(p) * vec3(.1031, .1030, .0973)); + p3 += dot(p3, p3.yzx+33.33); + return fract((p3.xxy+p3.yzz)*p3.zyx); +} + + +//---------------------------------------------------------------------------------------- +/// 3 out, 2 in... +vec3 hash32(vec2 p) +{ + vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973)); + p3 += dot(p3, p3.yxz+33.33); + return fract((p3.xxy+p3.yzz)*p3.zyx); +} + +//---------------------------------------------------------------------------------------- +/// 3 out, 3 in... +vec3 hash33(vec3 p3) +{ + p3 = fract(p3 * vec3(.1031, .1030, .0973)); + p3 += dot(p3, p3.yxz+33.33); + return fract((p3.xxy + p3.yxx)*p3.zyx); + +} + +//---------------------------------------------------------------------------------------- +// 4 out, 1 in... +vec4 hash41(float p) +{ + vec4 p4 = fract(vec4(p) * vec4(.1031, .1030, .0973, .1099)); + p4 += dot(p4, p4.wzxy+33.33); + return fract((p4.xxyz+p4.yzzw)*p4.zywx); + +} + +//---------------------------------------------------------------------------------------- +// 4 out, 2 in... +vec4 hash42(vec2 p) +{ + vec4 p4 = fract(vec4(p.xyxy) * vec4(.1031, .1030, .0973, .1099)); + p4 += dot(p4, p4.wzxy+33.33); + return fract((p4.xxyz+p4.yzzw)*p4.zywx); + +} + +//---------------------------------------------------------------------------------------- +// 4 out, 3 in... +vec4 hash43(vec3 p) +{ + vec4 p4 = fract(vec4(p.xyzx) * vec4(.1031, .1030, .0973, .1099)); + p4 += dot(p4, p4.wzxy+33.33); + return fract((p4.xxyz+p4.yzzw)*p4.zywx); +} + +//---------------------------------------------------------------------------------------- +// 4 out, 4 in... +vec4 hash44(vec4 p4) +{ + p4 = fract(p4 * vec4(.1031, .1030, .0973, .1099)); + p4 += dot(p4, p4.wzxy+33.33); + return fract((p4.xxyz+p4.yzzw)*p4.zywx); +} + + +//normally distributed random numbers +vec3 randn(float p) +{ + vec4 rand = hash41(p); + vec3 box_muller = sqrt(-2.*log(max(vec3(rand.x,rand.x,rand.z),1e-8)))*vec3(sin(2.*PI*rand.y),cos(2.*PI*rand.y),sin(2.*PI*rand.w)); + return box_muller; +} + +//uniformly inside a sphere +vec3 random_sphere(float p) +{ + return normalize(randn(p))*pow(hash(p+85.67),0.333333); +} + +vec3 cosdistr(vec3 dir, float seed) +{ + vec3 rand_dir = normalize(randn(seed*SQRT2)); + vec3 norm_dir = normalize(rand_dir - dot(dir,rand_dir)*dir); + float u = hash(seed); + return normalize(dir*sqrt(u) + norm_dir*sqrt(1.-u)); +} + + +vec4 perlin_octave(vec2 p) +{ + vec2 pi = floor(p); + vec2 pf = p - pi; + vec2 pfc = 0.5 - 0.5*cos(pf*PI); + vec2 a = vec2(0.,1.); + + vec4 a00 = hash42(pi+a.xx); + vec4 a01 = hash42(pi+a.xy); + vec4 a10 = hash42(pi+a.yx); + vec4 a11 = hash42(pi+a.yy); + + vec4 i1 = mix(a00, a01, pfc.y); + vec4 i2 = mix(a10, a11, pfc.y); + + return mix(i1, i2, pfc.x); +} + +mat2 rotat = mat2(cos(0.5), -sin(0.5), sin(0.5), cos(0.5)); + +vec4 perlin4(vec2 p) +{ + float a = 1.; + vec4 res = vec4(0.); + for(int i = 0; i < PERLIN_SCALE; i++) + { + res += a*(perlin_octave(p)-0.5); + //inverse perlin + p *= 0.6*rotat; + a *= 1.2; + } + return res; +} + +float singrid(vec2 p, float angle) +{ + return 0.5*(sin(cos(angle)*p.x + sin(angle)*p.y)*sin(-sin(angle)*p.x + cos(angle)*p.y) + 1.); +} + +//technically this is not a blue noise, but a single freqency noise, the spectrum should look like a gaussian peak around a frequency +float blue(vec2 p, float seed) +{ + seed = 100.*hash(seed); + vec2 shift = 20.*hash21(seed); + p += shift; + vec2 pnoise = perlin4(p*0.25+seed).xy; + + //bilinear interpolation between sin grids + return singrid(p,0.)*(pnoise.x*pnoise.y+(1.-pnoise.x)*(1.-pnoise.y)) + + singrid(p,3.14159*0.33*2.)*(1.-pnoise.x)*pnoise.y + + singrid(p,3.14159*0.66*2.)*(1.-pnoise.y)*pnoise.x; +} + +vec3 blue3(vec2 p, float seed) +{ + vec3 res; + res.x = blue(p, sin(seed)); + res.y = blue(p, sin(2.*seed)); + res.z = blue(p, sin(3.*seed)); + return res; +} \ No newline at end of file diff --git a/shaders/compute/utility/bloom.glsl b/shaders/compute/utility/bloom.glsl new file mode 100644 index 00000000..379bf814 --- /dev/null +++ b/shaders/compute/utility/bloom.glsl @@ -0,0 +1,6 @@ +vec3 bloom_treshold(vec3 color, float exposure) +{ + color = clamp(color*exposure, 0, 100)/exposure; + vec3 mapped = Camera.bloomintensity*exposure*pow(color,vec3(2.)); + return mapped; +} \ No newline at end of file diff --git a/shaders/compute/utility/camera.glsl b/shaders/compute/utility/camera.glsl new file mode 100644 index 00000000..92912462 --- /dev/null +++ b/shaders/compute/utility/camera.glsl @@ -0,0 +1,58 @@ + +struct ray +{ + vec3 pos; + vec3 dir; +}; + +struct glcamera +{ + vec3 position; + vec3 dirx; + vec3 diry; + vec3 dirz; + vec2 resolution; + float aspect_ratio; + float FOV; + float focus; + float bokeh; + float exposure; + float mblur; + float speckle; + float size; + float bloomintensity; + float bloomradius; + bool cross_eye; + float eye_separation; +}; + + +ivec2 getGpos(int index) +{ + int y = index/group_size; + int x = index%group_size; + return ivec2(x,y); +} + +uniform glcamera Camera; +float fovray; + + + +ray get_ray(vec2 screen_pos) +{ + float delta = 0; + if(Camera.cross_eye) + { + delta = Camera.eye_separation*(2.f*floor(2.f*screen_pos.x)-1.f); + screen_pos.x = 0.5*(mod(2*screen_pos.x,1.f)+0.5); + } + + vec2 shift = Camera.FOV*(2.f*screen_pos - 1.f)*vec2(Camera.aspect_ratio, -1.f); + ray cray; + cray.pos = Camera.position + (Camera.cross_eye?(Camera.dirx*delta):(Camera.size*(Camera.dirx*(shift.x) + Camera.diry*shift.y))); + cray.dir = normalize(Camera.dirx*shift.x + Camera.diry*shift.y + Camera.dirz); + float aspect_ratio_ratio = Camera.aspect_ratio/(Camera.resolution.x/Camera.resolution.y); + fovray = 1.41*Camera.FOV*max(1.f/aspect_ratio_ratio, aspect_ratio_ratio)/Camera.resolution.x; //pixel FOV + return cray; +} \ No newline at end of file diff --git a/shaders/compute/utility/distance_estimators.glsl b/shaders/compute/utility/distance_estimators.glsl new file mode 100644 index 00000000..857af706 --- /dev/null +++ b/shaders/compute/utility/distance_estimators.glsl @@ -0,0 +1,257 @@ +#define COL col_scene +#define DE de_scene + +uniform float iFracScale; +uniform float iFracAng1; +uniform float iFracAng2; +uniform vec3 iFracShift; +uniform vec3 iFracCol; +uniform vec3 iMarblePos; +uniform float iMarbleRad; +uniform float iFlagScale; +uniform vec3 iFlagPos; +uniform int FRACTAL_ITER; +uniform int MARBLE_MODE; +uniform float time; + +uniform float PBR_METALLIC; +uniform float PBR_ROUGHNESS; + +layout(rgba8, binding = 4) uniform image2D color_flag; + +///Original MM distance estimators + +float s1 = sin(iFracAng1), c1 = cos(iFracAng1), s2 = sin(iFracAng2), c2 = cos(iFracAng2); + +//########################################## +// Space folding +//########################################## +void planeFold(inout vec4 z, vec3 n, float d) { + z.xyz -= 2.0 * min(0.0, dot(z.xyz, n) - d) * n; +} +void sierpinskiFold(inout vec4 z) { + z.xy -= min(z.x + z.y, 0.0); + z.xz -= min(z.x + z.z, 0.0); + z.yz -= min(z.y + z.z, 0.0); +} + +// Polynomial smooth minimum by iq +float smoothmin(float a, float b, float k) { + float h = clamp(0.5 + 0.5*(a-b)/k, 0.0, 1.0); + return mix(a, b, h) - k*h*(1.0-h); +} + +/*void mengerFold(inout vec4 z) { + float a = smoothmin(z.x - z.y, 0.0, 0.03); + z.x -= a; + z.y += a; + a = smoothmin(z.x - z.z, 0.0, 0.03); + z.x -= a; + z.z += a; + a = smoothmin(z.y - z.z, 0.0, 0.03); + z.y -= a; + z.z += a; +}*/ + +vec2 mp = vec2(-1.,1.); +void mengerFold(inout vec4 z) +{ + z.xy += min(z.x - z.y, 0.0)*mp; + z.xz += min(z.x - z.z, 0.0)*mp; + z.yz += min(z.y - z.z, 0.0)*mp; +} + +void boxFold(inout vec4 z, vec3 r) { + z.xyz = clamp(z.xyz, -r, r) * 2.0 - z.xyz; +} + +//########################################## +// Primitive DEs +//########################################## +float de_sphere(vec4 p, float r) { + return (length(p.xyz) - r) / p.w; +} +float de_box(vec4 p, vec3 s) { + vec3 a = abs(p.xyz) - s; + return (min(max(max(a.x, a.y), a.z), 0.0) + length(max(a, 0.0))) / p.w; +} +float de_tetrahedron(vec4 p, float r) { + float md = max(max(-p.x - p.y - p.z, p.x + p.y - p.z), + max(-p.x + p.y + p.z, p.x - p.y + p.z)); + return (md - r) / (p.w * sqrt(3.0)); +} +float de_capsule(vec4 p, float h, float r) { + p.y -= clamp(p.y, -h, h); + return (length(p.xyz) - r) / p.w; +} + +//########################################## +// Main DEs +//########################################## +float de_fractal(vec4 p) +{ + mat2 rmZ = mat2(c1, s1, -s1, c1); + mat2 rmX = mat2(c2, s2, -s2, c2); + for (int i = 0; i < FRACTAL_ITER; ++i) { + p.xyz = abs(p.xyz); + p.xy *= rmZ; + mengerFold(p); + p.yz *= rmX; + p *= iFracScale; + p.xyz += iFracShift; + } + return de_box(p, vec3(6.0)); +} +/* +float de_fractal(vec4 p) +{ + for (int i = 0; i < FRACTAL_ITER; ++i) { + p.xyz = abs(p.xyz); + rotZ(p, s1, c1); + mengerFold(p); + rotX(p, s2, c2); + p *= iFracScale; + p.xyz += iFracShift; + } + return de_box(p, vec3(6.0)); +}*/ + +vec4 col_fractal(vec4 p) +{ + vec3 orbit = vec3(0.0); + mat2 rmZ = mat2(c1, s1, -s1, c1); + mat2 rmX = mat2(c2, s2, -s2, c2); + for (int i = 0; i < FRACTAL_ITER; ++i) { + p.xyz = abs(p.xyz); + p.xy *= rmZ; //rotation around z + mengerFold(p); + p.yz *= rmX; //rotation around x + p *= iFracScale; + p.xyz += iFracShift; + orbit = max(orbit, p.xyz*iFracCol); + } + return vec4(orbit, de_box(p, vec3(6.0))); +} + +float de_marble(vec4 p) +{ + return de_sphere(p - vec4(iMarblePos, 0), iMarbleRad); +} + +vec4 col_marble(vec4 p) +{ + vec4 col = vec4(0.5, 0.5, 0.5, de_sphere(p - vec4(iMarblePos, 0), iMarbleRad)); + return col; +} + +float de_flag(vec4 p) +{ + vec3 f_pos = iFlagPos + vec3(1.5, 4, 0)*iFlagScale; + vec4 p_s = p/iMarbleRad; + vec4 d_pos = p - vec4(f_pos, 0); + vec4 caps_pos = p - vec4(iFlagPos + vec3(0, iFlagScale*2.4, 0), 0); + //animated flag woooo + float speed = 14; + float oscillation = sin(8*p_s.x - 1*p_s.y - speed*time) + 0.4*sin(11*p_s.x + 2*p_s.y - 1.2*speed*time) + 0.15*sin(20*p_s.x - 5*p_s.y -1.4*speed*time); + //scale the flag displacement amplitude by the distance from the flagpole + float d = 0.4*de_box(d_pos + caps_pos.x*vec4(0,(0.02+ caps_pos.x* 0.5+0.01*oscillation),0.04*oscillation,0), vec3(1.5, 0.8, 0.005)*iMarbleRad); + d = min(d, de_capsule(caps_pos, iMarbleRad*2.4, iMarbleRad*0.05)); + return d; +} + +vec4 col_flag(vec4 p) +{ + vec3 f_pos = iFlagPos + vec3(1.5, 4, 0)*iFlagScale; + vec4 d_pos = p - vec4(f_pos, 0); + vec3 fsize = vec3(1.5, 0.8, 0.08)*iMarbleRad; + vec4 caps_pos = p - vec4(iFlagPos + vec3(0, iFlagScale*2.4, 0), 0); + float d1 = de_box(d_pos, fsize); + float d2 = de_capsule(p - vec4(iFlagPos + vec3(0, iFlagScale*2.4, 0), 0), iMarbleRad*2.4, iMarbleRad*0.18); + if (d1 < d2) { + vec2 color_flag_s = vec2(imageSize(color_flag)); + vec2 texture_coord = d_pos.xy*vec2(0.5,-0.48)/fsize.xy + vec2(0.5,0.5) - 0.5*vec2(0,caps_pos.x*(0.02+ caps_pos.x* 0.5))/fsize.xy; + vec3 flagcolor = imageLoad(color_flag, ivec2(texture_coord*color_flag_s)).xyz; + return vec4(flagcolor, d1); + } else { + return vec4(0.9, 0.9, 0.1, d2); + } +} + +float de_scene(vec3 pos) +{ + vec4 p = vec4(pos,1.f); + float d = de_fractal(p); + d = min(d, de_marble(p)); + d = min(d, de_flag(p)); + return d; +} + +vec4 col_scene(vec3 pos) +{ + vec4 p = vec4(pos,1.f); + vec4 col = col_fractal(p); + vec4 col_f = col_flag(p); + if (col_f.w < col.w) { col = col_f; } + vec4 col_m = col_marble(p); + if (col_m.w < col.w) { + return vec4(col_m.xyz, 1.0); + } + return vec4(min(col.xyz,1), 0.0); +} + +void scene_material(vec3 pos, inout vec4 color, inout vec2 pbr) +{ + //DE_count = DE_count+1; + vec4 p = vec4(pos,1.f); + + color = col_fractal(p); + vec4 color_f = col_flag(p); + vec4 color_m = col_marble(p); + + pbr = vec2(PBR_METALLIC, PBR_ROUGHNESS); + float reflection = 0; + + if (color_f.w < color.w) + { + color = color_f; + pbr = vec2(0.2,0.35); + } + + if (color_m.w < color.w) + { + color = color_m; + if(MARBLE_MODE <= 1) + { + pbr = vec2(1,0.2); + } + else + { + pbr = vec2(0,0.2); + } + + reflection = 1; + } + + color = vec4(min(color.xyz,1), reflection); +} + +//A faster formula to find the gradient/normal direction of the DE +//credit to http://www.iquilezles.org/www/articles/normalsSDF/normalsSDF.htm +vec4 calcNormal(vec3 p, float dx) { + const vec3 k = vec3(1,-1,0); + return (k.xyyx*DE(p + k.xyy*dx) + + k.yyxx*DE(p + k.yyx*dx) + + k.yxyx*DE(p + k.yxy*dx) + + k.xxxx*DE(p + k.xxx*dx))/vec4(4*dx,4*dx,4*dx,4); +} + +//calculate the normal using an already evaluated distance in one point +vec3 calcNormalA(in vec3 pos, in float h) +{ + vec4 e = vec4(0.0005,-0.0005, 1., -1); + pos = pos - e.xxx; + return normalize(e.zww*DE( pos + e.xyy ) + + e.wwz*DE( pos + e.yyx ) + + e.wzw*DE( pos + e.yxy ) + + e.zzz*h ); +} \ No newline at end of file diff --git a/shaders/compute/utility/ray_marching.glsl b/shaders/compute/utility/ray_marching.glsl new file mode 100644 index 00000000..bbb914fb --- /dev/null +++ b/shaders/compute/utility/ray_marching.glsl @@ -0,0 +1,224 @@ +#include + +#define MAX_DIST 500 +#define MIN_DIST 1e-6 +#define MAX_MARCHES 256 +#define NORMARCHES 8 +#define overrelax 1.25 + +/* OLD CODE +void ray_march(inout vec4 pos, inout vec4 dir, inout vec4 var, float fov) +{ + float pDE = 0; + //March the ray + for (; var.x < MAX_MARCHES; var.x += 1.0) { + dir.w += pos.w; + pos.xyz += pos.w*dir.xyz; + pDE =pos.w; + pos.w = DE(pos.xyz); + + //if the distance from the surface is less than the distance per pixel we stop + if(dir.w > MAX_DIST || (pos.w < max(fov*dir.w, MIN_DIST) && pDE > pos.w)) + { + break; + } + } +}*/ + + +void ray_march(inout vec4 p, inout vec4 ray, inout vec4 var, float angle, float max_d) +{ + float prev_h = 0., td = 0.; + float omega = overrelax; + float candidate_td = 1.; + float candidate_error = 1e8; + for(; ((ray.w+td) < max_d) && (var.x < MAX_MARCHES); var.x+= 1.) + { + p.w = DE(p.xyz + td*ray.xyz); + + if(prev_h*omega>max(p.w,0.)+max(prev_h,0.)) //if overtepped + { + td += (1.-omega)*prev_h; // step back to the safe distance + prev_h = 0.; + omega = (omega - 1.)*0.55 + 1.; //make the overstepping smaller + } + else + { + if(p.w/td < candidate_error) + { + if(p.w < 0.) + { + candidate_error = 0.; + candidate_td = td; + break; + } + + candidate_error = p.w/td; + candidate_td = td; + + if(p.w < (ray.w+td)*angle) //if closer to the surface than the cone radius + { + break; + } + } + + td += p.w*omega; //continue marching + + prev_h = p.w; + } + } + + ray.w += candidate_td; + p.xyz = p.xyz + candidate_td*ray.xyz; + p.w = candidate_error*candidate_td; +} + + +void ray_march(inout vec4 p, inout vec4 ray, inout vec4 var, float angle) +{ + ray_march(p, ray, var, angle, MAX_DIST); +} + + +void ray_march_limited(inout vec4 pos, inout vec4 dir, inout vec4 var, float d0) +{ + ray_march(pos, dir, var, d0); + if((pos.w > 0.) && (dir.w < MAX_DIST) && (var.x < MAX_MARCHES)) + { + pos.w = DE(pos.xyz) - d0*dir.w; + for (int i = 0; i < 1; i++) + { + pos.xyz += pos.w*dir.xyz; + dir.w += pos.w; + pos.w = DE(pos.xyz) - d0*dir.w; + } + pos.w += d0*dir.w; + } + +} + +void ray_march_continue(inout vec4 pos, inout vec4 dir, inout vec4 var, float fov) +{ + dir.w += pos.w; + pos.xyz += pos.w*dir.xyz; + + if((dir.w > MAX_DIST) || (pos.w < 0.) || (var.x >= MAX_MARCHES)) + { + return; + } + + ray_march(pos, dir, var, fov); +} +#define shadow_steps 128 +float shadow_march(vec4 pos, vec4 dir, float distance2light, float light_angle) +{ + float light_visibility = 1; + float ph = 1e5; + float dDEdt = 0; + pos.w = DE(pos.xyz); + int i = 0; + for (; i < shadow_steps; i++) { + + dir.w += pos.w; + pos.xyz += pos.w*dir.xyz; + pos.w = DE(pos.xyz); + + float y = pos.w*pos.w/(2.0*ph); + float d = (pos.w+ph)*0.5*(1-dDEdt); + float angle = d/(max(MIN_DIST,dir.w-y)*light_angle); + + light_visibility = min(light_visibility, angle); + + //minimizing banding even further + dDEdt = dDEdt*0.75 + 0.25*(pos.w-ph)/ph; + + ph = pos.w; + + if(dir.w >= distance2light) + { + break; + } + + if(dir.w > MAX_DIST || pos.w < max(fovray*dir.w, MIN_DIST)) + { + return 0; + } + } + + if(i >= shadow_steps) + { + light_visibility=0.; + } + //return light_visibility; //bad + light_visibility = light_visibility*2. - 1.; + return 0.5 + (light_visibility*sqrt(1.-light_visibility*light_visibility) + asin(light_visibility))/3.14159265; //looks better and is more physically accurate(for a circular light source) +} + +float sphere_intersection(vec3 r, vec3 p, vec4 sphere) +{ + p = p - sphere.xyz; + if(p == vec3(0)) return sphere.w; + + float b = dot(p, r); + float c = sphere.w*sphere.w - dot(p,p); + float d = b*b + c; + + if((d <= 0) || (c <= 0)) //if no intersection + { + return 0; + } + else + { + return sqrt(d) - b; //use furthest solution in the direction of the ray + } +} + +float find_furthest_intersection(vec3 r, vec3 p, ivec2 id) +{ + float d = 0; + ivec2 idR = min(id+1, group_size-1); + ivec2 idL = max(id-1, 0); + for(int i = idL.x; i <= idR.x; i++) + { + for(int j = idL.y; j <= idR.y; j++) + { + d = max(d, sphere_intersection(r,p,de_sph[i][j])); + } + } + return d; +} + + +float find_furthest_intersection_all(vec3 r, vec3 p, ivec2 id) +{ + float d = 0; + for(int i = 0; i < group_size; i++) + { + for(int j = 0; j < group_size; j++) + { + d = max(d, sphere_intersection(r,p,de_sph[i][j])); + } + } + return d; +} + +void normarch(inout vec4 pos) +{ + //calculate the normal + vec4 pos0 = pos; + vec4 norm = calcNormal(pos.xyz, pos.w/8); + norm.xyz = normalize(norm.xyz); + pos.w = norm.w; + + //march in the direction of the normal + for(int i = 0; i < NORMARCHES; i++) + { + pos.xyz += pos.w*norm.xyz; + pos.w = DE(pos.xyz); + //if the normal DE sphere is further than the initial DE sphere + if(length(pos0.xyz - (pos.xyz+pos.w*norm.xyz))>pos.w+pos0.w) + { + break; + } + } +} diff --git a/shaders/compute/utility/shading.glsl b/shaders/compute/utility/shading.glsl new file mode 100644 index 00000000..3f211f15 --- /dev/null +++ b/shaders/compute/utility/shading.glsl @@ -0,0 +1,448 @@ +#include + +#define PI 3.14159265 +#define AMBIENT_MARCHES 3 +#define AMBIENT_COLOR 2*vec4(1,1,1,1) +#define LIGHT_ANGLE 0.08 + +uniform vec3 BACKGROUND_COLOR; +uniform vec3 LIGHT_DIRECTION; +uniform vec3 LIGHT_COLOR; +uniform bool SHADOWS_ENABLED; + +uniform float gamma_material; +uniform float gamma_sky; +uniform float gamma_camera; + +//better to use a sampler though +vec4 interp(layout (rgba32f) image2D text, vec2 coord) +{ + ivec2 ci = ivec2(coord)+ivec2(0,0); + vec2 d = coord - floor(coord); + //d = vec2(0,0); + //a fix for gamma ruining the interpolation + return (imageLoad(text, ci)*(1-d.x)*(1-d.y) + + imageLoad(text, ci+ivec2(1,0))*d.x*(1-d.y) + + imageLoad(text, ci+ivec2(0,1))*(1-d.x)*d.y + + imageLoad(text, ci+ivec2(1,1))*d.x*d.y); +} + +//2d interpolation that is aware of the 3d positions of our points +vec4 bilinear_surface(layout (rgba32f) image2D text, float td, float sz, vec2 coord) +{ + ivec2 ci = ivec2(coord); + vec2 d = coord - floor(coord); + + vec4 A1 = imageLoad(text, ci); + vec4 A2 = imageLoad(text, ci+ivec2(1,0)); + vec4 A3 = imageLoad(text, ci+ivec2(0,1)); + vec4 A4 = imageLoad(text, ci+ivec2(1,1)); + + float td1 = A1.w; + float td2 = A2.w; + float td3 = A3.w; + float td4 = A4.w; + + float w1 = (1-d.x)*(1-d.y)/(sz*sz+(td-td1)*(td-td1)); + float w2 = (d.x)*(1-d.y)/(sz*sz+(td-td2)*(td-td2)); + float w3 = (1-d.x)*(d.y)/(sz*sz+(td-td3)*(td-td3)); + float w4 = (d.x)*(d.y)/(sz*sz+(td-td4)*(td-td4)); + + //a fix for gamma ruining the interpolation + return pow((pow(A1,vec4(1.f/gamma_camera))*w1 + pow(A2,vec4(1.f/gamma_camera))*w2 + pow(A3,vec4(1.f/gamma_camera))*w3 + pow(A4,vec4(1.f/gamma_camera))*w4)/(w1+w2+w3+w4),vec4(gamma_camera)); + +} + + +///PBR functions +vec3 fresnelSchlick(float cosTheta, vec3 F0) +{ + return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); +} + +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float num = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return num / denom; +} + +float GeometrySchlickGGX(float NdotV, float roughness) +{ + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + + float num = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return num / denom; +} + +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +///END PBR functions + +const float Br = 0.0025; +const float Bm = 0.0003; +const float g = 0.9800; +const vec3 nitrogen = vec3(0.650, 0.570, 0.475); +const vec3 Kr = Br / pow(nitrogen, vec3(4.0)); +const vec3 Km = Bm / pow(nitrogen, vec3(0.84)); + +vec3 sky_color(in vec3 pos) +{ + // Atmosphere Scattering + vec3 fsun = LIGHT_DIRECTION; + float brightnees = exp(-sqrt(pow(min(5*(pos.y-0.1),0),2)+0.1)); + if(pos.y < 0) + { + pos.y = 0; + pos.xyz = normalize(pos.xyz); + } + float mu = dot(normalize(pos), normalize(fsun)); + + vec3 extinction = mix(exp(-exp(-((pos.y + fsun.y * 4.0) * (exp(-pos.y * 16.0) + 0.1) / 80.0) / Br) * (exp(-pos.y * 16.0) + 0.1) * Kr / Br) * exp(-pos.y * exp(-pos.y * 8.0 ) * 4.0) * exp(-pos.y * 2.0) * 4.0, vec3(1.0 - exp(fsun.y)) * 0.2, -fsun.y * 0.2 + 0.5); + vec3 sky_col = brightnees* 3.0 / (8.0 * 3.14) * (1.0 + mu * mu) * (Kr + Km * (1.0 - g * g) / (2.0 + g * g) / pow(1.0 + g * g - 2.0 * g * mu, 1.5)) / (Br + Bm) * extinction; + sky_col = 0.4*clamp(sky_col,0,10); + return pow(sky_col,vec3(1.f/gamma_sky)); +} + +vec3 ambient_sky_color(in vec3 pos) +{ + float y = pos.y; + pos.xyz = normalize(vec3(1,0,0)); + return sky_color(pos)*exp(-abs(y)); +} + +vec4 ambient_occlusion(in vec4 pos, in vec4 norm, in vec4 dir) +{ + vec3 pos0 = pos.xyz; + + float occlusion_angle = 0.; + vec3 direction = normalize(norm.xyz); + vec3 ambient_color = ambient_sky_color(norm.xyz); + //step out + pos.xyz += 0.03*dir.w*direction; + //march in the direction of the normal + for(int i = 0; i < AMBIENT_MARCHES; i++) + { + pos.xyz += pos.w*direction; + pos.w = DE(pos.xyz); + + norm.w = length(pos0 - pos.xyz); + occlusion_angle += clamp(pos.w/norm.w,0.,1.); + } + + occlusion_angle /= float(AMBIENT_MARCHES); // average weighted by importance + return vec4(ambient_color,1.)*(0.5-cos(3.14159265*occlusion_angle)*0.5); +} + +//Global illumination approximation, loicvdb's shader https://www.shadertoy.com/view/3t3GWH used as reference +#define GIStrength .3 +#define AOStrength .3 +#define AmbientLightSteps 14 +vec3 ambient_light(vec3 pos) +{ + vec3 pos0 = pos; + float dist0 = DE(pos); + vec3 normal = calcNormal(pos, MIN_DIST).xyz, gi, al = vec3(0.0); + float ao = 1., dist = dist0; + vec3 lcolor = ambient_sky_color(LIGHT_DIRECTION); + for(int i = 0; i < AmbientLightSteps; i++){ + float expectedDist = dist * (1. + .8); + dist = DE(pos); + float weight = AOStrength*(1.-float(i)/float(AmbientLightSteps)); //more weight to first samples + ao *= pow(clamp(dist/expectedDist, 0., 1.0), weight); + normal = normalize(calcNormalA(pos, dist)+1.5*normal); //"smoothed" normal to avoid artifacts + pos += normal * .8*dist; //slightly shorter to avoid artifacts + al += ambient_sky_color(normal); + if(i == 6 || i == 13) gi += ao*lcolor*shadow_march(vec4(pos, MIN_DIST), vec4(LIGHT_DIRECTION,0), 10., LIGHT_ANGLE); // two GI samples + } + gi *= GIStrength/2.0; + return gi + al/float(AmbientLightSteps) * ao; +} + + +vec3 refraction(vec3 rd, vec3 n, float p) { + float dot_nd = dot(rd, n); + return p * (rd - dot_nd * n) + sqrt(1.0 - (p * p) * (1.0 - dot_nd * dot_nd)) * n; +} + +vec3 lighting(vec4 color, vec2 pbr, vec4 pos, vec4 dir, vec4 norm, vec3 refl, vec3 refr, float shadow) +{ + vec3 albedo = color.xyz; + albedo = pow(albedo,vec3(1.f/gamma_material)); //square it to make the fractals more colorfull + + vec4 ambient_color = ambient_occlusion(pos, norm, dir); + + float metallic = pbr.x; + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + //reflectance equation + vec3 Lo = vec3(0.0); + vec3 V = -dir.xyz; + vec3 N = norm.xyz; + + { //ambient occlusion contribution + float roughness = max(pbr.y,0.5); + vec3 L = normalize(N); + vec3 H = normalize(V + L); + vec3 radiance = ambient_color.xyz; + + // cook-torrance brdf + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0); + vec3 specular = numerator / max(denominator, 0.001); + + // add to outgoing radiance Lo + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; + } + + if(!SHADOWS_ENABLED) + { + shadow = ambient_color.w; + } + + vec3 sun_color = sky_color(LIGHT_DIRECTION); + + { //light contribution + float roughness = pbr.y; + vec3 L = normalize(LIGHT_DIRECTION); + vec3 H = normalize(V + L); + vec3 radiance = sun_color*shadow*(0.8+0.2*ambient_color.w); + + // cook-torrance brdf + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0); + vec3 specular = numerator / max(denominator, 0.001); + + // add to outgoing radiance Lo + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; + } + /* + { //light reflection, GI imitation + float roughness = max(PBR_ROUGHNESS,0.5); + vec3 L = normalize(-LIGHT_DIRECTION); + vec3 H = normalize(V + L); + vec3 radiance = 0.35*sun_color*ambient_color.w*(1-ambient_color.w); + + // cook-torrance brdf + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0); + vec3 specular = numerator / max(denominator, 0.001); + + // add to outgoing radiance Lo + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; + }*/ + + if(color.w>0.5) // if marble + { + vec3 n = norm.xyz; + vec3 q = dir.xyz - n*(2*dot(dir.xyz,n)); + //Combine for final marble color + if(MARBLE_MODE == 0) + { + //glass + vec3 F0 = vec3(0.03); + vec3 L = normalize(q); + vec3 H = normalize(V + L); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + Lo += kS*refl + kD*refr; + } + else if(MARBLE_MODE > 0) + { + //metal + vec3 F0 = vec3(0.6); + vec3 L = normalize(q); + vec3 H = normalize(V + L); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + Lo += kS*refl; + } + } + + return Lo; +} + +vec3 shading_simple(in vec4 pos, in vec4 dir, float fov, float shadow) +{ + + + if(pos.w < max(16*fovray*dir.w, MIN_DIST)) + { + //calculate the normal + float error = 0.5*fov*dir.w; + vec4 norm = calcNormal(pos.xyz, max(MIN_DIST, error)); + norm.xyz = normalize(norm.xyz); + if(norm.w < -error) + { + return COL(pos.xyz).xyz; + } + else + { + //optimize color sampling + vec3 cpos = pos.xyz - pos.w*norm.xyz; + //cpos = cpos - DE(cpos)*norm.xyz; + //cpos = cpos - DE(cpos)*norm.xyz; + + vec4 color; vec2 pbr; + scene_material(cpos, color, pbr); + return lighting(color, pbr, pos, dir, norm, vec3(0), vec3(0), shadow); + } + } + else + { + return sky_color(dir.xyz); + } +} + + +vec3 render_ray(in vec4 pos, in vec4 dir, float fov) +{ + vec4 var = vec4(0,0,0,1); + ray_march(pos, dir, var, fov); + float shadow = shadow_march(pos, vec4(LIGHT_DIRECTION,0), 10., LIGHT_ANGLE); + return shading_simple(pos, dir, fov, shadow); +} + +vec3 shading(in vec4 pos, in vec4 dir, float fov, float shadow) +{ + if(pos.w < max(2*fovray*dir.w, MIN_DIST)) + { + //calculate the normal + float error = 0.5*fov*dir.w; + vec4 norm = calcNormal(pos.xyz, max(MIN_DIST, error)); + norm.xyz = normalize(norm.xyz); + if(norm.w < -error) + { + return COL(pos.xyz).xyz; + } + else + { + //optimize color sampling + vec3 cpos = pos.xyz - norm.w*norm.xyz; + // cpos = cpos - DE(cpos)*norm.xyz; + // cpos = cpos - DE(cpos)*norm.xyz; + // cpos = cpos - DE(cpos)*norm.xyz; + vec4 color; vec2 pbr; + scene_material(cpos, color, pbr); + vec3 refl = vec3(0); + vec3 refr = vec3(0); + if(color.w>0.5) // if marble + { + vec3 n = normalize(iMarblePos - cpos.xyz); + vec3 q = refraction(dir.xyz, n, 1.0 / 1.5); + vec3 p2 = pos.xyz + (dot(q, n) * 2. * iMarbleRad) * q; + n = normalize(p2 - iMarblePos); + q = (dot(q, dir.xyz) * 2.0) * q - dir.xyz; + vec4 p_temp = vec4(p2+ n*fov*dir.w*2.5, 0); + vec4 r_temp = vec4(q, dir.w); + + refr = render_ray(p_temp, r_temp, fov*1.5); + + //Calculate reflection + n = -normalize(iMarblePos - cpos.xyz); + q = dir.xyz - n*(2*dot(dir.xyz,n)); + p_temp = vec4(pos.xyz + n*fov*dir.w*2., 0); + r_temp = vec4(q, dir.w); + + refl = render_ray(p_temp, r_temp, fov*1.5); + } + + return lighting(color, pbr, vec4(cpos, pos.w), dir, norm, refl, refr, shadow); + } + } + else + { + return sky_color(dir.xyz); + } + +} + +#define NEON_iterations 3 +#define NEON_marches 4 + +vec3 NEON_shading(in vec4 pos, in vec4 dir) +{ + vec3 color = vec3(0); + for (int i = 0; i < NEON_iterations; i++) + { + for (int j = 0; j < NEON_marches; j++) + { + dir.w += pos.w; + pos.xyz += pos.w*dir.xyz; + pos.w = DE(pos.xyz); + } + //sample color at the closest point + vec4 norm = calcNormal(pos.xyz, MIN_DIST); + vec3 cpos = pos.xyz - pos.w*norm.xyz; + + color += COL(cpos).xyz/(1+pos.w); + } + return color/NEON_iterations; +} + +vec3 ACESFilm(vec3 x) +{ + float a = 2.51; + float b = 0.03; + float c = 2.43; + float d = 0.59; + float e = 0.14; + return (x*(a*x+b))/(x*(c*x+d)+e); +} + +vec3 HDRmapping(vec3 color, float exposure) +{ + // Exposure tone mapping + vec3 mapped = ACESFilm(color * exposure); + // Gamma correction + return pow(mapped, vec3(1.0 / gamma_camera)); +} \ No newline at end of file diff --git a/shaders/textures/1.png b/shaders/textures/1.png new file mode 100644 index 0000000000000000000000000000000000000000..f601583aa5b639b0815452f3f4ca87dec1444203 GIT binary patch literal 153006 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

HOoD&)XBvow5eox5Aaj?%~v-Sd=|h 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ⅆ8cbtfxEAI*e*AVD+&qx)FZ)r`Mx*Jius$@#Irn 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

k`?S1FBI+KdCZ>Lhd=yb-40fo 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 Ef|Ucd1ONa4 literal 0 HcmV?d00001 diff --git a/shaders/textures/2.png b/shaders/textures/2.png new file mode 100644 index 0000000000000000000000000000000000000000..40df55ab938fa29c8b08eab0ec1a847a987b85de GIT binary patch literal 5757 zcmeI0TTl~M7{`|u1!N*#YMBxswiYRUa65GdG%>+=1=|w5l|f4)qd<{J43LBX0gWxz z3udg>Rv}PJp#n)D0x6e7i@-1uB7$U*grFD~Sz@@jgi9_>#J4`#nZE7AIlJdS-_Fi_ z^L@YnIp<7t)K1(Iza;*54ZF^JGTImF8`O#g?ke9 z8!7-)i@dGzi=1n(;}Nmx0PtauYq&-3`E=a*vLbRDbzdgk)E_r8!i&2*p_0kAXnJ=a zCaK9#5n;n0QDy4n;L@~_GeI|)yRS~KPVBgk?;&PgJbCOu<>QE(rOZ>yKln06uKTw0 zLGUg}w}V<2p;DrA-ZAb7hd(jttb<~0EAqn9Y`qKHj28W0qqi&i=rMG@kqF;R z2TnNFP#2w8xjEWx$bH#9V1t|cDj@1ap&C@>2;|qAhR&jO-i*fF7rm#L5REZ?o6}N~ zqD8d~O@17&lY@-<(mUJYvb)dq;c4NAZGZn+Rudm1X1B4o&f!RKA#ZRlQIpqIiaae- zW(y{MXB=*!@W!vAF?pGqtf7-0kW6Hlo!}t2`Wm+7yNOE(K|K8cy&oA|9bZow{-_=I zGHh(jHr})zq%#Ki1iVEWKG}^z?G$++|M~LJF}X#+)z9XW`W33i$pWOqOypM;2851X z5X^JYG>}@bqIWU%*fQr7uqztxUQ2aOoX-{%r(Ck2IOWq=AeNqmTEU6}>zQ{Wh0<6Y zxB+>F&R$|A4pRi3CgfhWBS$dV?a?n22_``;OJ$@%if{o6R<&zvgQzhn{0gqoSeaxR zHPYMNQDHh5%gUNHSF>5U^PNZxg_GHgiVYq4HY-e#N$gdij4jPGvn0Gg<&kDst2xw? zs<1zZYt|vxi;Fn-N|DQ9dDjaD9F3>7ix`{kth3c$lgGokFMYK=X6xtpdWUjA8{`O+hQ35NP0*h2#ZDdo4 zNMfTkJyWbtBy}~I9y$N|RrD>4oS3m-cIw(mV1Ds``9(epEH^986=b)a_K|ukGmZz$ zh@AM^E>flnG$xUpouo@2n6s<$T8ZYTzOs0DFr!~Wf5l-&gSL~k>Drinh1S|hsH6#O zzoBBsQ~(pw+UH1Gm6`No!TkLWSjrlb)#XELaJtZu%58%@xVUV+|q##*uc zVb+YQi;-fICHMr^w)6=S;qxe-1RgX){2)A6uk>{RT<8~6zFhe0>T;Zrc)56o=TTvC zsOM<3(C_1NFX5Bb;8b&RYDm!G|KK>JhC=2sM@Th~>HHYXXC{(Z*pyC1#RhVYBD0QGKtU*=tT5 zPUV{qY7LYOQ`YP57mKoGKoCxj^{q{NY%TL>NPs0 z*)*kK0Zg^3X{Hs?3_9!_i=HQsw-_8n!>X#95S1!7wXi{%c5`Lj5kmlP>@8MtE`GjA zR;a6J-eC2OvVc{WvVc`A5KGTnuf>W2>zQ{TMb1GgdGd0ZjP1y1U4<0gNIk&QbA0jB zXK4QPofrHILvC=9i(!>}MVqRN(w=+b>&$Bi{R>p%CyASvnhcsY8#D_`2}Hlg6_SRt zI8x^LBxmGd_b)Zc;KqzYg`AQ7DUOn@Oi0d{bDf@@XZH611My$iu69FLtiyZr=8%T0 TQt~C|l`#;xJ!+d|%OT-Ebk)$& literal 0 HcmV?d00001 diff --git a/shaders/textures/readme.txt b/shaders/textures/readme.txt new file mode 100644 index 00000000..d7a038d6 --- /dev/null +++ b/shaders/textures/readme.txt @@ -0,0 +1,2 @@ +Add textures here, they can be used in compute shaders. +Only .png is supported \ No newline at end of file diff --git a/src/Camera.cpp b/src/Camera.cpp index 84be2659..a03c9c1f 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -102,7 +102,7 @@ void Camera::SetDirZ(vec3 dir) void Camera::UpdateExposure(float illumination) { - exposure += auto_exposure_speed*(auto_exposure_target - illumination)*exposure; + exposure = exp(clamp(log(exposure + auto_exposure_speed*(auto_exposure_target - illumination)*exposure), -auto_exposure_range * 0.5f, auto_exposure_range * 0.5f)); } vec3 Camera::GetPosition() diff --git a/src/Camera.h b/src/Camera.h index 35a9293a..921dd086 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -37,9 +37,10 @@ class Camera FirstPerson }; - Camera() : alpha(0), beta(0), gamma(0), cur_mode(Free), radius(1.f), auto_exposure_speed(0.5), + Camera() : alpha(0), beta(0), gamma(0), cur_mode(Camera::Free), radius(1.f), auto_exposure_speed(0.5), smooth(0.3f), FOV(75.f), focus(1e10), bokeh(0), mblur(0.008), speckle(10), size(0), - exposure(0.7f), bloomintensity(0.05), bloomradius(3), iFrame(0) + exposure(0.7f), bloomintensity(0.05), bloomradius(3), iFrame(0), auto_exposure_range(4.), + aspect_ratio(1.), auto_exposure_target(1.), cross_eye(false), eye_separation(0.01), radv(1.f) { //camera directions dirx = quat(0, 1, 0, 0); @@ -98,6 +99,7 @@ class Camera float auto_exposure_speed; float auto_exposure_target; + float auto_exposure_range; private: CameraMode cur_mode; diff --git a/src/Gamemodes.cpp b/src/Gamemodes.cpp index cf2ba23d..6dcf21fc 100644 --- a/src/Gamemodes.cpp +++ b/src/Gamemodes.cpp @@ -520,6 +520,7 @@ void OpenScreenSaver(Scene * scene, Overlays * overlays) void PlayNewGame(Scene * scene, sf::RenderWindow * window, int level) { + SetCameraFocus(1e10); StopReplay(); RemoveAllObjects(); game_mode = PLAYING; diff --git a/src/Settings.h b/src/Settings.h index 2a1b8bfd..a7753b2d 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -97,8 +97,8 @@ static const std::array default_control_mapping = //an incomprehensible wall of default parameters static const MainSettings default_settings = { - 6, 10, 6, 3, 3, 0, true, true, true, 0.09, 9, 2.2, 70, 20, 20, 0.005, 0.2, false, - 0.005, 0.45, 0, false, true, 0, true, 0.5, 0.7, 2.2, false, -0.02, 0.2, 0.55, + 6, 10, 6, 3, 5, 0, true, true, true, 0.08, 9, 2.2, 70, 20, 20, 0.005, 0.2, false, + 0.005, 0.45, 0, false, true, 0, true, 0.5, 0.75, 2.2, false, -0.02, 0.2, 0.55, false, default_control_mapping, true, 60, true, 1.f, 0.1f, 15.f, 4.5f };