| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | #[compute] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #version 450 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-13 17:01:43 -03:00
										 |  |  | #VERSION_DEFINES | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 14:14:01 +02:00
										 |  |  | #ifdef SAMPLE_VOXEL_GI_NEAREST | 
					
						
							|  |  |  | #extension GL_EXT_samplerless_texture_functions : enable | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define M_PI 3.141592 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | /* Specialization Constants (Toggles) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | layout(constant_id = 0) const bool sc_half_res = false; | 
					
						
							|  |  |  | layout(constant_id = 1) const bool sc_use_full_projection_matrix = false; | 
					
						
							|  |  |  | layout(constant_id = 2) const bool sc_use_vrs = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | #define SDFGI_MAX_CASCADES 8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //set 0 for SDFGI and render buffers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | layout(set = 0, binding = 1) uniform texture3D sdf_cascades[SDFGI_MAX_CASCADES]; | 
					
						
							|  |  |  | layout(set = 0, binding = 2) uniform texture3D light_cascades[SDFGI_MAX_CASCADES]; | 
					
						
							|  |  |  | layout(set = 0, binding = 3) uniform texture3D aniso0_cascades[SDFGI_MAX_CASCADES]; | 
					
						
							|  |  |  | layout(set = 0, binding = 4) uniform texture3D aniso1_cascades[SDFGI_MAX_CASCADES]; | 
					
						
							|  |  |  | layout(set = 0, binding = 5) uniform texture3D occlusion_texture; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | layout(set = 0, binding = 6) uniform sampler linear_sampler; | 
					
						
							|  |  |  | layout(set = 0, binding = 7) uniform sampler linear_sampler_with_mipmaps; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct ProbeCascadeData { | 
					
						
							|  |  |  | 	vec3 position; | 
					
						
							|  |  |  | 	float to_probe; | 
					
						
							|  |  |  | 	ivec3 probe_world_offset; | 
					
						
							|  |  |  | 	float to_cell; // 1/bounds * grid_size | 
					
						
							| 
									
										
										
										
											2022-07-31 16:20:24 -07:00
										 |  |  | 	vec3 pad; | 
					
						
							|  |  |  | 	float exposure_normalization; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image2D ambient_buffer; | 
					
						
							|  |  |  | layout(rgba16f, set = 0, binding = 10) uniform restrict writeonly image2D reflection_buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | layout(set = 0, binding = 11) uniform texture2DArray lightprobe_texture; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | layout(set = 0, binding = 12) uniform texture2D depth_buffer; | 
					
						
							|  |  |  | layout(set = 0, binding = 13) uniform texture2D normal_roughness_buffer; | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | layout(set = 0, binding = 14) uniform utexture2D voxel_gi_buffer; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | layout(set = 0, binding = 15, std140) uniform SDFGI { | 
					
						
							|  |  |  | 	vec3 grid_size; | 
					
						
							|  |  |  | 	uint max_cascades; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool use_occlusion; | 
					
						
							|  |  |  | 	int probe_axis_size; | 
					
						
							|  |  |  | 	float probe_to_uvw; | 
					
						
							|  |  |  | 	float normal_bias; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec3 lightprobe_tex_pixel_size; | 
					
						
							|  |  |  | 	float energy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec3 lightprobe_uv_offset; | 
					
						
							|  |  |  | 	float y_mult; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec3 occlusion_clamp; | 
					
						
							|  |  |  | 	uint pad3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec3 occlusion_renormalize; | 
					
						
							|  |  |  | 	uint pad4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec3 cascade_probe_size; | 
					
						
							|  |  |  | 	uint pad5; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ProbeCascadeData cascades[SDFGI_MAX_CASCADES]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | sdfgi; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | #define MAX_VOXEL_GI_INSTANCES 8 | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | struct VoxelGIData { | 
					
						
							| 
									
										
										
										
											2021-11-28 23:09:30 +01:00
										 |  |  | 	mat4 xform; // 64 - 64 | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-28 23:09:30 +01:00
										 |  |  | 	vec3 bounds; // 12 - 76 | 
					
						
							|  |  |  | 	float dynamic_range; // 4 - 80 | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-28 23:09:30 +01:00
										 |  |  | 	float bias; // 4 - 84 | 
					
						
							|  |  |  | 	float normal_bias; // 4 - 88 | 
					
						
							|  |  |  | 	bool blend_ambient; // 4 - 92 | 
					
						
							|  |  |  | 	uint mipmaps; // 4 - 96 | 
					
						
							| 
									
										
										
										
											2022-07-31 16:20:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	vec3 pad; // 12 - 108 | 
					
						
							|  |  |  | 	float exposure_normalization; // 4 - 112 | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | layout(set = 0, binding = 16, std140) uniform VoxelGIs { | 
					
						
							|  |  |  | 	VoxelGIData data[MAX_VOXEL_GI_INSTANCES]; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | voxel_gi_instances; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | layout(set = 0, binding = 17) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-20 12:52:19 +10:00
										 |  |  | layout(set = 0, binding = 18, std140) uniform SceneData { | 
					
						
							|  |  |  | 	mat4x4 inv_projection[2]; | 
					
						
							|  |  |  | 	mat4x4 cam_transform; | 
					
						
							|  |  |  | 	vec4 eye_offset[2]; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-20 12:52:19 +10:00
										 |  |  | 	ivec2 screen_size; | 
					
						
							|  |  |  | 	float pad1; | 
					
						
							|  |  |  | 	float pad2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | scene_data; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-15 12:34:19 -08:00
										 |  |  | #ifdef USE_VRS | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | layout(r8ui, set = 0, binding = 19) uniform restrict readonly uimage2D vrs_buffer; | 
					
						
							| 
									
										
										
										
											2022-12-15 12:34:19 -08:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-20 12:52:19 +10:00
										 |  |  | layout(push_constant, std430) uniform Params { | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 	uint max_voxel_gi_instances; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 	bool high_quality_vct; | 
					
						
							|  |  |  | 	bool orthogonal; | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 	uint view_index; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-20 12:52:19 +10:00
										 |  |  | 	vec4 proj_info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float z_near; | 
					
						
							|  |  |  | 	float z_far; | 
					
						
							|  |  |  | 	float pad2; | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 	float pad3; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | } | 
					
						
							|  |  |  | params; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | vec2 octahedron_wrap(vec2 v) { | 
					
						
							|  |  |  | 	vec2 signVal; | 
					
						
							|  |  |  | 	signVal.x = v.x >= 0.0 ? 1.0 : -1.0; | 
					
						
							|  |  |  | 	signVal.y = v.y >= 0.0 ? 1.0 : -1.0; | 
					
						
							|  |  |  | 	return (1.0 - abs(v.yx)) * signVal; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | vec2 octahedron_encode(vec3 n) { | 
					
						
							|  |  |  | 	// https://twitter.com/Stubbesaurus/status/937994790553227264 | 
					
						
							|  |  |  | 	n /= (abs(n.x) + abs(n.y) + abs(n.z)); | 
					
						
							|  |  |  | 	n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy); | 
					
						
							|  |  |  | 	n.xy = n.xy * 0.5 + 0.5; | 
					
						
							|  |  |  | 	return n.xy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | vec4 blend_color(vec4 src, vec4 dst) { | 
					
						
							|  |  |  | 	vec4 res; | 
					
						
							|  |  |  | 	float sa = 1.0 - src.a; | 
					
						
							|  |  |  | 	res.a = dst.a * sa + src.a; | 
					
						
							|  |  |  | 	if (res.a == 0.0) { | 
					
						
							|  |  |  | 		res.rgb = vec3(0); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		res.rgb = (dst.rgb * dst.a * sa + src.rgb * src.a) / res.a; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | vec3 reconstruct_position(ivec2 screen_pos) { | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 	if (sc_use_full_projection_matrix) { | 
					
						
							|  |  |  | 		vec4 pos; | 
					
						
							|  |  |  | 		pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0; | 
					
						
							|  |  |  | 		pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0; | 
					
						
							|  |  |  | 		pos.w = 1.0; | 
					
						
							| 
									
										
										
										
											2022-05-20 12:52:19 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 		pos = scene_data.inv_projection[params.view_index] * pos; | 
					
						
							| 
									
										
										
										
											2022-05-20 12:52:19 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 		return pos.xyz / pos.w; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 		vec3 pos; | 
					
						
							|  |  |  | 		pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		pos.z = pos.z * 2.0 - 1.0; | 
					
						
							|  |  |  | 		if (params.orthogonal) { | 
					
						
							| 
									
										
										
										
											2024-02-14 21:39:39 +08:00
										 |  |  | 			pos.z = -(pos.z * (params.z_far - params.z_near) - (params.z_far + params.z_near)) / 2.0; | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2024-02-14 21:39:39 +08:00
										 |  |  | 			pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near + pos.z * (params.z_far - params.z_near)); | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		pos.z = -pos.z; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 		pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw; | 
					
						
							|  |  |  | 		if (!params.orthogonal) { | 
					
						
							|  |  |  | 			pos.xy *= pos.z; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 		return pos; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) { | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 	cascade_pos += cam_normal * sdfgi.normal_bias; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec3 base_pos = floor(cascade_pos); | 
					
						
							|  |  |  | 	//cascade_pos += mix(vec3(0.0),vec3(0.01),lessThan(abs(cascade_pos-base_pos),vec3(0.01))) * cam_normal; | 
					
						
							|  |  |  | 	ivec3 probe_base_pos = ivec3(base_pos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec4 diffuse_accum = vec4(0.0); | 
					
						
							|  |  |  | 	vec3 specular_accum; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ivec3 tex_pos = ivec3(probe_base_pos.xy, int(cascade)); | 
					
						
							|  |  |  | 	tex_pos.x += probe_base_pos.z * sdfgi.probe_axis_size; | 
					
						
							|  |  |  | 	tex_pos.xy = tex_pos.xy * (SDFGI_OCT_SIZE + 2) + ivec2(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec3 diffuse_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec3 specular_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_specular_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	specular_accum = vec3(0.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec4 light_accum = vec4(0.0); | 
					
						
							|  |  |  | 	float weight_accum = 0.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (uint j = 0; j < 8; j++) { | 
					
						
							|  |  |  | 		ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1); | 
					
						
							|  |  |  | 		ivec3 probe_posi = probe_base_pos; | 
					
						
							|  |  |  | 		probe_posi += offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Compute weight | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		vec3 probe_pos = vec3(probe_posi); | 
					
						
							|  |  |  | 		vec3 probe_to_pos = cascade_pos - probe_pos; | 
					
						
							|  |  |  | 		vec3 probe_dir = normalize(-probe_to_pos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		vec3 trilinear = vec3(1.0) - abs(probe_to_pos); | 
					
						
							|  |  |  | 		float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(cam_normal, probe_dir)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Compute lightprobe occlusion | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (sdfgi.use_occlusion) { | 
					
						
							|  |  |  | 			ivec3 occ_indexv = abs((sdfgi.cascades[cascade].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4); | 
					
						
							|  |  |  | 			vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			vec3 occ_pos = clamp(cascade_pos, probe_pos - sdfgi.occlusion_clamp, probe_pos + sdfgi.occlusion_clamp) * sdfgi.probe_to_uvw; | 
					
						
							|  |  |  | 			occ_pos.z += float(cascade); | 
					
						
							|  |  |  | 			if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures | 
					
						
							|  |  |  | 				occ_pos.x += 1.0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			occ_pos *= sdfgi.occlusion_renormalize; | 
					
						
							|  |  |  | 			float occlusion = dot(textureLod(sampler3D(occlusion_texture, linear_sampler), occ_pos, 0.0), occ_mask); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			weight *= max(occlusion, 0.01); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Compute lightprobe texture position | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		vec3 diffuse; | 
					
						
							|  |  |  | 		vec3 pos_uvw = diffuse_posf; | 
					
						
							|  |  |  | 		pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy; | 
					
						
							|  |  |  | 		pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z; | 
					
						
							|  |  |  | 		diffuse = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-31 16:20:24 -07:00
										 |  |  | 		diffuse_accum += vec4(diffuse * weight * sdfgi.cascades[cascade].exposure_normalization, weight); | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			vec3 specular = vec3(0.0); | 
					
						
							|  |  |  | 			vec3 pos_uvw = specular_posf; | 
					
						
							|  |  |  | 			pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy; | 
					
						
							|  |  |  | 			pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z; | 
					
						
							|  |  |  | 			if (roughness < 0.99) { | 
					
						
							|  |  |  | 				specular = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw + vec3(0, 0, float(sdfgi.max_cascades)), 0.0).rgb; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (roughness > 0.2) { | 
					
						
							|  |  |  | 				specular = mix(specular, textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb, (roughness - 0.2) * 1.25); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-31 16:20:24 -07:00
										 |  |  | 			specular_accum += specular * weight * sdfgi.cascades[cascade].exposure_normalization; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (diffuse_accum.a > 0.0) { | 
					
						
							|  |  |  | 		diffuse_accum.rgb /= diffuse_accum.a; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	diffuse_light = diffuse_accum.rgb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (diffuse_accum.a > 0.0) { | 
					
						
							|  |  |  | 		specular_accum /= diffuse_accum.a; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	specular_light = specular_accum; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, out vec4 ambient_light, out vec4 reflection_light) { | 
					
						
							|  |  |  | 	//make vertex orientation the world one, but still align to camera | 
					
						
							|  |  |  | 	vertex.y *= sdfgi.y_mult; | 
					
						
							|  |  |  | 	normal.y *= sdfgi.y_mult; | 
					
						
							|  |  |  | 	reflection.y *= sdfgi.y_mult; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//renormalize | 
					
						
							|  |  |  | 	normal = normalize(normal); | 
					
						
							|  |  |  | 	reflection = normalize(reflection); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec3 cam_pos = vertex; | 
					
						
							|  |  |  | 	vec3 cam_normal = normal; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec4 light_accum = vec4(0.0); | 
					
						
							|  |  |  | 	float weight_accum = 0.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec4 light_blend_accum = vec4(0.0); | 
					
						
							|  |  |  | 	float weight_blend_accum = 0.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float blend = -1.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// helper constants, compute once | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uint cascade = 0xFFFFFFFF; | 
					
						
							|  |  |  | 	vec3 cascade_pos; | 
					
						
							|  |  |  | 	vec3 cascade_normal; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (uint i = 0; i < sdfgi.max_cascades; i++) { | 
					
						
							|  |  |  | 		cascade_pos = (cam_pos - sdfgi.cascades[i].position) * sdfgi.cascades[i].to_probe; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (any(lessThan(cascade_pos, vec3(0.0))) || any(greaterThanEqual(cascade_pos, sdfgi.cascade_probe_size))) { | 
					
						
							|  |  |  | 			continue; //skip cascade | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cascade = i; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cascade < SDFGI_MAX_CASCADES) { | 
					
						
							|  |  |  | 		ambient_light = vec4(0, 0, 0, 1); | 
					
						
							|  |  |  | 		reflection_light = vec4(0, 0, 0, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		float blend; | 
					
						
							|  |  |  | 		vec3 diffuse, specular; | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 		sdfvoxel_gi_process(cascade, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse, specular); | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			//process blend | 
					
						
							|  |  |  | 			float blend_from = (float(sdfgi.probe_axis_size - 1) / 2.0) - 2.5; | 
					
						
							|  |  |  | 			float blend_to = blend_from + 2.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			vec3 inner_pos = cam_pos * sdfgi.cascades[cascade].to_probe; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			float len = length(inner_pos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			inner_pos = abs(normalize(inner_pos)); | 
					
						
							|  |  |  | 			len *= max(inner_pos.x, max(inner_pos.y, inner_pos.z)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (len >= blend_from) { | 
					
						
							|  |  |  | 				blend = smoothstep(blend_from, blend_to, len); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				blend = 0.0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (blend > 0.0) { | 
					
						
							|  |  |  | 			//blend | 
					
						
							|  |  |  | 			if (cascade == sdfgi.max_cascades - 1) { | 
					
						
							|  |  |  | 				ambient_light.a = 1.0 - blend; | 
					
						
							|  |  |  | 				reflection_light.a = 1.0 - blend; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				vec3 diffuse2, specular2; | 
					
						
							|  |  |  | 				cascade_pos = (cam_pos - sdfgi.cascades[cascade + 1].position) * sdfgi.cascades[cascade + 1].to_probe; | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 				sdfvoxel_gi_process(cascade + 1, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse2, specular2); | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 				diffuse = mix(diffuse, diffuse2, blend); | 
					
						
							|  |  |  | 				specular = mix(specular, specular2, blend); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ambient_light.rgb = diffuse; | 
					
						
							| 
									
										
										
										
											2021-01-17 13:25:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 		if (roughness < 0.2) { | 
					
						
							|  |  |  | 			vec3 pos_to_uvw = 1.0 / sdfgi.grid_size; | 
					
						
							|  |  |  | 			vec4 light_accum = vec4(0.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			float blend_size = (sdfgi.grid_size.x / float(sdfgi.probe_axis_size - 1)) * 0.5; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			float radius_sizes[SDFGI_MAX_CASCADES]; | 
					
						
							|  |  |  | 			cascade = 0xFFFF; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			float base_distance = length(cam_pos); | 
					
						
							|  |  |  | 			for (uint i = 0; i < sdfgi.max_cascades; i++) { | 
					
						
							|  |  |  | 				radius_sizes[i] = (1.0 / sdfgi.cascades[i].to_cell) * (sdfgi.grid_size.x * 0.5 - blend_size); | 
					
						
							|  |  |  | 				if (cascade == 0xFFFF && base_distance < radius_sizes[i]) { | 
					
						
							|  |  |  | 					cascade = i; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			cascade = min(cascade, sdfgi.max_cascades - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			float max_distance = radius_sizes[sdfgi.max_cascades - 1]; | 
					
						
							|  |  |  | 			vec3 ray_pos = cam_pos; | 
					
						
							|  |  |  | 			vec3 ray_dir = reflection; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				float prev_radius = cascade > 0 ? radius_sizes[cascade - 1] : 0.0; | 
					
						
							|  |  |  | 				float base_blend = (base_distance - prev_radius) / (radius_sizes[cascade] - prev_radius); | 
					
						
							|  |  |  | 				float bias = (1.0 + base_blend) * 1.1; | 
					
						
							|  |  |  | 				vec3 abs_ray_dir = abs(ray_dir); | 
					
						
							|  |  |  | 				//ray_pos += ray_dir * (bias / sdfgi.cascades[cascade].to_cell); //bias to avoid self occlusion | 
					
						
							|  |  |  | 				ray_pos += (ray_dir * 1.0 / max(abs_ray_dir.x, max(abs_ray_dir.y, abs_ray_dir.z)) + cam_normal * 1.4) * bias / sdfgi.cascades[cascade].to_cell; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			float softness = 0.2 + min(1.0, roughness * 5.0) * 4.0; //approximation to roughness so it does not seem like a hard fade | 
					
						
							| 
									
										
										
										
											2021-02-06 22:49:33 -03:00
										 |  |  | 			uint i = 0; | 
					
						
							|  |  |  | 			bool found = false; | 
					
						
							|  |  |  | 			while (true) { | 
					
						
							|  |  |  | 				if (length(ray_pos) >= max_distance || light_accum.a > 0.99) { | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (!found && i >= cascade && length(ray_pos) < radius_sizes[i]) { | 
					
						
							|  |  |  | 					uint next_i = min(i + 1, sdfgi.max_cascades - 1); | 
					
						
							|  |  |  | 					cascade = max(i, cascade); //never go down | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 22:49:33 -03:00
										 |  |  | 					vec3 pos = ray_pos - sdfgi.cascades[i].position; | 
					
						
							|  |  |  | 					pos *= sdfgi.cascades[i].to_cell * pos_to_uvw; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 22:49:33 -03:00
										 |  |  | 					float fdistance = textureLod(sampler3D(sdf_cascades[i], linear_sampler), pos, 0.0).r * 255.0 - 1.1; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 22:49:33 -03:00
										 |  |  | 					vec4 hit_light = vec4(0.0); | 
					
						
							|  |  |  | 					if (fdistance < softness) { | 
					
						
							|  |  |  | 						hit_light.rgb = textureLod(sampler3D(light_cascades[i], linear_sampler), pos, 0.0).rgb; | 
					
						
							|  |  |  | 						hit_light.rgb *= 0.5; //approximation given value read is actually meant for anisotropy | 
					
						
							|  |  |  | 						hit_light.a = clamp(1.0 - (fdistance / softness), 0.0, 1.0); | 
					
						
							|  |  |  | 						hit_light.rgb *= hit_light.a; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 22:49:33 -03:00
										 |  |  | 					fdistance /= sdfgi.cascades[i].to_cell; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 22:49:33 -03:00
										 |  |  | 					if (i < (sdfgi.max_cascades - 1)) { | 
					
						
							|  |  |  | 						pos = ray_pos - sdfgi.cascades[next_i].position; | 
					
						
							|  |  |  | 						pos *= sdfgi.cascades[next_i].to_cell * pos_to_uvw; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 22:49:33 -03:00
										 |  |  | 						float fdistance2 = textureLod(sampler3D(sdf_cascades[next_i], linear_sampler), pos, 0.0).r * 255.0 - 1.1; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 22:49:33 -03:00
										 |  |  | 						vec4 hit_light2 = vec4(0.0); | 
					
						
							|  |  |  | 						if (fdistance2 < softness) { | 
					
						
							|  |  |  | 							hit_light2.rgb = textureLod(sampler3D(light_cascades[next_i], linear_sampler), pos, 0.0).rgb; | 
					
						
							|  |  |  | 							hit_light2.rgb *= 0.5; //approximation given value read is actually meant for anisotropy | 
					
						
							|  |  |  | 							hit_light2.a = clamp(1.0 - (fdistance2 / softness), 0.0, 1.0); | 
					
						
							|  |  |  | 							hit_light2.rgb *= hit_light2.a; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 22:49:33 -03:00
										 |  |  | 						float prev_radius = i == 0 ? 0.0 : radius_sizes[max(0, i - 1)]; | 
					
						
							|  |  |  | 						float blend = clamp((length(ray_pos) - prev_radius) / (radius_sizes[i] - prev_radius), 0.0, 1.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						fdistance2 /= sdfgi.cascades[next_i].to_cell; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						hit_light = mix(hit_light, hit_light2, blend); | 
					
						
							|  |  |  | 						fdistance = mix(fdistance, fdistance2, blend); | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 22:49:33 -03:00
										 |  |  | 					light_accum += hit_light; | 
					
						
							|  |  |  | 					ray_pos += ray_dir * fdistance; | 
					
						
							|  |  |  | 					found = true; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				i++; | 
					
						
							|  |  |  | 				if (i == sdfgi.max_cascades) { | 
					
						
							|  |  |  | 					i = 0; | 
					
						
							|  |  |  | 					found = false; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			vec3 light = light_accum.rgb / max(light_accum.a, 0.00001); | 
					
						
							|  |  |  | 			float alpha = min(1.0, light_accum.a); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			float b = min(1.0, roughness * 5.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			float sa = 1.0 - b; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			reflection_light.a = alpha * sa + b; | 
					
						
							|  |  |  | 			if (reflection_light.a == 0) { | 
					
						
							|  |  |  | 				specular = vec3(0.0); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				specular = (light * alpha * sa + specular * b) / reflection_light.a; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		reflection_light.rgb = specular; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ambient_light.rgb *= sdfgi.energy; | 
					
						
							|  |  |  | 		reflection_light.rgb *= sdfgi.energy; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ambient_light = vec4(0); | 
					
						
							|  |  |  | 		reflection_light = vec4(0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //standard voxel cone trace | 
					
						
							|  |  |  | vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { | 
					
						
							|  |  |  | 	float dist = p_bias; | 
					
						
							|  |  |  | 	vec4 color = vec4(0.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (dist < max_distance && color.a < 0.95) { | 
					
						
							|  |  |  | 		float diameter = max(1.0, 2.0 * tan_half_angle * dist); | 
					
						
							|  |  |  | 		vec3 uvw_pos = (pos + dist * direction) * cell_size; | 
					
						
							|  |  |  | 		float half_diameter = diameter * 0.5; | 
					
						
							|  |  |  | 		//check if outside, then break | 
					
						
							|  |  |  | 		if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + half_diameter * cell_size)))) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		vec4 scolor = textureLod(sampler3D(probe, linear_sampler_with_mipmaps), uvw_pos, log2(diameter)); | 
					
						
							|  |  |  | 		float a = (1.0 - color.a); | 
					
						
							|  |  |  | 		color += a * scolor; | 
					
						
							|  |  |  | 		dist += half_diameter; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return color; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float max_distance, float p_bias) { | 
					
						
							|  |  |  | 	float dist = p_bias; | 
					
						
							|  |  |  | 	vec4 color = vec4(0.0); | 
					
						
							|  |  |  | 	float radius = max(0.5, dist); | 
					
						
							|  |  |  | 	float lod_level = log2(radius * 2.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (dist < max_distance && color.a < 0.95) { | 
					
						
							|  |  |  | 		vec3 uvw_pos = (pos + dist * direction) * cell_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//check if outside, then break | 
					
						
							|  |  |  | 		if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + radius * cell_size)))) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		vec4 scolor = textureLod(sampler3D(probe, linear_sampler_with_mipmaps), uvw_pos, lod_level); | 
					
						
							|  |  |  | 		lod_level += 1.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		float a = (1.0 - color.a); | 
					
						
							|  |  |  | 		scolor *= a; | 
					
						
							|  |  |  | 		color += scolor; | 
					
						
							|  |  |  | 		dist += radius; | 
					
						
							|  |  |  | 		radius = max(0.5, dist); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return color; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, inout vec4 out_spec, inout vec4 out_diff, inout float out_blend) { | 
					
						
							|  |  |  | 	position = (voxel_gi_instances.data[index].xform * vec4(position, 1.0)).xyz; | 
					
						
							|  |  |  | 	ref_vec = normalize((voxel_gi_instances.data[index].xform * vec4(ref_vec, 0.0)).xyz); | 
					
						
							|  |  |  | 	normal = normalize((voxel_gi_instances.data[index].xform * vec4(normal, 0.0)).xyz); | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 	position += normal * voxel_gi_instances.data[index].normal_bias; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	//this causes corrupted pixels, i have no idea why.. | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 	if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, voxel_gi_instances.data[index].bounds))))) { | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 	mat3 dir_xform = mat3(voxel_gi_instances.data[index].xform) * normal_xform; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 	vec3 blendv = abs(position / voxel_gi_instances.data[index].bounds * 2.0 - 1.0); | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 	float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0); | 
					
						
							|  |  |  | 	//float blend=1.0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 	float max_distance = length(voxel_gi_instances.data[index].bounds); | 
					
						
							|  |  |  | 	vec3 cell_size = 1.0 / voxel_gi_instances.data[index].bounds; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	//irradiance | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec4 light = vec4(0.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (params.high_quality_vct) { | 
					
						
							|  |  |  | 		const uint cone_dir_count = 6; | 
					
						
							|  |  |  | 		vec3 cone_dirs[cone_dir_count] = vec3[]( | 
					
						
							|  |  |  | 				vec3(0.0, 0.0, 1.0), | 
					
						
							|  |  |  | 				vec3(0.866025, 0.0, 0.5), | 
					
						
							|  |  |  | 				vec3(0.267617, 0.823639, 0.5), | 
					
						
							|  |  |  | 				vec3(-0.700629, 0.509037, 0.5), | 
					
						
							|  |  |  | 				vec3(-0.700629, -0.509037, 0.5), | 
					
						
							|  |  |  | 				vec3(0.267617, -0.823639, 0.5)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		float cone_weights[cone_dir_count] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); | 
					
						
							|  |  |  | 		float cone_angle_tan = 0.577; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (uint i = 0; i < cone_dir_count; i++) { | 
					
						
							|  |  |  | 			vec3 dir = normalize(dir_xform * cone_dirs[i]); | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 			light += cone_weights[i] * voxel_cone_trace(voxel_gi_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, voxel_gi_instances.data[index].bias); | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		const uint cone_dir_count = 4; | 
					
						
							|  |  |  | 		vec3 cone_dirs[cone_dir_count] = vec3[]( | 
					
						
							|  |  |  | 				vec3(0.707107, 0.0, 0.707107), | 
					
						
							|  |  |  | 				vec3(0.0, 0.707107, 0.707107), | 
					
						
							|  |  |  | 				vec3(-0.707107, 0.0, 0.707107), | 
					
						
							|  |  |  | 				vec3(0.0, -0.707107, 0.707107)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		float cone_weights[cone_dir_count] = float[](0.25, 0.25, 0.25, 0.25); | 
					
						
							|  |  |  | 		for (int i = 0; i < cone_dir_count; i++) { | 
					
						
							|  |  |  | 			vec3 dir = normalize(dir_xform * cone_dirs[i]); | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 			light += cone_weights[i] * voxel_cone_trace_45_degrees(voxel_gi_textures[index], cell_size, position, dir, max_distance, voxel_gi_instances.data[index].bias); | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-31 16:20:24 -07:00
										 |  |  | 	light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization; | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 	if (!voxel_gi_instances.data[index].blend_ambient) { | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 		light.a = 1.0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	out_diff += light * blend; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//radiance | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 	vec4 irr_light = voxel_cone_trace(voxel_gi_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, voxel_gi_instances.data[index].bias); | 
					
						
							| 
									
										
										
										
											2022-07-31 16:20:24 -07:00
										 |  |  | 	irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization; | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 	if (!voxel_gi_instances.data[index].blend_ambient) { | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 		irr_light.a = 1.0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	out_spec += irr_light * blend; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	out_blend += blend; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | vec4 fetch_normal_and_roughness(ivec2 pos) { | 
					
						
							|  |  |  | 	vec4 normal_roughness = texelFetch(sampler2D(normal_roughness_buffer, linear_sampler), pos, 0); | 
					
						
							|  |  |  | 	normal_roughness.xyz = normalize(normal_roughness.xyz * 2.0 - 1.0); | 
					
						
							|  |  |  | 	return normal_roughness; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-22 20:50:24 -03:00
										 |  |  | void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 reflection_light) { | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 	vec4 normal_roughness = fetch_normal_and_roughness(pos); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-22 20:50:24 -03:00
										 |  |  | 	vec3 normal = normal_roughness.xyz; | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (normal.length() > 0.5) { | 
					
						
							|  |  |  | 		//valid normal, can do GI | 
					
						
							|  |  |  | 		float roughness = normal_roughness.w; | 
					
						
							| 
									
										
										
										
											2023-12-18 15:35:26 -07:00
										 |  |  | 		bool dynamic_object = roughness > 0.5; | 
					
						
							|  |  |  | 		if (dynamic_object) { | 
					
						
							|  |  |  | 			roughness = 1.0 - roughness; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		roughness /= (127.0 / 255.0); | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 		vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[gl_GlobalInvocationID.z].xyz)); | 
					
						
							| 
									
										
										
										
											2022-05-20 12:52:19 +10:00
										 |  |  | 		vertex = mat3(scene_data.cam_transform) * vertex; | 
					
						
							|  |  |  | 		normal = normalize(mat3(scene_data.cam_transform) * normal); | 
					
						
							|  |  |  | 		vec3 reflection = normalize(reflect(-view, normal)); | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-17 13:25:38 -03:00
										 |  |  | #ifdef USE_SDFGI | 
					
						
							|  |  |  | 		sdfgi_process(vertex, normal, reflection, roughness, ambient_light, reflection_light); | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | #ifdef USE_VOXEL_GI_INSTANCES | 
					
						
							| 
									
										
										
										
											2021-01-17 13:25:38 -03:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2023-04-25 14:14:01 +02:00
										 |  |  | #ifdef SAMPLE_VOXEL_GI_NEAREST | 
					
						
							|  |  |  | 			uvec2 voxel_gi_tex = texelFetch(voxel_gi_buffer, pos, 0).rg; | 
					
						
							|  |  |  | #else | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 			uvec2 voxel_gi_tex = texelFetch(usampler2D(voxel_gi_buffer, linear_sampler), pos, 0).rg; | 
					
						
							| 
									
										
										
										
											2023-04-25 14:14:01 +02:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 			roughness *= roughness; | 
					
						
							|  |  |  | 			//find arbitrary tangent and bitangent, then build a matrix | 
					
						
							|  |  |  | 			vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); | 
					
						
							|  |  |  | 			vec3 tangent = normalize(cross(v0, normal)); | 
					
						
							|  |  |  | 			vec3 bitangent = normalize(cross(tangent, normal)); | 
					
						
							|  |  |  | 			mat3 normal_mat = mat3(tangent, bitangent, normal); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			vec4 amb_accum = vec4(0.0); | 
					
						
							|  |  |  | 			vec4 spec_accum = vec4(0.0); | 
					
						
							|  |  |  | 			float blend_accum = 0.0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:47:26 -03:00
										 |  |  | 			for (uint i = 0; i < params.max_voxel_gi_instances; i++) { | 
					
						
							|  |  |  | 				if (any(equal(uvec2(i), voxel_gi_tex))) { | 
					
						
							|  |  |  | 					voxel_gi_compute(i, vertex, normal, reflection, normal_mat, roughness, spec_accum, amb_accum, blend_accum); | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (blend_accum > 0.0) { | 
					
						
							|  |  |  | 				amb_accum /= blend_accum; | 
					
						
							|  |  |  | 				spec_accum /= blend_accum; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-22 20:50:24 -03:00
										 |  |  | #ifdef USE_SDFGI | 
					
						
							|  |  |  | 			reflection_light = blend_color(spec_accum, reflection_light); | 
					
						
							|  |  |  | 			ambient_light = blend_color(amb_accum, ambient_light); | 
					
						
							|  |  |  | #else | 
					
						
							|  |  |  | 			reflection_light = spec_accum; | 
					
						
							|  |  |  | 			ambient_light = amb_accum; | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-01-17 13:25:38 -03:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-01-22 20:50:24 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void main() { | 
					
						
							|  |  |  | 	ivec2 pos = ivec2(gl_GlobalInvocationID.xy); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 	uint vrs_x, vrs_y; | 
					
						
							| 
									
										
										
										
											2022-12-15 12:34:19 -08:00
										 |  |  | #ifdef USE_VRS | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 	if (sc_use_vrs) { | 
					
						
							|  |  |  | 		ivec2 vrs_pos; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-21 07:37:00 -04:00
										 |  |  | 		// Currently we use a 16x16 texel, possibly some day make this configurable. | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 		if (sc_half_res) { | 
					
						
							|  |  |  | 			vrs_pos = pos >> 3; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			vrs_pos = pos >> 4; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		uint vrs_texel = imageLoad(vrs_buffer, vrs_pos).r; | 
					
						
							|  |  |  | 		// note, valid values for vrs_x and vrs_y are 1, 2 and 4. | 
					
						
							|  |  |  | 		vrs_x = 1 << ((vrs_texel >> 2) & 3); | 
					
						
							|  |  |  | 		vrs_y = 1 << (vrs_texel & 3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (mod(pos.x, vrs_x) != 0) { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (mod(pos.y, vrs_y) != 0) { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-15 12:34:19 -08:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (sc_half_res) { | 
					
						
							|  |  |  | 		pos <<= 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-20 12:52:19 +10:00
										 |  |  | 	if (any(greaterThanEqual(pos, scene_data.screen_size))) { //too large, do nothing | 
					
						
							| 
									
										
										
										
											2021-01-22 20:50:24 -03:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-24 16:00:20 -03:00
										 |  |  | 	vec4 ambient_light = vec4(0.0); | 
					
						
							|  |  |  | 	vec4 reflection_light = vec4(0.0); | 
					
						
							| 
									
										
										
										
											2021-01-22 20:50:24 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	vec3 vertex = reconstruct_position(pos); | 
					
						
							|  |  |  | 	vertex.y = -vertex.y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	process_gi(pos, vertex, ambient_light, reflection_light); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 	if (sc_half_res) { | 
					
						
							|  |  |  | 		pos >>= 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	imageStore(ambient_buffer, pos, ambient_light); | 
					
						
							|  |  |  | 	imageStore(reflection_buffer, pos, reflection_light); | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-15 12:34:19 -08:00
										 |  |  | #ifdef USE_VRS | 
					
						
							| 
									
										
										
										
											2022-02-11 22:33:54 +11:00
										 |  |  | 	if (sc_use_vrs) { | 
					
						
							|  |  |  | 		if (vrs_x > 1) { | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(1, 0), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(1, 0), reflection_light); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (vrs_x > 2) { | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(2, 0), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(2, 0), reflection_light); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(3, 0), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(3, 0), reflection_light); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (vrs_y > 1) { | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(0, 1), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(0, 1), reflection_light); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (vrs_y > 1 && vrs_x > 1) { | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(1, 1), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(1, 1), reflection_light); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (vrs_y > 1 && vrs_x > 2) { | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(2, 1), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(2, 1), reflection_light); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(3, 1), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(3, 1), reflection_light); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (vrs_y > 2) { | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(0, 2), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(0, 2), reflection_light); | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(0, 3), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(0, 3), reflection_light); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (vrs_y > 2 && vrs_x > 1) { | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(1, 2), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(1, 2), reflection_light); | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(1, 3), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(1, 3), reflection_light); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (vrs_y > 2 && vrs_x > 2) { | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(2, 2), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(2, 2), reflection_light); | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(2, 3), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(2, 3), reflection_light); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(3, 2), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(3, 2), reflection_light); | 
					
						
							|  |  |  | 			imageStore(ambient_buffer, pos + ivec2(3, 3), ambient_light); | 
					
						
							|  |  |  | 			imageStore(reflection_buffer, pos + ivec2(3, 3), reflection_light); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-15 12:34:19 -08:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2020-06-25 10:33:28 -03:00
										 |  |  | } |