Skip to content

Commit

Permalink
#13: Crude ability to bake DDGI atlases per tile
Browse files Browse the repository at this point in the history
  • Loading branch information
Anecoz committed Dec 18, 2023
1 parent 06161e3 commit 7622545
Show file tree
Hide file tree
Showing 66 changed files with 724 additions and 91 deletions.
Binary file modified assets/bilateral_filter_comp.spv
Binary file not shown.
Binary file modified assets/bloom_composite_comp.spv
Binary file not shown.
Binary file modified assets/bloom_prefilter_comp.spv
Binary file not shown.
Binary file modified assets/cull_comp.spv
Binary file not shown.
Binary file modified assets/debug_spheres_frag.spv
Binary file not shown.
Binary file modified assets/debug_spheres_vert.spv
Binary file not shown.
Binary file modified assets/deferred_cluster_comp.spv
Binary file not shown.
Binary file modified assets/deferred_pbr_frag.spv
Binary file not shown.
Binary file modified assets/deferred_tiled_comp.spv
Binary file not shown.
Binary file modified assets/grass_frag.spv
Binary file not shown.
Binary file modified assets/grass_vert.spv
Binary file not shown.
Binary file modified assets/hiz_comp.spv
Binary file not shown.
Binary file modified assets/irradiance_probe_update_rchit.spv
Binary file not shown.
Binary file modified assets/irradiance_probe_update_rgen.spv
Binary file not shown.
Binary file modified assets/irradiance_probe_update_rmiss.spv
Binary file not shown.
Binary file modified assets/light_shadow_rchit.spv
Binary file not shown.
Binary file modified assets/light_shadow_rgen.spv
Binary file not shown.
Binary file modified assets/light_shadow_sum_comp.spv
Binary file not shown.
Binary file modified assets/luminance_average_comp.spv
Binary file not shown.
Binary file modified assets/luminance_histogram_comp.spv
Binary file not shown.
Binary file modified assets/mirror_reflections_rchit.spv
Binary file not shown.
Binary file modified assets/mirror_reflections_rgen.spv
Binary file not shown.
Binary file modified assets/mirror_reflections_rmiss.spv
Binary file not shown.
Binary file modified assets/particle_update_comp.spv
Binary file not shown.
Binary file modified assets/pp_fxaa_frag.spv
Binary file not shown.
Binary file modified assets/probe_conv_comp.spv
Binary file not shown.
34 changes: 33 additions & 1 deletion assets/shaders/bindless.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable

#define TILE_PAGE_RADIUS 0
#define TILE_SIZE 32

struct Renderable
{
mat4 transform;
Expand All @@ -20,6 +23,11 @@ struct Light
vec4 color; // w is enabled or not
};

struct TileInfo
{
int ddgiAtlasTex;
};

struct PointLightShadowCube
{
mat4 shadowMatrices[6]; // Front, back, up, down, right, left where "front" is +x
Expand Down Expand Up @@ -160,7 +168,11 @@ layout(std430, set = 0, binding = 13) readonly buffer SkeletonBuffer {
mat4 joints[];
} skeletonBuffer;

layout(set = 0, binding = 14) uniform sampler2D textures[];
layout(std430, set = 0, binding = 14) readonly buffer TileInfoBuffer {
TileInfo tiles[];
} tileInfoBuffer;

layout(set = 0, binding = 15) uniform sampler2D textures[];

SurfaceData getSurfaceDataFromMat(MaterialInfo matInfo, vec2 uv, vec3 inNormal, mat3 inTBN, vec3 inTangent, vec3 inColor)
{
Expand Down Expand Up @@ -262,4 +274,24 @@ vec4 constructBoundingSphere(MeshInfo meshInfo)
float radius = distance(meshInfo.minPos.xyz, meshInfo.maxPos.xyz) / 2.0;

return vec4(center, radius);
}

// Returns -1 if there is no tile info for this pos, else an index into the tileinfo buffer
int worldPosToTileInfo(vec3 worldPos, vec3 camPos, out ivec2 idx)
{
const int w = TILE_PAGE_RADIUS * 2 + 1;
idx = ivec2(int(floor(worldPos.x/TILE_SIZE)), int(floor(worldPos.z/TILE_SIZE)));
ivec2 cameraIdx = ivec2(int(floor(camPos.x/TILE_SIZE)), int(floor(camPos.z/TILE_SIZE)));

// Are we outside of radius?
if (idx.x - cameraIdx.x > TILE_PAGE_RADIUS ||
idx.y - cameraIdx.y > TILE_PAGE_RADIUS) {
return -1;
}

// Else convert to cam-relative index
ivec2 camRelativeIdx = idx - cameraIdx;
ivec2 fixedIdx = camRelativeIdx + TILE_PAGE_RADIUS; // from 0 instead of -r

return fixedIdx.y * w + fixedIdx.x;
}
39 changes: 29 additions & 10 deletions assets/shaders/deferred_tiled.comp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#version 450

#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_nonuniform_qualifier : enable

layout (local_size_x = 32, local_size_y = 32) in;

Expand Down Expand Up @@ -258,19 +259,37 @@ void doLight(ivec2 pixel)
}
}

