339 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			339 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								Copyright (c) 2024 Turánszki János
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#ifndef _CONETRACE_GLSL_
							 | 
						||
| 
								 | 
							
								#define _CONETRACE_GLSL_
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "std/voxels_constants.glsl"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// References
							 | 
						||
| 
								 | 
							
								// https://github.com/Friduric/voxel-cone-tracing
							 | 
						||
| 
								 | 
							
								// https://github.com/Cigg/Voxel-Cone-Tracing
							 | 
						||
| 
								 | 
							
								// https://github.com/GreatBlambo/voxel_cone_tracing/
							 | 
						||
| 
								 | 
							
								// http://simonstechblog.blogspot.com/2013/01/implementing-voxel-cone-tracing.html
							 | 
						||
| 
								 | 
							
								// http://leifnode.com/2015/05/voxel-cone-traced-global-illumination/
							 | 
						||
| 
								 | 
							
								// http://www.seas.upenn.edu/%7Epcozzi/OpenGLInsights/OpenGLInsights-SparseVoxelization.pdf
							 | 
						||
| 
								 | 
							
								// https://research.nvidia.com/sites/default/files/publications/GIVoxels-pg2011-authors.pdf
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const float MAX_DISTANCE = voxelgiRange;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef _VoxelGI
							 | 
						||
