2017-08-06 17:36:25 +02:00
|
|
|
// References
|
2017-02-22 15:50:19 +01:00
|
|
|
// https://github.com/Friduric/voxel-cone-tracing
|
|
|
|
// https://github.com/Cigg/Voxel-Cone-Tracing
|
2017-08-03 14:01:04 +02:00
|
|
|
// https://github.com/GreatBlambo/voxel_cone_tracing/
|
2017-02-22 15:50:19 +01:00
|
|
|
// 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
|
|
|
|
|
2017-10-23 16:24:57 +02:00
|
|
|
const float MAX_DISTANCE = 1.73205080757 * voxelgiRange;
|
|
|
|
const float VOXEL_SIZE = (2.0 / voxelgiResolution.x) * voxelgiStep;
|
|
|
|
const float blendFac = (1.0 / max(voxelgiOcc, 0.1));
|
2017-08-06 17:36:25 +02:00
|
|
|
|
|
|
|
uniform sampler3D voxels;
|
2017-12-19 18:05:38 +01:00
|
|
|
uniform sampler3D voxelsLast;
|
2017-08-06 17:36:25 +02:00
|
|
|
|
|
|
|
vec3 orthogonal(const vec3 u) {
|
|
|
|
// Pass normalized u
|
|
|
|
const vec3 v = vec3(0.99146, 0.11664, 0.05832); // Pick any normalized vector
|
|
|
|
return abs(dot(u, v)) > 0.99999 ? cross(u, vec3(0.0, 1.0, 0.0)) : cross(u, v);
|
|
|
|
}
|
2017-08-03 14:01:04 +02:00
|
|
|
|
2017-08-03 17:25:13 +02:00
|
|
|
vec3 tangent(const vec3 n) {
|
|
|
|
vec3 t1 = cross(n, vec3(0, 0, 1));
|
|
|
|
vec3 t2 = cross(n, vec3(0, 1, 0));
|
|
|
|
if (length(t1) > length(t2)) return normalize(t1);
|
|
|
|
else return normalize(t2);
|
|
|
|
}
|
2017-08-03 14:01:04 +02:00
|
|
|
|
2017-08-06 17:36:25 +02:00
|
|
|
// uvec3 faceIndices(const vec3 dir) {
|
2017-08-03 14:01:04 +02:00
|
|
|
// uvec3 ret;
|
|
|
|
// ret.x = (dir.x < 0.0) ? 0 : 1;
|
|
|
|
// ret.y = (dir.y < 0.0) ? 2 : 3;
|
|
|
|
// ret.z = (dir.z < 0.0) ? 4 : 5;
|
|
|
|
// return ret;
|
|
|
|
// }
|
|
|
|
|
2017-08-06 17:36:25 +02:00
|
|
|
// vec4 sampleVoxel(const vec3 pos, vec3 dir, const uvec3 indices, const float lod) {
|
2017-08-03 14:01:04 +02:00
|
|
|
// dir = abs(dir);
|
|
|
|
// return dir.x * textureLod(voxels[indices.x], pos, lod) +
|
|
|
|
// dir.y * textureLod(voxels[indices.y], pos, lod) +
|
|
|
|
// dir.z * textureLod(voxels[indices.z], pos, lod);
|
|
|
|
// }
|
2017-02-22 15:50:19 +01:00
|
|
|
|
2017-12-19 18:05:38 +01:00
|
|
|
vec4 traceCone(sampler3D voxels, const vec3 origin, vec3 dir, const float aperture, const float maxDist, const float offset) {
|
2017-08-03 17:25:13 +02:00
|
|
|
dir = normalize(dir);
|
2017-08-06 17:36:25 +02:00
|
|
|
// uvec3 indices = faceIndices(dir);
|
|
|
|
vec4 sampleCol = vec4(0.0);
|
|
|
|
float dist = offset;
|
2017-08-03 17:25:13 +02:00
|
|
|
float diam = dist * aperture;
|
2017-12-19 18:05:38 +01:00
|
|
|
vec3 samplePos;
|
2017-08-03 17:25:13 +02:00
|
|
|
// Step until alpha > 1 or out of bounds
|
2017-08-06 17:36:25 +02:00
|
|
|
while (sampleCol.a < 1.0 && dist < maxDist) {
|
2017-12-19 18:05:38 +01:00
|
|
|
samplePos = dir * dist + origin;
|
2017-08-03 17:25:13 +02:00
|
|
|
// Choose mip level based on the diameter of the cone
|
2017-10-23 01:55:47 +02:00
|
|
|
float mip = max(log2(diam * voxelgiResolution.x), 0);
|
2017-08-06 17:36:25 +02:00
|
|
|
// vec4 mipSample = sampleVoxel(samplePos, dir, indices, mip);
|
2017-10-23 16:24:57 +02:00
|
|
|
vec4 mipSample = textureLod(voxels, samplePos * 0.5 + 0.5, mip);
|
|
|
|
#ifdef _VoxelGIEmission
|
2017-10-15 19:11:26 +02:00
|
|
|
mipSample.rgb = min(mipSample.rgb * 0.9, vec3(0.9)) + max((mipSample.rgb - 0.9) * 200.0, 0.0); // Higher range to allow emission
|
2017-10-23 16:24:57 +02:00
|
|
|
#endif
|
2017-08-03 17:25:13 +02:00
|
|
|
// Blend mip sample with current sample color
|
2017-10-23 16:24:57 +02:00
|
|
|
sampleCol += (1 - sampleCol.a) * mipSample;
|
2017-08-06 17:36:25 +02:00
|
|
|
dist += max(diam / 2, VOXEL_SIZE); // Step size
|
2017-08-03 17:25:13 +02:00
|
|
|
diam = dist * aperture;
|
|
|
|
}
|
2017-08-06 17:36:25 +02:00
|
|
|
return sampleCol;
|
2017-08-03 17:25:13 +02:00
|
|
|
}
|
2017-08-03 14:01:04 +02:00
|
|
|
|
2017-12-19 18:05:38 +01:00
|
|
|
vec4 traceDiffuse(const vec3 origin, const vec3 normal, sampler3D voxels) {
|
2017-08-03 17:25:13 +02:00
|
|
|
const float TAN_22_5 = 0.55785173935;
|
2017-08-06 17:36:25 +02:00
|
|
|
const float angleMix = 0.5f;
|
2017-08-03 17:25:13 +02:00
|
|
|
const float aperture = TAN_22_5;
|
|
|
|
const vec3 o1 = normalize(tangent(normal));
|
|
|
|
const vec3 o2 = normalize(cross(o1, normal));
|
|
|
|
const vec3 c1 = 0.5f * (o1 + o2);
|
|
|
|
const vec3 c2 = 0.5f * (o1 - o2);
|
2017-10-23 16:24:57 +02:00
|
|
|
const float offset = 1.5 * VOXEL_SIZE * voxelgiOffsetDiff;
|
2017-12-19 18:05:38 +01:00
|
|
|
|
|
|
|
#ifdef _VoxelCones1
|
|
|
|
return traceCone(voxels, origin, normal, aperture, MAX_DISTANCE, offset);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _VoxelCones3
|
|
|
|
vec4 col = traceCone(voxels, origin, normal, aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, -o1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, c2, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
return col / (3.0 * blendFac);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _VoxelCones5
|
|
|
|
vec4 col = traceCone(voxels, origin, normal, aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, -o1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, -o2, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, c1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, c2, angleMix), aperture, MAX_DISTANCE, offset);
|
2017-10-23 16:24:57 +02:00
|
|
|
return col / (5.0 * blendFac);
|
2017-12-19 18:05:38 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _VoxelCones9
|
|
|
|
// Normal direction
|
|
|
|
vec4 col = traceCone(voxels, origin, normal, aperture, MAX_DISTANCE, offset);
|
2017-08-03 17:25:13 +02:00
|
|
|
// 4 side cones
|
2017-12-19 18:05:38 +01:00
|
|
|
col += traceCone(voxels, origin, mix(normal, o1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, -o1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, o2, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, -o2, angleMix), aperture, MAX_DISTANCE, offset);
|
2017-08-03 17:25:13 +02:00
|
|
|
// 4 corners
|
2017-12-19 18:05:38 +01:00
|
|
|
col += traceCone(voxels, origin, mix(normal, c1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, -c1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, c2, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceCone(voxels, origin, mix(normal, -c2, angleMix), aperture, MAX_DISTANCE, offset);
|
2017-10-23 16:24:57 +02:00
|
|
|
return col / (9.0 * blendFac);
|
2017-10-12 22:40:30 +02:00
|
|
|
#endif
|
2017-12-19 18:05:38 +01:00
|
|
|
|
|
|
|
return vec4(0.0);
|
2017-08-03 17:25:13 +02:00
|
|
|
}
|
2017-08-03 14:01:04 +02:00
|
|
|
|
2017-08-06 17:36:25 +02:00
|
|
|
float traceShadow(const vec3 origin, const vec3 dir, const float aperture, const float targetDistance) {
|
2017-10-23 16:24:57 +02:00
|
|
|
const float offset = 2 * VOXEL_SIZE * voxelgiOffsetShadow;
|
2017-12-19 18:05:38 +01:00
|
|
|
return traceCone(voxels, origin, dir, aperture, targetDistance, offset).a;
|
2016-10-17 17:39:40 +02:00
|
|
|
}
|
|
|
|
|
2017-08-06 17:36:25 +02:00
|
|
|
vec3 traceSpecular(const vec3 pos, const vec3 normal, const vec3 viewDir, const float roughness) {
|
|
|
|
float rough = max(roughness, 0.15);
|
|
|
|
float specularAperture = clamp(tan((3.14159265 / 2) * rough * 0.75), 0.0174533, 3.14159265);
|
|
|
|
vec3 specularDir = normalize(reflect(-viewDir, normal));
|
|
|
|
// Clamp to 1 grad and pi, exponent is angle of cone in radians
|
2017-10-23 16:24:57 +02:00
|
|
|
const float offset = 3 * VOXEL_SIZE * voxelgiOffsetSpec;
|
2017-12-19 18:05:38 +01:00
|
|
|
return traceCone(voxels, pos, specularDir, specularAperture, MAX_DISTANCE, offset).xyz;
|
2017-05-20 19:07:15 +02:00
|
|
|
}
|
2017-02-22 15:50:19 +01:00
|
|
|
|
2017-08-06 17:36:25 +02:00
|
|
|
vec3 traceRefraction(const vec3 pos, const vec3 normal, const vec3 viewDir, const float roughness) {
|
|
|
|
const float ior = 1.440;
|
|
|
|
const float transmittance = 1.0;
|
|
|
|
vec3 refraction = refract(viewDir, normal, 1.0 / ior);
|
2017-08-13 20:28:06 +02:00
|
|
|
float rough = max(roughness, 0.03);
|
2017-08-06 17:36:25 +02:00
|
|
|
float specularAperture = clamp(tan((3.14159265 / 2) * rough), 0.0174533, 3.14159265);
|
2017-10-23 16:24:57 +02:00
|
|
|
const float offset = 1.5 * VOXEL_SIZE * voxelgiOffsetRefract;
|
2017-12-19 18:05:38 +01:00
|
|
|
return transmittance * traceCone(voxels, pos, refraction, specularAperture, MAX_DISTANCE, offset).xyz;
|
2016-10-17 17:39:40 +02:00
|
|
|
}
|
2017-08-22 10:04:13 +02:00
|
|
|
|
2017-12-19 18:05:38 +01:00
|
|
|
float traceConeAO(sampler3D voxels, const vec3 origin, vec3 dir, const float aperture, const float maxDist, const float offset) {
|
2017-08-22 10:04:13 +02:00
|
|
|
dir = normalize(dir);
|
|
|
|
float sampleCol = 0.0;
|
|
|
|
float dist = offset;
|
|
|
|
float diam = dist * aperture;
|
2017-12-19 18:05:38 +01:00
|
|
|
vec3 samplePos;
|
2017-08-22 10:04:13 +02:00
|
|
|
while (sampleCol < 1.0 && dist < maxDist) {
|
2017-12-19 18:05:38 +01:00
|
|
|
samplePos = dir * dist + origin;
|
2017-10-23 01:55:47 +02:00
|
|
|
float mip = max(log2(diam * voxelgiResolution.x), 0);
|
2017-08-22 10:04:13 +02:00
|
|
|
float mipSample = textureLod(voxels, samplePos * 0.5 + vec3(0.5), mip).r;
|
|
|
|
sampleCol += (1 - sampleCol) * mipSample;
|
|
|
|
dist += max(diam / 2, VOXEL_SIZE);
|
|
|
|
diam = dist * aperture;
|
|
|
|
}
|
|
|
|
return sampleCol;
|
|
|
|
}
|
|
|
|
|
2017-12-19 18:05:38 +01:00
|
|
|
float traceAO(const vec3 origin, const vec3 normal, sampler3D voxels) {
|
2017-08-22 10:04:13 +02:00
|
|
|
const float TAN_22_5 = 0.55785173935;
|
|
|
|
const float angleMix = 0.5f;
|
|
|
|
const float aperture = TAN_22_5;
|
|
|
|
const vec3 o1 = normalize(tangent(normal));
|
|
|
|
const vec3 o2 = normalize(cross(o1, normal));
|
|
|
|
const vec3 c1 = 0.5f * (o1 + o2);
|
|
|
|
const vec3 c2 = 0.5f * (o1 - o2);
|
2017-10-23 16:24:57 +02:00
|
|
|
const float offset = 1.5 * VOXEL_SIZE * voxelgiOffsetDiff;
|
2017-12-19 18:05:38 +01:00
|
|
|
|
|
|
|
#ifdef _VoxelCones1
|
|
|
|
return traceConeAO(voxels, origin, normal, aperture, MAX_DISTANCE, offset);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _VoxelCones3
|
|
|
|
float col = traceConeAO(voxels, origin, normal, aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, o1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, -c2, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
return col / (3.0 * blendFac);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _VoxelCones5
|
|
|
|
float col = traceConeAO(voxels, origin, normal, aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, o1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, o2, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, -c1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, -c2, angleMix), aperture, MAX_DISTANCE, offset);
|
2017-10-23 16:24:57 +02:00
|
|
|
return col / (5.0 * blendFac);
|
2017-11-04 16:16:07 +01:00
|
|
|
#endif
|
2017-12-19 18:05:38 +01:00
|
|
|
|
|
|
|
#ifdef _VoxelCones9
|
|
|
|
float col = traceConeAO(voxels, origin, normal, aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, o1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, o2, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, -c1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, -c2, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, -o1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, -o2, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, c1, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
col += traceConeAO(voxels, origin, mix(normal, c2, angleMix), aperture, MAX_DISTANCE, offset);
|
|
|
|
return col / (9.0 * blendFac);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0.0;
|
2017-08-22 10:04:13 +02:00
|
|
|
}
|