if (checkUboFlag(UBO_DDGI_FLAG)) {
if (distance(ubo.cameraPos.xyz, fragWorldPos) > NUM_PROBES_PER_PLANE * PROBE_STEP.x / 2.0) {
// Check if we have a DDGI atlas
ivec2 tIdx = ivec2(0, 0);
int tileBufIdx = worldPosToTileInfo(fragWorldPos, ubo.cameraPos.xyz, tIdx);
int atlasIdx = tileInfoBuffer.tiles[tileBufIdx].ddgiAtlasTex;
bool ddgiAtlas = tileBufIdx >= 0 && atlasIdx >= 0;

if (checkUboFlag(UBO_DDGI_FLAG) || ddgiAtlas) {
if (!ddgiAtlas && distance(ubo.cameraPos.xyz, fragWorldPos) > NUM_PROBES_PER_PLANE * PROBE_STEP.x / 2.0) {
ambient += ubo.skyIntensity * vec3(0.3) * albedo * clamp(shadow, 0.3, 1.0);
}
else {
ambient += calcIndirectDiffuseLight(
normal,
albedo,
metallic,
roughness,
fragWorldPos,
ubo.cameraPos.xyz,
probeTex);
if (ddgiAtlas) {
ambient += calcIndirectDiffuseLight(
normal,
albedo,
metallic,
roughness,
fragWorldPos,
ubo.cameraPos.xyz,
textures[nonuniformEXT(atlasIdx)]);
}
else {
ambient += calcIndirectDiffuseLight(
normal,
albedo,
metallic,
roughness,
fragWorldPos,
ubo.cameraPos.xyz,
probeTex);
}
}
}
else {
Expand Down
3 changes: 0 additions & 3 deletions assets/shaders/irradiance_probe_update.rchit
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,12 @@ void main()
1 // payload (location = 1)
);

//payload.irradiance = shadowPayload.shadow < 0.5 ? vec3(0.0) : vec3(1.0);

// proceed to calculate our radiance
MaterialInfo matInfo = materialBuffer.infos[materialIndex];
vec2 uv = v0.uv.xy * barycentrics.x + v1.uv.xy * barycentrics.y + v2.uv.xy * barycentrics.z;
vec3 normal = normalize(v0.normal.xyz * barycentrics.x + v1.normal.xyz * barycentrics.y + v2.normal.xyz * barycentrics.z);
normal = normalize(vec3(normal.xyz * gl_WorldToObjectEXT));
vec3 color = v0.color.xyz * barycentrics.x + v1.color.xyz * barycentrics.y + v2.color.xyz * barycentrics.z;
//vec3 tangent = v0.tangent.xyz * barycentrics.x + v1.tangent.xyz * barycentrics.y + v2.tangent.xyz * barycentrics.z;
color = toLinear(vec4(color, 1.0)).rgb;

SurfaceData surfData = getSurfaceDataFromMat(matInfo, uv, normal, mat3(0.0), vec3(0.0), color);
Expand Down
36 changes: 25 additions & 11 deletions assets/shaders/irradiance_probe_update.rgen
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,37 @@ void main()
ivec2 pixel = ivec2(gl_LaunchIDEXT.xy);

int probeX = pixel.x / PROBE_IRR_DIR_PIX_SIZE;
int probeY = int(pc.probeLayer);//pixel.y / (PROBE_IRR_DIR_PIX_SIZE * NUM_PROBES_PER_PLANE); // THIS IS THE HEIGHT, AKA PLANE!
int probeZ = pixel.y / PROBE_IRR_DIR_PIX_SIZE;//(pixel.y - (probeY * PROBE_IRR_DIR_PIX_SIZE * NUM_PROBES_PER_PLANE)) / PROBE_IRR_DIR_PIX_SIZE;
int probeY = int(pc.probeLayer);
int probeZ = pixel.y / PROBE_IRR_DIR_PIX_SIZE;

ivec2 pixelWithinProbe = ivec2(pixel.x - probeX * PROBE_IRR_DIR_PIX_SIZE, pixel.y - probeZ * PROBE_IRR_DIR_PIX_SIZE);
int rayIndex = pixelWithinProbe.y * PROBE_IRR_DIR_PIX_SIZE + pixelWithinProbe.x;

ivec2 camProbeIdx =
ivec2(int(ubo.cameraPos.x / PROBE_STEP.x), int(ubo.cameraPos.z / PROBE_STEP.z));
vec3 origin = vec3(0.0);
if (checkUboFlag(UBO_BAKE_MODE_ON_FLAG)) {
// If we're baking, use the tile info to figure out where the current probe is located
const int tSize = ubo.bakeTileInfo.z;
const ivec2 tIdx = ubo.bakeTileInfo.xy;
const vec3 scale = vec3(
float(tSize) / float(NUM_PROBES_PER_PLANE),
1.0,
float(tSize) / float(NUM_PROBES_PER_PLANE));

vec3 camOffset = vec3(
float(camProbeIdx.x) * PROBE_STEP.x - PROBE_STEP.x * float(NUM_PROBES_PER_PLANE)/2.0,
0.0,
float(camProbeIdx.y) * PROBE_STEP.z - PROBE_STEP.z * float(NUM_PROBES_PER_PLANE)/2.0);
const vec3 tileOffset = vec3(float(tIdx.x) * float(tSize), 0.0, float(tIdx.y) * float(tSize));

vec3 origin = vec3(float(probeX), float(probeY), float(probeZ)) * PROBE_STEP + camOffset;
origin = vec3(float(probeX), float(probeY), float(probeZ)) * scale + tileOffset;
}
else {
ivec2 camProbeIdx =
ivec2(int(ubo.cameraPos.x / PROBE_STEP.x), int(ubo.cameraPos.z / PROBE_STEP.z));

vec3 camOffset = vec3(
float(camProbeIdx.x) * PROBE_STEP.x - PROBE_STEP.x * float(NUM_PROBES_PER_PLANE)/2.0,
0.0,
float(camProbeIdx.y) * PROBE_STEP.z - PROBE_STEP.z * float(NUM_PROBES_PER_PLANE)/2.0);

origin = vec3(float(probeX), float(probeY), float(probeZ)) * PROBE_STEP + camOffset;
}

// Create a directional vector from the "ray index"
vec3 worldDir = worldDirFromFibonacciIndex(rayIndex);
Expand All @@ -89,8 +105,6 @@ void main()
tMax, // ray max range
0); // payload (location = 0)

//vec3 packedDir = (worldDir.xyz + 1.0) * 0.5;
//imageStore(dirIm, pixel, vec4(packedDir, 1.0));
imageStore(dirIm, pixel, vec4(worldDir.xyz, 1.0));
imageStore(irradianceIm, pixel, vec4(payload.irradiance.rgb, 1.0));

Expand Down
105 changes: 71 additions & 34 deletions assets/shaders/pbr_light.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -177,27 +177,15 @@ vec3 sampleSingleProbe(sampler2D probeTex, ivec3 probeIndex, vec3 normal)

ivec2 probePixelEnd = probePixelStart + PROBE_CONV_PIX_SIZE - 1;

/*vec2 probeTexStart = vec2(
(float(probePixelStart.x) + 0.5) / float(probeTexSize.x),
(float(probePixelStart.y) + 0.5) / float(probeTexSize.y));*/

vec2 probeTexStart = pixelToUv(probePixelStart, probeTexSize);

/*vec2 probeTexEnd = vec2(
(float(probePixelEnd.x) + 0.5) / float(probeTexSize.x),
(float(probePixelEnd.y) + 0.5) / float(probeTexSize.y));*/

vec2 probeTexEnd = pixelToUv(probePixelEnd, probeTexSize);

// This returns on -1 to 1, so change to 0 to 1
vec2 oct = octEncode(normalize(normal));
oct = (oct + vec2(1.0)) * 0.5;
//oct = clamp(oct, vec2(0.05), vec2(0.95));

vec2 octTexCoord = probeTexStart + (probeTexEnd - probeTexStart) * oct;

//vec4 irr = texture(probeTex, octTexCoord);
//return irr.rgb / irr.w;
return texture(probeTex, octTexCoord).rgb;
}