| 
								 | 
							
								uniform sampler3D dummy;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								vec4 sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCount * 10], const float clipmap_index, const float step_dist, const int precomputed_direction, const vec3 face_offset, const vec3 direction_weight) {
							 | 
						||
| 
								 | 
							
								 	vec4 col = vec4(0.0);
							 | 
						||
| 
								 | 
							
									vec3 tc = (P - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
							 | 
						||
| 
								 | 
							
									vec3 half_texel = vec3(0.5) / voxelgiResolution;
							 | 
						||
| 
								 | 
							
									tc = tc * 0.5 + 0.5;
							 | 
						||
| 
								 | 
							
									tc = clamp(tc, half_texel, 1.0 - half_texel);
							 | 
						||
| 
								 | 
							
									tc.x = (tc.x + precomputed_direction) / (6 + DIFFUSE_CONE_COUNT);
							 | 
						||
| 
								 | 
							
									tc.y = (tc.y + clipmap_index) / voxelgiClipmapCount;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (precomputed_direction == 0) {
							 | 
						||
| 
								 | 
							
										col = direction_weight.x * textureLod(voxels, vec3(tc.x + face_offset.x, tc.y, tc.z), 0)
							 | 
						||
| 
								 | 
							
											+ direction_weight.y * textureLod(voxels, vec3(tc.x + face_offset.y, tc.y, tc.z), 0)
							 | 
						||
| 
								 | 
							
											+ direction_weight.z * textureLod(voxels, vec3(tc.x + face_offset.z, tc.y, tc.z), 0);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
										col = textureLod(voxels, tc, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									col *= step_dist / float(clipmaps[int(clipmap_index * 10)]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return col;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#ifdef _VoxelAOvar
							 | 
						||
| 
								 | 
							
								float sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCount * 10], const float clipmap_index, const float step_dist, const int precomputed_direction, const vec3 face_offset, const vec3 direction_weight) {
							 | 
						||
| 
								 | 
							
								 	float opac = 0.0;
							 | 
						||
| 
								 | 
							
									vec3 tc = (P - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
							 | 
						||
| 
								 | 
							
									vec3 half_texel = vec3(0.5) / voxelgiResolution;
							 | 
						||
| 
								 | 
							
									tc = tc * 0.5 + 0.5;
							 | 
						||
| 
								 | 
							
									tc = clamp(tc, half_texel, 1.0 - half_texel);
							 | 
						||
| 
								 | 
							
									tc.x = (tc.x + precomputed_direction) / (6 + DIFFUSE_CONE_COUNT);
							 | 
						||
| 
								 | 
							
									tc.y = (tc.y + clipmap_index) / voxelgiClipmapCount;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (precomputed_direction == 0) {
							 | 
						||
| 
								 | 
							
										opac = direction_weight.x * textureLod(voxels, vec3(tc.x + face_offset.x, tc.y, tc.z), 0).r
							 | 
						||
| 
								 | 
							
											+ direction_weight.y * textureLod(voxels, vec3(tc.x + face_offset.y, tc.y, tc.z), 0).r
							 | 
						||
| 
								 | 
							
											+ direction_weight.z * textureLod(voxels, vec3(tc.x + face_offset.z, tc.y, tc.z), 0).r;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
										opac = textureLod(voxels, tc, 0).r;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									opac *= step_dist / float(clipmaps[int(clipmap_index * 10)]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return opac;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef _VoxelGI
							 | 
						||
| 
								 | 
							
								vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const int precomputed_direction, const bool use_sdf, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) {
							 | 
						||
| 
								 | 
							
								    vec4 sampleCol = vec4(0.0);
							 | 
						||
| 
								 | 
							
									float voxelSize0 = float(clipmaps[0]) * 2.0;
							 | 
						||
| 
								 | 
							
									float dist = voxelSize0;
							 | 
						||
| 
								 | 
							
									float step_dist = dist;
							 | 
						||
| 
								 | 
							
									vec3 samplePos;
							 | 
						||
| 
								 | 
							
									vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
							 | 
						||
| 
								 | 
							
									int clipmap_index0 = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									vec3 aniso_direction = -dir;
							 | 
						||
| 
								 | 
							
									vec3 face_offset = vec3(
							 | 
						||
| 
								 | 
							
										aniso_direction.x > 0.0 ? 0 : 1,
							 | 
						||
| 
								 | 
							
										aniso_direction.y > 0.0 ? 2 : 3,
							 | 
						||
| 
								 | 
							
										aniso_direction.z > 0.0 ? 4 : 5
							 | 
						||
| 
								 | 
							
									) / (6 + DIFFUSE_CONE_COUNT);
							 | 
						||
| 
								 | 
							
									vec3 direction_weight = abs(dir);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									float coneCoefficient = 2.0 * tan(aperture * 0.5);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while (sampleCol.a < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
							 | 
						||
| 
								 | 
							
										vec4 mipSample = vec4(0.0);
							 | 
						||
| 
								 | 
							
										float diam = max(voxelSize0, dist * coneCoefficient);
							 | 
						||
| 
								 | 
							
								        float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
							 | 
						||
| 
								 | 
							
								        float clipmap_index = floor(lod);
							 | 
						||
| 
								 | 
							
										float clipmap_blend = fract(lod);
							 | 
						||
| 
								 | 
							
										vec3 p0 = start_pos + dir * dist;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
							 | 
						||
| 
								 | 
							
										samplePos = samplePos * 0.5 + 0.5;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0)))) {
							 | 
						||
| 
								 | 
							
											clipmap_index0++;
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, precomputed_direction, face_offset, direction_weight);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
							 | 
						||
| 
								 | 
							
											vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
							 | 
						||
| 
								 | 
							
											mipSample = mix(mipSample, mipSampleNext, smoothstep(0.0, 1.0, clipmap_blend));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										sampleCol += (1.0 - sampleCol.a) * mipSample;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										float stepSizeCurrent = step_size;
							 | 
						||
| 
								 | 
							
										if (use_sdf) {
							 | 
						||
| 
								 | 
							
											// half texel correction is applied to avoid sampling over current clipmap:
							 | 
						||
| 
								 | 
							
											const vec3 half_texel = vec3(0.5) / voxelgiResolution;
							 | 
						||
| 
								 | 
							
											vec3 tc0 = clamp(samplePos, half_texel, 1 - half_texel);
							 | 
						||
| 
								 | 
							
											tc0.y = (tc0.y + clipmap_index) / voxelgiClipmapCount; // remap into clipmap
							 | 
						||
| 
								 | 
							
											float sdf = textureLod(voxelsSDF, tc0, 0).r;
							 | 
						||
| 
								 | 
							
											stepSizeCurrent = max(step_size, sdf - diam);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										step_dist = diam * stepSizeCurrent;
							 | 
						||
| 
								 | 
							
										dist += step_dist;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								    return sampleCol;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) {
							 | 
						||
| 
								 | 
							
									float sum = 0.0;
							 | 
						||
| 
								 | 
							
									vec4 amount = vec4(0.0);
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) {
							 | 
						||
| 
								 | 
							
										vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i];
							 | 
						||
| 
								 | 
							
										const float cosTheta = dot(normal, coneDir);
							 | 
						||
| 
								 | 
							
										if (cosTheta <= 0)
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										int precomputed_direction = 6 + i;
							 | 
						||
| 
								 | 
							
										amount += traceCone(voxels, dummy, origin, normal, coneDir, precomputed_direction, false, DIFFUSE_CONE_APERTURE, 1.0, clipmaps) * cosTheta;
							 | 
						||
| 
								 | 
							
										sum += cosTheta;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									amount /= sum;
							 | 
						||
| 
								 | 
							
									amount.rgb = max(amount.rgb, vec3(0.0));
							 | 
						||
| 
								 | 
							
									amount.a = clamp(amount.a, 0.0, 1.0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return amount * voxelgiOcc;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
							 | 
						||
| 
								 | 
							
									vec3 specularDir = reflect(-viewDir, normal);
							 | 
						||
| 
								 | 
							
									vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep;
							 | 
						||
| 
								 | 
							
									vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									amount.rgb = max(vec3(0.0), amount.rgb);
							 | 
						||
| 
								 | 
							
									amount.a = clamp(amount.a, 0.0, 1.0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return amount * voxelgiOcc;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
							 | 
						||
| 
								 | 
							
								 	const float transmittance = 1.0;
							 | 
						||
| 
								 | 
							
								 	vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior);
							 | 
						||
| 
								 | 
							
								 	vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
							 | 
						||
| 
								 | 
							
									vec4 amount =  transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									amount.rgb = max(vec3(0.0), amount.rgb);
							 | 
						||
| 
								 | 
							
									amount.a = clamp(amount.a, 0.0, 1.0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return amount * voxelgiOcc;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef _VoxelAOvar
							 | 
						||
| 
								 | 
							
								float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const vec3 dir, const int precomputed_direction, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) {
							 | 
						||
| 
								 | 
							
									float sampleCol = 0.0;
							 | 
						||
| 
								 | 
							
									float voxelSize0 = float(clipmaps[0]) * 2.0;
							 | 
						||
| 
								 | 
							
									float dist = voxelSize0;
							 | 
						||
| 
								 | 
							
									float step_dist = dist;
							 | 
						||
| 
								 | 
							
									vec3 samplePos;
							 | 
						||
| 
								 | 
							
									vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
							 | 
						||
| 
								 | 
							
									int clipmap_index0 = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									vec3 aniso_direction = -dir;
							 | 
						||
| 
								 | 
							
									vec3 face_offset = vec3(
							 | 
						||
| 
								 | 
							
										aniso_direction.x > 0.0 ? 0 : 1,
							 | 
						||
| 
								 | 
							
										aniso_direction.y > 0.0 ? 2 : 3,
							 | 
						||
| 
								 | 
							
										aniso_direction.z > 0.0 ? 4 : 5
							 | 
						||
| 
								 | 
							
									) / (6 + DIFFUSE_CONE_COUNT);
							 | 
						||
| 
								 | 
							
									vec3 direction_weight = abs(dir);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									float coneCoefficient = 2.0 * tan(aperture * 0.5);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
							 | 
						||
| 
								 | 
							
										float mipSample = 0.0;
							 | 
						||
| 
								 | 
							
										float diam = max(voxelSize0, dist * coneCoefficient);
							 | 
						||
| 
								 | 
							
								        float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
							 | 
						||
| 
								 | 
							
										float clipmap_index = floor(lod);
							 | 
						||
| 
								 | 
							
										float clipmap_blend = fract(lod);
							 | 
						||
| 
								 | 
							
										vec3 p0 = start_pos + dir * dist;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution.x);
							 | 
						||
| 
								 | 
							
										samplePos = samplePos * 0.5 + 0.5;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ((any(notEqual(clamp(samplePos, 0.0, 1.0), samplePos)))) {
							 | 
						||
| 
								 | 
							
											clipmap_index0++;
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, precomputed_direction, face_offset, direction_weight);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
							 | 
						||
| 
								 | 
							
											float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
							 | 
						||
| 
								 | 
							
											mipSample = mix(mipSample, mipSampleNext, clipmap_blend);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										sampleCol += (1.0 - sampleCol) * mipSample;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										step_dist = diam * step_size;
							 | 
						||
| 
								 | 
							
										dist += step_dist;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								    return sampleCol;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) {
							 | 
						||
| 
								 | 
							
									float sum = 0.0;
							 | 
						||
| 
								 | 
							
									float amount = 0.0;
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < DIFFUSE_CONE_COUNT; i++) {
							 | 
						||
| 
								 | 
							
										vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i];
							 | 
						||
| 
								 | 
							
										int precomputed_direction = 6 + i;
							 | 
						||
| 
								 | 
							
										const float cosTheta = dot(normal, coneDir);
							 | 
						||
| 
								 | 
							
										if (cosTheta <= 0)
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										amount += traceConeAO(voxels, origin, normal, coneDir, precomputed_direction, DIFFUSE_CONE_APERTURE, 1.0, clipmaps) * cosTheta;
							 | 
						||
| 
								 | 
							
										sum += cosTheta;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									amount /= sum;
							 | 
						||
| 
								 | 
							
									amount = clamp(amount, 0.0, 1.0);
							 | 
						||
| 
								 | 
							
									return amount * voxelgiOcc;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef _VoxelShadow
							 | 
						||
| 
								 | 
							
								float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) {
							 | 
						||
| 
								 | 
							
								    float sampleCol = 0.0;
							 | 
						||
| 
								 | 
							
									float voxelSize0 = float(clipmaps[0]) * 2.0;
							 | 
						||
| 
								 | 
							
									float dist = voxelSize0;
							 | 
						||
| 
								 | 
							
									float step_dist = dist;
							 | 
						||
| 
								 | 
							
									vec3 samplePos;
							 | 
						||
| 
								 | 
							
									vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
							 | 
						||
| 
								 | 
							
									int clipmap_index0 = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									vec3 aniso_direction = -dir;
							 | 
						||
| 
								 | 
							
									vec3 face_offset = vec3(
							 | 
						||
| 
								 | 
							
										aniso_direction.x > 0.0 ? 0 : 1,
							 | 
						||
| 
								 | 
							
										aniso_direction.y > 0.0 ? 2 : 3,
							 | 
						||
| 
								 | 
							
										aniso_direction.z > 0.0 ? 4 : 5
							 | 
						||
| 
								 | 
							
									) / (6 + DIFFUSE_CONE_COUNT);
							 | 
						||
| 
								 | 
							
									vec3 direction_weight = abs(dir);
							 | 
						||
| 
								 | 
							
									float coneCoefficient = 2.0 * tan(aperture * 0.5);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
							 | 
						||
| 
								 | 
							
										float mipSample = 0.0;
							 | 
						||
| 
								 | 
							
										float diam = max(voxelSize0, dist * coneCoefficient);
							 | 
						||
| 
								 | 
							
								        float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
							 | 
						||
| 
								 | 
							
										float clipmap_index = floor(lod);
							 | 
						||
| 
								 | 
							
										float clipmap_blend = fract(lod);
							 | 
						||
| 
								 | 
							
										vec3 p0 = start_pos + dir * dist;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution.x);
							 | 
						||
| 
								 | 
							
										samplePos = samplePos * 0.5 + 0.5;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) {
							 | 
						||
| 
								 | 
							
											clipmap_index0++;
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										#ifdef _VoxelAOvar
							 | 
						||
| 
								 | 
							
										mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, 0, face_offset, direction_weight);
							 | 
						||
| 
								 | 
							
										#else
							 | 
						||
| 
								 | 
							
										mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, 0, face_offset, direction_weight).a;
							 | 
						||
| 
								 | 
							
										#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
							 | 
						||
| 
								 | 
							
											#ifdef _VoxelAOvar
							 | 
						||
| 
								 | 
							
											float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight);
							 | 
						||
