Full BSDF
This commit is contained in:
@ -34,17 +34,19 @@ THE SOFTWARE.
|
||||
// https://research.nvidia.com/sites/default/files/publications/GIVoxels-pg2011-authors.pdf
|
||||
|
||||
const float MAX_DISTANCE = voxelgiRange;
|
||||
const int MAX_CONE_STEPS = 32;
|
||||
|
||||
#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);
|
||||
int base = int(clipmap_index * 10);
|
||||
float voxelSize = float(clipmaps[base]);
|
||||
vec3 tc = (P - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * 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.x = (tc.x + precomputed_direction) / (6 + diffuseConeCount);
|
||||
tc.y = (tc.y + clipmap_index) / voxelgiClipmapCount;
|
||||
|
||||
if (precomputed_direction == 0) {
|
||||
@ -55,7 +57,7 @@ vec4 sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCo
|
||||
else
|
||||
col = textureLod(voxels, tc, 0);
|
||||
|
||||
col *= step_dist / float(clipmaps[int(clipmap_index * 10)]);
|
||||
col *= step_dist / voxelSize;
|
||||
|
||||
return col;
|
||||
}
|
||||
@ -64,11 +66,13 @@ vec4 sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCo
|
||||
#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);
|
||||
int base = int(clipmap_index * 10);
|
||||
float voxelSize = float(clipmaps[base]);
|
||||
vec3 tc = (P - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * 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.x = (tc.x + precomputed_direction) / (6 + diffuseConeCount);
|
||||
tc.y = (tc.y + clipmap_index) / voxelgiClipmapCount;
|
||||
|
||||
if (precomputed_direction == 0) {
|
||||
@ -79,7 +83,7 @@ float sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapC
|
||||
else
|
||||
opac = textureLod(voxels, tc, 0).r;
|
||||
|
||||
opac *= step_dist / float(clipmaps[int(clipmap_index * 10)]);
|
||||
opac *= step_dist / voxelSize;
|
||||
|
||||
return opac;
|
||||
}
|
||||
@ -92,7 +96,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
float dist = voxelSize0;
|
||||
float step_dist = dist;
|
||||
vec3 samplePos;
|
||||
vec3 start_pos = origin + n * voxelSize0;
|
||||
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||
int clipmap_index0 = 0;
|
||||
|
||||
vec3 aniso_direction = -dir;
|
||||
@ -100,12 +104,14 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
aniso_direction.x > 0.0 ? 0.0 : 1.0,
|
||||
aniso_direction.y > 0.0 ? 2.0 : 3.0,
|
||||
aniso_direction.z > 0.0 ? 4.0 : 5.0
|
||||
) / (6 + DIFFUSE_CONE_COUNT);
|
||||
) / (6 + diffuseConeCount);
|
||||
vec3 direction_weight = abs(dir);
|
||||
|
||||
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
||||
|
||||
while (sampleCol.a < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
|
||||
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
int steps = 0;
|
||||
while (sampleCol.a < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount && steps < MAX_CONE_STEPS) {
|
||||
vec4 mipSample = vec4(0.0);
|
||||
float diam = max(voxelSize0, dist * coneCoefficient);
|
||||
float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
|
||||
@ -113,7 +119,9 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
float clipmap_blend = smoothstep(0.0, 1.0, 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);
|
||||
int base = int(clipmap_index * 10);
|
||||
float voxelSize = float(clipmaps[base]);
|
||||
samplePos = (p0 - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
|
||||
samplePos = samplePos * 0.5 + 0.5;
|
||||
|
||||
if (any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0)))) {
|
||||
@ -129,8 +137,11 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
|
||||
mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
|
||||
if(totalBlend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
if(totalBlend > 0.05 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
int baseNext = int((clipmap_index + 1.0) * 10);
|
||||
float voxelSizeCoarse = float(clipmaps[baseNext]);
|
||||
mipSampleNext *= voxelSizeCoarse / voxelSize;
|
||||
mipSample = mix(mipSample, mipSampleNext, totalBlend);
|
||||
}
|
||||
|
||||
@ -138,8 +149,6 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
|
||||
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;
|
||||
@ -147,6 +156,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
}
|
||||
step_dist = diam * stepSizeCurrent;
|
||||
dist += step_dist;
|
||||
steps++;
|
||||
}
|
||||
return sampleCol;
|
||||
}
|
||||
@ -154,13 +164,13 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
||||
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];
|
||||
for (int i = 0; i < diffuseConeCount; ++i) {
|
||||
vec3 coneDir = diffuseConeDirections[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;
|
||||
amount += traceCone(voxels, voxels, origin, normal, coneDir, precomputed_direction, false, diffuseConeAperture, 1.0, clipmaps) * cosTheta;
|
||||
sum += cosTheta;
|
||||
}
|
||||
|
||||
@ -191,7 +201,7 @@ vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sam
|
||||
amount.rgb = max(vec3(0.0), amount.rgb);
|
||||
amount.a = clamp(amount.a, 0.0, 1.0);
|
||||
|
||||
return amount * voxelgiOcc;
|
||||
return amount * voxelgiOcc * voxelgiRefr;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -202,7 +212,7 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
float dist = voxelSize0;
|
||||
float step_dist = dist;
|
||||
vec3 samplePos;
|
||||
vec3 start_pos = origin + n * voxelSize0;
|
||||
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||
int clipmap_index0 = 0;
|
||||
|
||||
vec3 aniso_direction = -dir;
|
||||
@ -210,12 +220,13 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
aniso_direction.x > 0.0 ? 0.0 : 1.0,
|
||||
aniso_direction.y > 0.0 ? 2.0 : 3.0,
|
||||
aniso_direction.z > 0.0 ? 4.0 : 5.0
|
||||
) / (6 + DIFFUSE_CONE_COUNT);
|
||||
) / (6 + diffuseConeCount);
|
||||
vec3 direction_weight = abs(dir);
|
||||
|
||||
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
||||
|
||||
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
|
||||
int steps = 0;
|
||||
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount && steps < MAX_CONE_STEPS) {
|
||||
float mipSample = 0.0;
|
||||
float diam = max(voxelSize0, dist * coneCoefficient);
|
||||
float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
|
||||
@ -223,7 +234,9 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
float clipmap_blend = smoothstep(0.0, 1.0, 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);
|
||||
int base = int(clipmap_index * 10);
|
||||
float voxelSize = float(clipmaps[base]);
|
||||
samplePos = (p0 - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
|
||||
samplePos = samplePos * 0.5 + 0.5;
|
||||
|
||||
if ((any(notEqual(clamp(samplePos, 0.0, 1.0), samplePos)))) {
|
||||
@ -239,8 +252,11 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
|
||||
mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
|
||||
if(totalBlend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
if(totalBlend > 0.05 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
int baseNext = int((clipmap_index + 1.0) * 10);
|
||||
float voxelSizeCoarse = float(clipmaps[baseNext]);
|
||||
mipSampleNext *= voxelSizeCoarse / voxelSize;
|
||||
mipSample = mix(mipSample, mipSampleNext, totalBlend);
|
||||
}
|
||||
|
||||
@ -248,6 +264,7 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
|
||||
step_dist = diam * step_size;
|
||||
dist += step_dist;
|
||||
steps++;
|
||||
}
|
||||
return sampleCol;
|
||||
}
|
||||
@ -256,18 +273,18 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
||||
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];
|
||||
for (int i = 0; i < diffuseConeCount; i++) {
|
||||
vec3 coneDir = diffuseConeDirections[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;
|
||||
amount += traceConeAO(voxels, origin, normal, coneDir, precomputed_direction, diffuseConeAperture, 1.0, clipmaps) * cosTheta;
|
||||
sum += cosTheta;
|
||||
}
|
||||
amount /= max(sum, 0.0001);
|
||||
amount = clamp(amount, 0.0, 1.0);
|
||||
return amount * voxelgiOcc;
|
||||
return amount;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -278,7 +295,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
float dist = voxelSize0;
|
||||
float step_dist = dist;
|
||||
vec3 samplePos;
|
||||
vec3 start_pos = origin + n * voxelSize0;
|
||||
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||
int clipmap_index0 = 0;
|
||||
|
||||
vec3 aniso_direction = -dir;
|
||||
@ -286,11 +303,13 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
aniso_direction.x > 0.0 ? 0.0 : 1.0,
|
||||
aniso_direction.y > 0.0 ? 2.0 : 3.0,
|
||||
aniso_direction.z > 0.0 ? 4.0 : 5.0
|
||||
) / (6 + DIFFUSE_CONE_COUNT);
|
||||
) / (6 + diffuseConeCount);
|
||||
vec3 direction_weight = abs(dir);
|
||||
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
||||
|
||||
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
|
||||
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
int steps = 0;
|
||||
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount && steps < MAX_CONE_STEPS) {
|
||||
float mipSample = 0.0;
|
||||
float diam = max(voxelSize0, dist * coneCoefficient);
|
||||
float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
|
||||
@ -298,7 +317,9 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
float clipmap_blend = smoothstep(0.0, 1.0, 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);
|
||||
int base = int(clipmap_index * 10);
|
||||
float voxelSize = float(clipmaps[base]);
|
||||
samplePos = (p0 - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
|
||||
samplePos = samplePos * 0.5 + 0.5;
|
||||
|
||||
if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) {
|
||||
@ -318,11 +339,14 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, 0, face_offset, direction_weight).a;
|
||||
#endif
|
||||
|
||||
if(totalBlend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
if(totalBlend > 0.05 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
int baseNext = int((clipmap_index + 1.0) * 10);
|
||||
float voxelSizeCoarse = float(clipmaps[baseNext]);
|
||||
float scaleRatio = voxelSizeCoarse / voxelSize;
|
||||
#ifdef _VoxelAOvar
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight);
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight) * scaleRatio;
|
||||
#else
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight).a;
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight).a * scaleRatio;
|
||||
#endif
|
||||
mipSample = mix(mipSample, mipSampleNext, totalBlend);
|
||||
}
|
||||
@ -331,8 +355,6 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
|
||||
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;
|
||||
@ -340,6 +362,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
|
||||
step_dist = diam * stepSizeCurrent;
|
||||
dist += step_dist;
|
||||
steps++;
|
||||
}
|
||||
return sampleCol;
|
||||
}
|
||||
@ -347,7 +370,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
||||
|
||||
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, const vec2 velocity) {
|
||||
vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
|
||||
float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, SHADOW_CONE_APERTURE, voxelgiStep, clipmaps);
|
||||
float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, voxelgiAperture, voxelgiStep, clipmaps);
|
||||
amount = clamp(amount, 0.0, 1.0);
|
||||
return amount * voxelgiOcc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user