Expand Down Expand Up @@ -254,67 +242,116 @@ vec4 weightProbe(sampler2D probeTex, vec3 worldPos, vec3 probePos, vec3 normal,
vec3 sampleProbe(sampler2D probeTex, vec3 worldPos, vec3 normal)
{
// Find closest probe to worldPos
ivec2 camProbeIdx =
ivec2(int(ubo.cameraPos.x / PROBE_STEP.x), int(ubo.cameraPos.z / PROBE_STEP.z));
int probeX = 0;
int probeY = 0;
int probeZ = 0;

vec3 baseProbePos = vec3(0.0);

vec3 probeStep = PROBE_STEP;

// Do we have a baked atlas?
ivec2 tIdx = ivec2(0, 0);
int tileBufIdx = worldPosToTileInfo(worldPos, ubo.cameraPos.xyz, tIdx);
int atlasIdx = -1;
if (tileBufIdx >= 0) {
atlasIdx = tileInfoBuffer.tiles[tileBufIdx].ddgiAtlasTex;
}
bool ddgiAtlas = tileBufIdx >= 0 && atlasIdx >= 0;

if (ddgiAtlas) {
const int tSize = TILE_SIZE;
const vec3 tileOffset = vec3(float(tIdx.x) * float(tSize), 0.0, float(tIdx.y) * float(tSize));

vec3 camOffset = vec3(
float(camProbeIdx.x) * PROBE_STEP.x - PROBE_STEP.x * float(NUM_PROBES_PER_PLANE) / 2.0,
0.0,
float(camProbeIdx.y) * PROBE_STEP.z - PROBE_STEP.z * float(NUM_PROBES_PER_PLANE) / 2.0);
//vec3 camOffset = vec3(ubo.cameraGridPos.x - PROBE_STEP.x * float(NUM_PROBES_PER_PLANE) / 2.0, 0.0, ubo.cameraGridPos.z - PROBE_STEP.z * float(NUM_PROBES_PER_PLANE) / 2.0);
//vec3 camOffset = vec3(0.0);
//vec3 camOffset = vec3(floor(ubo.cameraPos.x) - float(NUM_PROBES_PER_PLANE) / 2.0, 0.0, floor(ubo.cameraPos.z) - float(NUM_PROBES_PER_PLANE) / 2.0);
probeStep = vec3(
float(tSize) / float(NUM_PROBES_PER_PLANE),
1.0,
float(tSize) / float(NUM_PROBES_PER_PLANE));

int probeX = clamp(int(floor((worldPos.x - camOffset.x) / PROBE_STEP.x)), 0, NUM_PROBES_PER_PLANE - 1);
int probeY = clamp(int(floor(worldPos.y / PROBE_STEP.y)), 0, NUM_PROBE_PLANES - 1);
int probeZ = clamp(int(floor((worldPos.z - camOffset.z) / PROBE_STEP.z)), 0, NUM_PROBES_PER_PLANE - 1);
vec3 posInTile = worldPos - tileOffset;
probeX = clamp(int(floor(posInTile.x / probeStep.x)), 0, NUM_PROBES_PER_PLANE - 1);
probeY = clamp(int(floor(posInTile.y / probeStep.y)), 0, NUM_PROBE_PLANES - 1);
probeZ = clamp(int(floor(posInTile.z / probeStep.z)), 0, NUM_PROBES_PER_PLANE - 1);

//vec3 baseProbePos = vec3(probeX + camOffset.x, probeY * 2.0, probeZ + camOffset.z);
vec3 baseProbePos = vec3(probeX, probeY, probeZ) * PROBE_STEP + camOffset;
baseProbePos = vec3(probeX, probeY, probeZ) * probeStep + tileOffset;
}
else if (checkUboFlag(UBO_BAKE_MODE_ON_FLAG)) {
// If we're baking, use the tile information to find the closest probe
const int tSize = ubo.bakeTileInfo.z;
const ivec2 tIdx = ubo.bakeTileInfo.xy;
const vec3 tileOffset = vec3(float(tIdx.x) * float(tSize), 0.0, float(tIdx.y) * float(tSize));

probeStep = vec3(
float(tSize) / float(NUM_PROBES_PER_PLANE),
1.0,
float(tSize) / float(NUM_PROBES_PER_PLANE));

vec3 posInTile = worldPos - tileOffset;
probeX = clamp(int(floor(posInTile.x / probeStep.x)), 0, NUM_PROBES_PER_PLANE - 1);
probeY = clamp(int(floor(posInTile.y / probeStep.y)), 0, NUM_PROBE_PLANES - 1);
probeZ = clamp(int(floor(posInTile.z / probeStep.z)), 0, NUM_PROBES_PER_PLANE - 1);

baseProbePos = vec3(probeX, probeY, probeZ) * probeStep + tileOffset;
}
else {
ivec2 camProbeIdx =
ivec2(int(ubo.cameraPos.x / PROBE_STEP.x), int(ubo.cameraPos.z / PROBE_STEP.z));

vec3 camOffset = vec3(
float(camProbeIdx.x) * PROBE_STEP.x - PROBE_STEP.x * float(NUM_PROBES_PER_PLANE) / 2.0,
0.0,
float(camProbeIdx.y) * PROBE_STEP.z - PROBE_STEP.z * float(NUM_PROBES_PER_PLANE) / 2.0);

probeX = clamp(int(floor((worldPos.x - camOffset.x) / PROBE_STEP.x)), 0, NUM_PROBES_PER_PLANE - 1);
probeY = clamp(int(floor(worldPos.y / PROBE_STEP.y)), 0, NUM_PROBE_PLANES - 1);
probeZ = clamp(int(floor((worldPos.z - camOffset.z) / PROBE_STEP.z)), 0, NUM_PROBES_PER_PLANE - 1);

baseProbePos = vec3(probeX, probeY, probeZ) * PROBE_STEP + camOffset;
}

float sumWeight = 0.0;
vec3 sumIrradiance = vec3(0.0);

// alpha is how far from the floor(currentVertex) position. on [0, 1] for each axis.
vec3 alpha = clamp((worldPos - baseProbePos) / PROBE_STEP, vec3(0.0), vec3(1.0));
vec3 alpha = clamp((worldPos - baseProbePos) / probeStep, vec3(0.0), vec3(1.0));

vec3 probePos = baseProbePos;

vec4 res = weightProbe(probeTex, worldPos, probePos, normal, ivec3(probeX, probeY, probeZ), alpha, ivec3(0));
sumIrradiance += res.w * res.rgb;
sumWeight += res.w;

probePos = baseProbePos + vec3(1.0, 1.0, 1.0) * PROBE_STEP;
probePos = baseProbePos + vec3(1.0, 1.0, 1.0) * probeStep;
res = weightProbe(probeTex, worldPos, probePos, normal, ivec3(probeX + 1, probeY + 1, probeZ + 1), alpha, ivec3(1, 1, 1));
sumIrradiance += res.w * res.rgb;
sumWeight += res.w;

probePos = baseProbePos + vec3(1.0, 1.0, 0.0) * PROBE_STEP;
probePos = baseProbePos + vec3(1.0, 1.0, 0.0) * probeStep;
res = weightProbe(probeTex, worldPos, probePos, normal, ivec3(probeX + 1, probeY + 1, probeZ), alpha, ivec3(1, 1, 0));
sumIrradiance += res.w * res.rgb;
sumWeight += res.w;

probePos = baseProbePos + vec3(1.0, 0.0, 0.0) * PROBE_STEP;
probePos = baseProbePos + vec3(1.0, 0.0, 0.0) * probeStep;
res = weightProbe(probeTex, worldPos, probePos, normal, ivec3(probeX + 1, probeY, probeZ), alpha, ivec3(1, 0, 0));
sumIrradiance += res.w * res.rgb;
sumWeight += res.w;

probePos = baseProbePos + vec3(0.0, 1.0, 1.0) * PROBE_STEP;
probePos = baseProbePos + vec3(0.0, 1.0, 1.0) * probeStep;
res = weightProbe(probeTex, worldPos, probePos, normal, ivec3(probeX, probeY + 1, probeZ + 1), alpha, ivec3(0, 1, 1));
sumIrradiance += res.w * res.rgb;
sumWeight += res.w;

probePos = baseProbePos + vec3(0.0, 1.0, 0.0) * PROBE_STEP;
probePos = baseProbePos + vec3(0.0, 1.0, 0.0) * probeStep;
res = weightProbe(probeTex, worldPos, probePos, normal, ivec3(probeX, probeY + 1, probeZ), alpha, ivec3(0, 1, 0));
sumIrradiance += res.w * res.rgb;
sumWeight += res.w;

probePos = baseProbePos + vec3(0.0, 0.0, 1.0) * PROBE_STEP;
probePos = baseProbePos + vec3(0.0, 0.0, 1.0) * probeStep;
res = weightProbe(probeTex, worldPos, probePos, normal, ivec3(probeX, probeY, probeZ + 1), alpha, ivec3(0, 0, 1));
sumIrradiance += res.w * res.rgb;
sumWeight += res.w;

probePos = baseProbePos + vec3(1.0, 0.0, 1.0) * PROBE_STEP;
probePos = baseProbePos + vec3(1.0, 0.0, 1.0) * probeStep;
res = weightProbe(probeTex, worldPos, probePos, normal, ivec3(probeX + 1, probeY, probeZ + 1), alpha, ivec3(1, 0, 1));
sumIrradiance += res.w * res.rgb;
sumWeight += res.w;
Expand Down
Loading

0 comments on commit 7622545

Please sign in to comment.