| 
								 | 
							
											#else
							 | 
						||
| 
								 | 
							
											float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight).a;
							 | 
						||
| 
								 | 
							
											#endif
							 | 
						||
| 
								 | 
							
											mipSample = mix(mipSample, mipSampleNext, clipmap_blend);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										sampleCol += (1.0 - sampleCol) * mipSample;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										float stepSizeCurrent = step_size;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// half texel correction is applied to avoid sampling over current clipmap:
							 | 
						||
| 
								 | 
							
										const vec3 half_texel = vec3(0.5) / voxelgiResolution;
							 | 
						||
| 
								 | 
							
										vec3 tc0 = clamp(samplePos, half_texel, 1 - half_texel);
							 | 
						||
| 
								 | 
							
										tc0.y = (tc0.y + clipmap_index) / voxelgiClipmapCount; // remap into clipmap
							 | 
						||
| 
								 | 
							
										float sdf = textureLod(voxelsSDF, tc0, 0.0).r;
							 | 
						||
| 
								 | 
							
										stepSizeCurrent = max(step_size, sdf - diam);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										step_dist = diam * stepSizeCurrent;
							 | 
						||
| 
								 | 
							
										dist += step_dist;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return sampleCol;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel) {
							 | 
						||
| 
								 | 
							
								 	vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep;
							 | 
						||
| 
								 | 
							
									float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps);
							 | 
						||
| 
								 | 
							
									amount = clamp(amount, 0.0, 1.0);
							 | 
						||
| 
								 | 
							
									return amount * voxelgiOcc;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#endif // _CONETRACE_GLSL_
							 |