mirror of
https://github.com/ZDoom/ZDRay.git
synced 2025-01-26 01:21:02 +00:00
Implement light probe tracing on the GPU
This commit is contained in:
parent
43bdb1cbca
commit
96b31d8a69
6 changed files with 94 additions and 359 deletions
|
@ -175,7 +175,6 @@ set( SOURCES
|
||||||
src/lightmap/glsl_rchit_sun.h
|
src/lightmap/glsl_rchit_sun.h
|
||||||
src/lightmap/glsl_rgen_bounce.h
|
src/lightmap/glsl_rgen_bounce.h
|
||||||
src/lightmap/glsl_rgen_light.h
|
src/lightmap/glsl_rgen_light.h
|
||||||
src/lightmap/glsl_rgen_sun.h
|
|
||||||
src/lightmap/glsl_rmiss_bounce.h
|
src/lightmap/glsl_rmiss_bounce.h
|
||||||
src/lightmap/glsl_rmiss_light.h
|
src/lightmap/glsl_rmiss_light.h
|
||||||
src/lightmap/glsl_rmiss_sun.h
|
src/lightmap/glsl_rmiss_sun.h
|
||||||
|
|
|
@ -59,23 +59,41 @@ void main()
|
||||||
if (PassType != 0)
|
if (PassType != 0)
|
||||||
incoming = imageLoad(outputs, texelPos);
|
incoming = imageLoad(outputs, texelPos);
|
||||||
|
|
||||||
|
vec3 origin = data0.xyz;
|
||||||
int surfaceIndex = int(data0.w);
|
int surfaceIndex = int(data0.w);
|
||||||
if (surfaceIndex >= 0)
|
if (surfaceIndex != -1)
|
||||||
{
|
{
|
||||||
SurfaceInfo surface = surfaces[surfaceIndex];
|
|
||||||
|
|
||||||
vec3 origin = data0.xyz;
|
|
||||||
vec3 normal = surface.Normal;
|
|
||||||
|
|
||||||
if (PassType == 0)
|
if (PassType == 0)
|
||||||
{
|
{
|
||||||
incoming.rgb = surface.EmissiveColor * surface.EmissiveIntensity;
|
if (surfaceIndex >= 0)
|
||||||
|
{
|
||||||
|
SurfaceInfo surface = surfaces[surfaceIndex];
|
||||||
|
incoming.rgb = surface.EmissiveColor * surface.EmissiveIntensity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (PassType == 1)
|
if (PassType == 1)
|
||||||
incoming.w = 1.0f / float(SampleCount);
|
incoming.w = 1.0f / float(SampleCount);
|
||||||
|
|
||||||
|
vec3 normal;
|
||||||
|
if (surfaceIndex >= 0)
|
||||||
|
{
|
||||||
|
normal = surfaces[surfaceIndex].Normal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (SampleIndex % 6)
|
||||||
|
{
|
||||||
|
case 0: normal = vec3( 1.0f, 0.0f, 0.0f); break;
|
||||||
|
case 1: normal = vec3(-1.0f, 0.0f, 0.0f); break;
|
||||||
|
case 2: normal = vec3( 0.0f, 1.0f, 0.0f); break;
|
||||||
|
case 3: normal = vec3( 0.0f, -1.0f, 0.0f); break;
|
||||||
|
case 4: normal = vec3( 0.0f, 0.0f, 1.0f); break;
|
||||||
|
case 5: normal = vec3( 0.0f, 0.0f, -1.0f); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vec3 H = ImportanceSample(normal);
|
vec3 H = ImportanceSample(normal);
|
||||||
vec3 L = normalize(H * (2.0f * dot(normal, H)) - normal);
|
vec3 L = normalize(H * (2.0f * dot(normal, H)) - normal);
|
||||||
|
|
||||||
|
@ -94,7 +112,7 @@ void main()
|
||||||
{
|
{
|
||||||
float hitDistance = distance(origin, payload.hitPosition);
|
float hitDistance = distance(origin, payload.hitPosition);
|
||||||
surfaceIndex = payload.hitSurfaceIndex;
|
surfaceIndex = payload.hitSurfaceIndex;
|
||||||
surface = surfaces[surfaceIndex];
|
SurfaceInfo surface = surfaces[surfaceIndex];
|
||||||
origin = payload.hitPosition;
|
origin = payload.hitPosition;
|
||||||
|
|
||||||
if (surface.EmissiveDistance > 0.0)
|
if (surface.EmissiveDistance > 0.0)
|
||||||
|
@ -107,11 +125,11 @@ void main()
|
||||||
|
|
||||||
incoming.w *= 0.25; // the amount of incoming light the surfaces emit
|
incoming.w *= 0.25; // the amount of incoming light the surfaces emit
|
||||||
}
|
}
|
||||||
|
|
||||||
data0.xyz = origin;
|
|
||||||
data0.w = float(surfaceIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data0.xyz = origin;
|
||||||
|
data0.w = float(surfaceIndex);
|
||||||
|
|
||||||
imageStore(positions, texelPos, data0);
|
imageStore(positions, texelPos, data0);
|
||||||
imageStore(outputs, texelPos, incoming);
|
imageStore(outputs, texelPos, incoming);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,11 +67,12 @@ void main()
|
||||||
vec4 incoming = imageLoad(outputs, texelPos);
|
vec4 incoming = imageLoad(outputs, texelPos);
|
||||||
vec4 data0 = imageLoad(positions, texelPos);
|
vec4 data0 = imageLoad(positions, texelPos);
|
||||||
int surfaceIndex = int(data0.w);
|
int surfaceIndex = int(data0.w);
|
||||||
if (surfaceIndex < 0 || incoming.w <= 0.0)
|
if (surfaceIndex == -1 || incoming.w <= 0.0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SurfaceInfo surface = surfaces[surfaceIndex];
|
vec3 normal;
|
||||||
vec3 normal = surface.Normal;
|
if (surfaceIndex >= 0)
|
||||||
|
normal = surfaces[surfaceIndex].Normal;
|
||||||
|
|
||||||
vec3 origin = data0.xyz + normal * 0.1;
|
vec3 origin = data0.xyz + normal * 0.1;
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ void main()
|
||||||
const float dist = 32768.0;
|
const float dist = 32768.0;
|
||||||
|
|
||||||
float attenuation = 0.0;
|
float attenuation = 0.0;
|
||||||
if (PassType == 0)
|
if (PassType == 0 && surfaceIndex >= 0)
|
||||||
{
|
{
|
||||||
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
||||||
vec3 e1 = cross(normal, e0);
|
vec3 e1 = cross(normal, e0);
|
||||||
|
@ -116,7 +117,11 @@ void main()
|
||||||
vec3 dir = normalize(light.Origin - origin);
|
vec3 dir = normalize(light.Origin - origin);
|
||||||
|
|
||||||
float distAttenuation = max(1.0 - (dist / light.Radius), 0.0);
|
float distAttenuation = max(1.0 - (dist / light.Radius), 0.0);
|
||||||
float angleAttenuation = max(dot(normal, dir), 0.0);
|
float angleAttenuation = 1.0f;
|
||||||
|
if (surfaceIndex >= 0)
|
||||||
|
{
|
||||||
|
angleAttenuation = max(dot(normal, dir), 0.0);
|
||||||
|
}
|
||||||
float spotAttenuation = 1.0;
|
float spotAttenuation = 1.0;
|
||||||
if (light.OuterAngleCos > -1.0)
|
if (light.OuterAngleCos > -1.0)
|
||||||
{
|
{
|
||||||
|
@ -130,7 +135,7 @@ void main()
|
||||||
{
|
{
|
||||||
float shadowAttenuation = 0.0;
|
float shadowAttenuation = 0.0;
|
||||||
|
|
||||||
if (PassType == 0)
|
if (PassType == 0 && surfaceIndex >= 0)
|
||||||
{
|
{
|
||||||
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
||||||
vec3 e1 = cross(normal, e0);
|
vec3 e1 = cross(normal, e0);
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
static const char* glsl_rgen_sun = R"glsl(
|
|
||||||
|
|
||||||
#version 460
|
|
||||||
#extension GL_EXT_ray_tracing : require
|
|
||||||
|
|
||||||
struct hitPayload
|
|
||||||
{
|
|
||||||
vec3 hitPosition;
|
|
||||||
float hitAttenuation;
|
|
||||||
int hitSurfaceIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(location = 0) rayPayloadEXT hitPayload payload;
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform accelerationStructureEXT acc;
|
|
||||||
layout(set = 0, binding = 1, rgba32f) uniform image2D startpositions;
|
|
||||||
layout(set = 0, binding = 2, rgba32f) uniform image2D positions;
|
|
||||||
layout(set = 0, binding = 3, rgba32f) uniform image2D outputs;
|
|
||||||
|
|
||||||
layout(set = 0, binding = 4) uniform Uniforms
|
|
||||||
{
|
|
||||||
uint SampleIndex;
|
|
||||||
uint SampleCount;
|
|
||||||
uint PassType;
|
|
||||||
uint LightCount;
|
|
||||||
vec3 SunDir;
|
|
||||||
float SampleDistance;
|
|
||||||
vec3 SunColor;
|
|
||||||
float SunIntensity;
|
|
||||||
vec3 HemisphereVec;
|
|
||||||
float Padding1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SurfaceInfo
|
|
||||||
{
|
|
||||||
vec3 Normal;
|
|
||||||
float EmissiveDistance;
|
|
||||||
vec3 EmissiveColor;
|
|
||||||
float EmissiveIntensity;
|
|
||||||
float Sky;
|
|
||||||
float Padding0, Padding1, Padding2;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(set = 0, binding = 6) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
|
|
||||||
|
|
||||||
vec2 Hammersley(uint i, uint N);
|
|
||||||
float RadicalInverse_VdC(uint bits);
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
ivec2 texelPos = ivec2(gl_LaunchIDEXT.xy);
|
|
||||||
vec4 incoming = imageLoad(outputs, texelPos);
|
|
||||||
vec4 data0 = imageLoad(positions, texelPos);
|
|
||||||
int surfaceIndex = int(data0.w);
|
|
||||||
if (surfaceIndex < 0 || incoming.w <= 0.0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SurfaceInfo surface = surfaces[surfaceIndex];
|
|
||||||
vec3 normal = surface.Normal;
|
|
||||||
|
|
||||||
vec3 origin = data0.xyz;
|
|
||||||
origin += normal * 0.1;
|
|
||||||
|
|
||||||
const float minDistance = 0;
|
|
||||||
const float dist = 32768.0;
|
|
||||||
|
|
||||||
float attenuation = 0.0;
|
|
||||||
if (PassType == 0)
|
|
||||||
{
|
|
||||||
vec3 e0 = cross(normal, abs(normal.x) < abs(normal.y) ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0));
|
|
||||||
vec3 e1 = cross(normal, e0);
|
|
||||||
e0 = cross(normal, e1);
|
|
||||||
|
|
||||||
for (uint i = 0; i < SampleCount; i++)
|
|
||||||
{
|
|
||||||
vec2 offset = (Hammersley(i, SampleCount) - 0.5) * SampleDistance;
|
|
||||||
vec3 origin2 = origin + offset.x * e0 + offset.y * e1;
|
|
||||||
|
|
||||||
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 2, 0, 2, origin2, minDistance, SunDir, dist, 0);
|
|
||||||
attenuation += payload.hitAttenuation;
|
|
||||||
}
|
|
||||||
attenuation *= 1.0 / float(SampleCount);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
traceRayEXT(acc, gl_RayFlagsOpaqueEXT, 0xff, 2, 0, 2, origin, minDistance, SunDir, dist, 0);
|
|
||||||
attenuation = payload.hitAttenuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
incoming.rgb += SunColor * (attenuation * SunIntensity) * incoming.w;
|
|
||||||
imageStore(outputs, texelPos, incoming);
|
|
||||||
}
|
|
||||||
|
|
||||||
float RadicalInverse_VdC(uint bits)
|
|
||||||
{
|
|
||||||
bits = (bits << 16u) | (bits >> 16u);
|
|
||||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
|
||||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
|
||||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
|
||||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
|
||||||
return float(bits) * 2.3283064365386963e-10f; // / 0x100000000
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 Hammersley(uint i, uint N)
|
|
||||||
{
|
|
||||||
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
)glsl";
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include "glsl_rgen_bounce.h"
|
#include "glsl_rgen_bounce.h"
|
||||||
#include "glsl_rgen_light.h"
|
#include "glsl_rgen_light.h"
|
||||||
#include "glsl_rgen_sun.h"
|
|
||||||
#include "glsl_rchit_bounce.h"
|
#include "glsl_rchit_bounce.h"
|
||||||
#include "glsl_rchit_light.h"
|
#include "glsl_rchit_light.h"
|
||||||
#include "glsl_rchit_sun.h"
|
#include "glsl_rchit_sun.h"
|
||||||
|
@ -46,15 +45,15 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
||||||
|
|
||||||
CreateVulkanObjects();
|
CreateVulkanObjects();
|
||||||
|
|
||||||
printf("Tracing light probes\n");
|
std::vector<TraceTask> tasks;
|
||||||
|
for (size_t i = 0; i < mesh->lightProbes.size(); i++)
|
||||||
Worker::RunJob((int)mesh->lightProbes.size(), [=](int id) {
|
{
|
||||||
RaytraceProbeSample(&mesh->lightProbes[id]);
|
TraceTask task;
|
||||||
});
|
task.id = -(int)(i + 2);
|
||||||
|
task.x = 0;
|
||||||
printf("Tracing surfaces, %d bounce(s)\n", LightBounce);
|
task.y = 0;
|
||||||
|
tasks.push_back(task);
|
||||||
std::vector<SurfaceTask> tasks;
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
for (size_t i = 0; i < mesh->surfaces.size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -65,8 +64,8 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < sampleWidth; x++)
|
for (int x = 0; x < sampleWidth; x++)
|
||||||
{
|
{
|
||||||
SurfaceTask task;
|
TraceTask task;
|
||||||
task.surf = (int)i;
|
task.id = (int)i;
|
||||||
task.x = x;
|
task.x = x;
|
||||||
task.y = y;
|
task.y = y;
|
||||||
tasks.push_back(task);
|
tasks.push_back(task);
|
||||||
|
@ -87,6 +86,8 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
||||||
HemisphereVectors.push_back(H);
|
HemisphereVectors.push_back(H);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("Ray tracing with %d bounce(s)\n", LightBounce);
|
||||||
|
|
||||||
size_t maxTasks = (size_t)rayTraceImageSize * rayTraceImageSize;
|
size_t maxTasks = (size_t)rayTraceImageSize * rayTraceImageSize;
|
||||||
for (size_t startTask = 0; startTask < tasks.size(); startTask += maxTasks)
|
for (size_t startTask = 0; startTask < tasks.size(); startTask += maxTasks)
|
||||||
{
|
{
|
||||||
|
@ -102,9 +103,9 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
||||||
uniforms.SunColor = mesh->map->GetSunColor();
|
uniforms.SunColor = mesh->map->GetSunColor();
|
||||||
uniforms.SunIntensity = 1.0f;
|
uniforms.SunIntensity = 1.0f;
|
||||||
|
|
||||||
|
uniforms.PassType = 0;
|
||||||
uniforms.SampleIndex = 0;
|
uniforms.SampleIndex = 0;
|
||||||
uniforms.SampleCount = bounceSampleCount;
|
uniforms.SampleCount = bounceSampleCount;
|
||||||
uniforms.PassType = 0;
|
|
||||||
RunTrace(uniforms, rgenBounceRegion);
|
RunTrace(uniforms, rgenBounceRegion);
|
||||||
|
|
||||||
uniforms.SampleCount = coverageSampleCount;
|
uniforms.SampleCount = coverageSampleCount;
|
||||||
|
@ -124,8 +125,8 @@ void GPURaytracer::Raytrace(LevelMesh* level)
|
||||||
RunTrace(uniforms, rgenLightRegion);
|
RunTrace(uniforms, rgenLightRegion);
|
||||||
|
|
||||||
uniforms.PassType = 2;
|
uniforms.PassType = 2;
|
||||||
uniforms.SampleCount = bounceSampleCount;
|
|
||||||
uniforms.SampleIndex = (i + bounce) % uniforms.SampleCount;
|
uniforms.SampleIndex = (i + bounce) % uniforms.SampleCount;
|
||||||
|
uniforms.SampleCount = bounceSampleCount;
|
||||||
uniforms.HemisphereVec = HemisphereVectors[uniforms.SampleIndex];
|
uniforms.HemisphereVec = HemisphereVectors[uniforms.SampleIndex];
|
||||||
RunTrace(uniforms, rgenBounceRegion);
|
RunTrace(uniforms, rgenBounceRegion);
|
||||||
}
|
}
|
||||||
|
@ -159,7 +160,7 @@ void GPURaytracer::CreateVulkanObjects()
|
||||||
finishbuildbarrier.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
|
finishbuildbarrier.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPURaytracer::UploadTasks(const SurfaceTask* tasks, size_t size)
|
void GPURaytracer::UploadTasks(const TraceTask* tasks, size_t size)
|
||||||
{
|
{
|
||||||
if (!cmdbuffer)
|
if (!cmdbuffer)
|
||||||
{
|
{
|
||||||
|
@ -176,12 +177,20 @@ void GPURaytracer::UploadTasks(const SurfaceTask* tasks, size_t size)
|
||||||
Vec4* startPositions = (Vec4*)imageData;
|
Vec4* startPositions = (Vec4*)imageData;
|
||||||
for (size_t i = 0; i < size; i++)
|
for (size_t i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
const SurfaceTask& task = tasks[i];
|
const TraceTask& task = tasks[i];
|
||||||
Surface* surface = mesh->surfaces[task.surf].get();
|
|
||||||
|
|
||||||
Vec3 pos = surface->lightmapOrigin + surface->lightmapSteps[0] * (float)task.x + surface->lightmapSteps[1] * (float)task.y;
|
if (task.id >= 0)
|
||||||
|
{
|
||||||
|
Surface* surface = mesh->surfaces[task.id].get();
|
||||||
|
Vec3 pos = surface->lightmapOrigin + surface->lightmapSteps[0] * (float)task.x + surface->lightmapSteps[1] * (float)task.y;
|
||||||
|
startPositions[i] = Vec4(pos, (float)task.id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LightProbeSample& probe = mesh->lightProbes[(size_t)(-task.id) - 2];
|
||||||
|
startPositions[i] = Vec4(probe.Position, (float)-2);
|
||||||
|
}
|
||||||
|
|
||||||
startPositions[i] = Vec4(pos, (float)task.surf);
|
|
||||||
}
|
}
|
||||||
for (size_t i = size; i < maxTasks; i++)
|
for (size_t i = size; i < maxTasks; i++)
|
||||||
{
|
{
|
||||||
|
@ -276,7 +285,7 @@ void GPURaytracer::SubmitCommands()
|
||||||
cmdbuffer.reset();
|
cmdbuffer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPURaytracer::DownloadTasks(const SurfaceTask* tasks, size_t size)
|
void GPURaytracer::DownloadTasks(const TraceTask* tasks, size_t size)
|
||||||
{
|
{
|
||||||
PipelineBarrier barrier4;
|
PipelineBarrier barrier4;
|
||||||
barrier4.addImage(outputImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
|
barrier4.addImage(outputImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
|
||||||
|
@ -299,11 +308,18 @@ void GPURaytracer::DownloadTasks(const SurfaceTask* tasks, size_t size)
|
||||||
Vec4* output = (Vec4*)imageData;
|
Vec4* output = (Vec4*)imageData;
|
||||||
for (size_t i = 0; i < size; i++)
|
for (size_t i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
const SurfaceTask& task = tasks[i];
|
const TraceTask& task = tasks[i];
|
||||||
Surface* surface = mesh->surfaces[task.surf].get();
|
if (task.id >= 0)
|
||||||
|
{
|
||||||
size_t sampleWidth = surface->lightmapDims[0];
|
Surface* surface = mesh->surfaces[task.id].get();
|
||||||
surface->samples[task.x + task.y * sampleWidth] = Vec3(output[i].x, output[i].y, output[i].z);
|
size_t sampleWidth = surface->lightmapDims[0];
|
||||||
|
surface->samples[task.x + task.y * sampleWidth] = Vec3(output[i].x, output[i].y, output[i].z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LightProbeSample& probe = mesh->lightProbes[(size_t)(-task.id) - 2];
|
||||||
|
probe.Color = Vec3(output[i].x, output[i].y, output[i].z);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
imageTransferBuffer->Unmap();
|
imageTransferBuffer->Unmap();
|
||||||
}
|
}
|
||||||
|
@ -412,7 +428,7 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
||||||
BufferBuilder lbuilder;
|
BufferBuilder lbuilder;
|
||||||
lbuilder.setUsage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
lbuilder.setUsage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||||
lbuilder.setSize(lightbuffersize);
|
lbuilder.setSize(lightbuffersize);
|
||||||
lightBuffer = sbuilder.create(device.get());
|
lightBuffer = lbuilder.create(device.get());
|
||||||
lightBuffer->SetDebugName("lightBuffer");
|
lightBuffer->SetDebugName("lightBuffer");
|
||||||
|
|
||||||
BufferBuilder tbuilder;
|
BufferBuilder tbuilder;
|
||||||
|
@ -612,7 +628,6 @@ void GPURaytracer::CreateShaders()
|
||||||
{
|
{
|
||||||
rgenBounce = CompileRayGenShader(glsl_rgen_bounce, "rgen.bounce");
|
rgenBounce = CompileRayGenShader(glsl_rgen_bounce, "rgen.bounce");
|
||||||
rgenLight = CompileRayGenShader(glsl_rgen_light, "rgen.light");
|
rgenLight = CompileRayGenShader(glsl_rgen_light, "rgen.light");
|
||||||
rgenSun = CompileRayGenShader(glsl_rgen_sun, "rgen.sun");
|
|
||||||
rchitBounce = CompileClosestHitShader(glsl_rchit_bounce, "rchit.bounce");
|
rchitBounce = CompileClosestHitShader(glsl_rchit_bounce, "rchit.bounce");
|
||||||
rchitLight = CompileClosestHitShader(glsl_rchit_light, "rchit.light");
|
rchitLight = CompileClosestHitShader(glsl_rchit_light, "rchit.light");
|
||||||
rchitSun = CompileClosestHitShader(glsl_rchit_sun, "rchit.sun");
|
rchitSun = CompileClosestHitShader(glsl_rchit_sun, "rchit.sun");
|
||||||
|
@ -693,7 +708,6 @@ void GPURaytracer::CreatePipeline()
|
||||||
builder.setMaxPipelineRayRecursionDepth(1);
|
builder.setMaxPipelineRayRecursionDepth(1);
|
||||||
builder.addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenBounce.get());
|
builder.addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenBounce.get());
|
||||||
builder.addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenLight.get());
|
builder.addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenLight.get());
|
||||||
builder.addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenSun.get());
|
|
||||||
builder.addShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissBounce.get());
|
builder.addShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissBounce.get());
|
||||||
builder.addShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissLight.get());
|
builder.addShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissLight.get());
|
||||||
builder.addShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissSun.get());
|
builder.addShader(VK_SHADER_STAGE_MISS_BIT_KHR, rmissSun.get());
|
||||||
|
@ -702,13 +716,12 @@ void GPURaytracer::CreatePipeline()
|
||||||
builder.addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, rchitSun.get());
|
builder.addShader(VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, rchitSun.get());
|
||||||
builder.addRayGenGroup(0);
|
builder.addRayGenGroup(0);
|
||||||
builder.addRayGenGroup(1);
|
builder.addRayGenGroup(1);
|
||||||
builder.addRayGenGroup(2);
|
builder.addMissGroup(2);
|
||||||
builder.addMissGroup(3);
|
builder.addMissGroup(3);
|
||||||
builder.addMissGroup(4);
|
builder.addMissGroup(4);
|
||||||
builder.addMissGroup(5);
|
builder.addTrianglesHitGroup(5);
|
||||||
builder.addTrianglesHitGroup(6);
|
builder.addTrianglesHitGroup(6);
|
||||||
builder.addTrianglesHitGroup(7);
|
builder.addTrianglesHitGroup(7);
|
||||||
builder.addTrianglesHitGroup(8);
|
|
||||||
pipeline = builder.create(device.get());
|
pipeline = builder.create(device.get());
|
||||||
pipeline->SetDebugName("pipeline");
|
pipeline->SetDebugName("pipeline");
|
||||||
|
|
||||||
|
@ -722,7 +735,7 @@ void GPURaytracer::CreatePipeline()
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
VkDeviceSize raygenCount = 3;
|
VkDeviceSize raygenCount = 2;
|
||||||
VkDeviceSize missCount = 3;
|
VkDeviceSize missCount = 3;
|
||||||
VkDeviceSize hitCount = 3;
|
VkDeviceSize hitCount = 3;
|
||||||
|
|
||||||
|
@ -736,8 +749,6 @@ void GPURaytracer::CreatePipeline()
|
||||||
rgenBounceRegion.size = rgenStride;
|
rgenBounceRegion.size = rgenStride;
|
||||||
rgenLightRegion.stride = rgenStride;
|
rgenLightRegion.stride = rgenStride;
|
||||||
rgenLightRegion.size = rgenStride;
|
rgenLightRegion.size = rgenStride;
|
||||||
rgenSunRegion.stride = rgenStride;
|
|
||||||
rgenSunRegion.size = rgenStride;
|
|
||||||
|
|
||||||
missRegion.stride = handleSizeAligned;
|
missRegion.stride = handleSizeAligned;
|
||||||
missRegion.size = align_up(missCount * handleSizeAligned, rtProperties.shaderGroupBaseAlignment);
|
missRegion.size = align_up(missCount * handleSizeAligned, rtProperties.shaderGroupBaseAlignment);
|
||||||
|
@ -789,7 +800,6 @@ void GPURaytracer::CreatePipeline()
|
||||||
|
|
||||||
rgenBounceRegion.deviceAddress = sbtAddress + rgenOffset;
|
rgenBounceRegion.deviceAddress = sbtAddress + rgenOffset;
|
||||||
rgenLightRegion.deviceAddress = sbtAddress + rgenOffset + rgenStride;
|
rgenLightRegion.deviceAddress = sbtAddress + rgenOffset + rgenStride;
|
||||||
rgenSunRegion.deviceAddress = sbtAddress + rgenOffset + 2 * rgenStride;
|
|
||||||
missRegion.deviceAddress = sbtAddress + missOffset;
|
missRegion.deviceAddress = sbtAddress + missOffset;
|
||||||
hitRegion.deviceAddress = sbtAddress + hitOffset;
|
hitRegion.deviceAddress = sbtAddress + hitOffset;
|
||||||
}
|
}
|
||||||
|
@ -867,7 +877,7 @@ void GPURaytracer::CreateDescriptorSet()
|
||||||
write.addStorageImage(descriptorSet.get(), 1, startPositionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
write.addStorageImage(descriptorSet.get(), 1, startPositionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
||||||
write.addStorageImage(descriptorSet.get(), 2, positionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
write.addStorageImage(descriptorSet.get(), 2, positionsImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
||||||
write.addStorageImage(descriptorSet.get(), 3, outputImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
write.addStorageImage(descriptorSet.get(), 3, outputImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
|
||||||
write.addBuffer(descriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, uniformBuffer.get());
|
write.addBuffer(descriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, uniformBuffer.get(), 0, sizeof(Uniforms));
|
||||||
write.addBuffer(descriptorSet.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get());
|
write.addBuffer(descriptorSet.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get());
|
||||||
write.addBuffer(descriptorSet.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceBuffer.get());
|
write.addBuffer(descriptorSet.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceBuffer.get());
|
||||||
write.addBuffer(descriptorSet.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, lightBuffer.get());
|
write.addBuffer(descriptorSet.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, lightBuffer.get());
|
||||||
|
@ -897,124 +907,9 @@ void GPURaytracer::PrintVulkanInfo()
|
||||||
printf("Vulkan version: %s (api) %s (driver)\n", apiVersion.c_str(), driverVersion.c_str());
|
printf("Vulkan version: %s (api) %s (driver)\n", apiVersion.c_str(), driverVersion.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPURaytracer::RaytraceProbeSample(LightProbeSample* probe)
|
Vec2 GPURaytracer::Hammersley(uint32_t i, uint32_t N)
|
||||||
{
|
{
|
||||||
Vec3 incoming(0.0f, 0.0f, 0.0f);
|
return Vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||||
|
|
||||||
if (LightBounce > 0)
|
|
||||||
{
|
|
||||||
Vec3 directions[6] =
|
|
||||||
{
|
|
||||||
{ 1.0f, 0.0f, 0.0f },
|
|
||||||
{ -1.0f, 0.0f, 0.0f },
|
|
||||||
{ 0.0f, 1.0f, 0.0f },
|
|
||||||
{ 0.0f, -1.0f, 0.0f },
|
|
||||||
{ 0.0f, 0.0f, 1.0f, },
|
|
||||||
{ 0.0f, 0.0f, -1.0f, }
|
|
||||||
};
|
|
||||||
for (int i = 0; i < bounceSampleCount; i++)
|
|
||||||
{
|
|
||||||
const Vec3& normal = directions[i % 6];
|
|
||||||
Vec2 Xi = Hammersley(i, bounceSampleCount);
|
|
||||||
Vec3 H = ImportanceSampleGGX(Xi, normal, 1.0f);
|
|
||||||
Vec3 L = Vec3::Normalize(H * (2.0f * Vec3::Dot(normal, H)) - normal);
|
|
||||||
incoming += TracePath(probe->Position, L, i);
|
|
||||||
}
|
|
||||||
incoming = incoming / (float)bounceSampleCount / (float)LightBounce;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ThingLight& light : mesh->map->ThingLights)
|
|
||||||
{
|
|
||||||
Vec3 lightOrigin = light.LightOrigin();
|
|
||||||
float lightRadius = light.LightRadius();
|
|
||||||
|
|
||||||
if (probe->Position.DistanceSq(lightOrigin) > (lightRadius * lightRadius))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mesh->TraceAnyHit(lightOrigin, probe->Position))
|
|
||||||
continue; // this light is occluded by something
|
|
||||||
|
|
||||||
Vec3 dir = (lightOrigin - probe->Position);
|
|
||||||
float dist = dir.Unit();
|
|
||||||
dir.Normalize();
|
|
||||||
|
|
||||||
incoming += light.rgb * (light.SpotAttenuation(dir) * light.DistAttenuation(dist) * light.intensity);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vec3& sundir = mesh->map->GetSunDirection();
|
|
||||||
LevelTraceHit trace = mesh->Trace(probe->Position, probe->Position + sundir * 32768.0f);
|
|
||||||
if (trace.fraction != 1.0f && trace.hitSurface->bSky)
|
|
||||||
incoming += mesh->map->GetSunColor();
|
|
||||||
|
|
||||||
probe->Color = incoming;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 GPURaytracer::GetLightEmittance(Surface* surface, const Vec3& pos)
|
|
||||||
{
|
|
||||||
Vec3 emittance = Vec3(0.0f);
|
|
||||||
for (ThingLight& light : mesh->map->ThingLights)
|
|
||||||
{
|
|
||||||
Vec3 lightOrigin = light.LightOrigin();
|
|
||||||
float lightRadius = light.LightRadius();
|
|
||||||
|
|
||||||
if (surface->plane.Distance(lightOrigin) - surface->plane.d < 0)
|
|
||||||
continue; // completely behind the plane
|
|
||||||
|
|
||||||
if (pos.DistanceSq(lightOrigin) > (lightRadius * lightRadius))
|
|
||||||
continue; // light too far away
|
|
||||||
|
|
||||||
Vec3 dir = (lightOrigin - pos);
|
|
||||||
float dist = dir.Unit();
|
|
||||||
dir.Normalize();
|
|
||||||
|
|
||||||
float attenuation = light.SpotAttenuation(dir) * light.DistAttenuation(dist) * surface->plane.Normal().Dot(dir);
|
|
||||||
if (attenuation <= 0.0f)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mesh->TraceAnyHit(lightOrigin, pos))
|
|
||||||
continue; // this light is occluded by something
|
|
||||||
|
|
||||||
emittance += light.rgb * (attenuation * light.intensity);
|
|
||||||
}
|
|
||||||
return emittance;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 GPURaytracer::TracePath(const Vec3& pos, const Vec3& dir, int sampleIndex, int depth)
|
|
||||||
{
|
|
||||||
if (depth >= LightBounce)
|
|
||||||
return Vec3(0.0f);
|
|
||||||
|
|
||||||
LevelTraceHit hit = mesh->Trace(pos + dir * 0.1f, pos + dir * 2000.0f);
|
|
||||||
if (hit.fraction == 1.0f)
|
|
||||||
return Vec3(0.0f);
|
|
||||||
|
|
||||||
Vec3 normal = hit.hitSurface->plane.Normal();
|
|
||||||
Vec3 hitpos = hit.start * (1.0f - hit.fraction) + hit.end * hit.fraction;
|
|
||||||
|
|
||||||
Vec3 emittance = GetSurfaceEmittance(hit.hitSurface, pos.Distance(hitpos)) + GetLightEmittance(hit.hitSurface, hitpos) * 0.5f;
|
|
||||||
|
|
||||||
const Vec3& sundir = mesh->map->GetSunDirection();
|
|
||||||
float attenuation = normal.Dot(sundir);
|
|
||||||
if (attenuation > 0.0f)
|
|
||||||
{
|
|
||||||
Vec3 start = hitpos + normal * 0.1f;
|
|
||||||
LevelTraceHit trace = mesh->Trace(start, start + sundir * 32768.0f);
|
|
||||||
if (trace.fraction != 1.0f && trace.hitSurface->bSky)
|
|
||||||
emittance += mesh->map->GetSunColor() * (attenuation * 0.5f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2 Xi = Hammersley(sampleIndex, bounceSampleCount);
|
|
||||||
Vec3 H = ImportanceSampleGGX(Xi, normal, 1.0f);
|
|
||||||
Vec3 L = Vec3::Normalize(H * (2.0f * Vec3::Dot(normal, H)) - normal);
|
|
||||||
|
|
||||||
float NdotL = Vec3::Dot(normal, L);
|
|
||||||
if (NdotL <= 0.0f)
|
|
||||||
return emittance;
|
|
||||||
|
|
||||||
const float p = 1 / (2 * M_PI);
|
|
||||||
Vec3 incoming = TracePath(hitpos, L, (sampleIndex + depth + 1) % bounceSampleCount, depth + 1);
|
|
||||||
|
|
||||||
return emittance + incoming * NdotL / p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float GPURaytracer::RadicalInverse_VdC(uint32_t bits)
|
float GPURaytracer::RadicalInverse_VdC(uint32_t bits)
|
||||||
|
@ -1026,69 +921,3 @@ float GPURaytracer::RadicalInverse_VdC(uint32_t bits)
|
||||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||||
return float(bits) * 2.3283064365386963e-10f; // / 0x100000000
|
return float(bits) * 2.3283064365386963e-10f; // / 0x100000000
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 GPURaytracer::Hammersley(uint32_t i, uint32_t N)
|
|
||||||
{
|
|
||||||
return Vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 GPURaytracer::ImportanceSampleGGX(Vec2 Xi, Vec3 N, float roughness)
|
|
||||||
{
|
|
||||||
float a = roughness * roughness;
|
|
||||||
|
|
||||||
float phi = 2.0f * M_PI * Xi.x;
|
|
||||||
float cosTheta = sqrt((1.0f - Xi.y) / (1.0f + (a * a - 1.0f) * Xi.y));
|
|
||||||
float sinTheta = sqrt(1.0f - cosTheta * cosTheta);
|
|
||||||
|
|
||||||
// from spherical coordinates to cartesian coordinates
|
|
||||||
Vec3 H(std::cos(phi) * sinTheta, std::sin(phi) * sinTheta, cosTheta);
|
|
||||||
|
|
||||||
// from tangent-space vector to world-space sample vector
|
|
||||||
Vec3 up = std::abs(N.z) < 0.999f ? Vec3(0.0f, 0.0f, 1.0f) : Vec3(1.0f, 0.0f, 0.0f);
|
|
||||||
Vec3 tangent = Vec3::Normalize(Vec3::Cross(up, N));
|
|
||||||
Vec3 bitangent = Vec3::Cross(N, tangent);
|
|
||||||
|
|
||||||
Vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
|
||||||
return Vec3::Normalize(sampleVec);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 GPURaytracer::GetSurfaceEmittance(Surface* surface, float distance)
|
|
||||||
{
|
|
||||||
SurfaceLightDef* def = nullptr;
|
|
||||||
if (surface->type >= ST_MIDDLESIDE && surface->type <= ST_LOWERSIDE)
|
|
||||||
{
|
|
||||||
int lightdefidx = mesh->map->Sides[surface->typeIndex].lightdef;
|
|
||||||
if (lightdefidx != -1)
|
|
||||||
{
|
|
||||||
def = &mesh->map->SurfaceLights[lightdefidx];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (surface->type == ST_FLOOR || surface->type == ST_CEILING)
|
|
||||||
{
|
|
||||||
MapSubsectorEx* sub = &mesh->map->GLSubsectors[surface->typeIndex];
|
|
||||||
IntSector* sector = mesh->map->GetSectorFromSubSector(sub);
|
|
||||||
|
|
||||||
if (sector && surface->numVerts > 0)
|
|
||||||
{
|
|
||||||
if (sector->floorlightdef != -1 && surface->type == ST_FLOOR)
|
|
||||||
{
|
|
||||||
def = &mesh->map->SurfaceLights[sector->floorlightdef];
|
|
||||||
}
|
|
||||||
else if (sector->ceilinglightdef != -1 && surface->type == ST_CEILING)
|
|
||||||
{
|
|
||||||
def = &mesh->map->SurfaceLights[sector->ceilinglightdef];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (def && distance < def->distance + def->distance)
|
|
||||||
{
|
|
||||||
float radius = def->distance + def->distance;
|
|
||||||
float attenuation = std::max(1.0f - (distance / radius), 0.0f);
|
|
||||||
return def->rgb * (attenuation * def->intensity);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Vec3(0.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -44,9 +44,9 @@ struct LightInfo
|
||||||
float Padding2;
|
float Padding2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SurfaceTask
|
struct TraceTask
|
||||||
{
|
{
|
||||||
int surf, x, y;
|
int id, x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GPURaytracer
|
class GPURaytracer
|
||||||
|
@ -69,24 +69,17 @@ private:
|
||||||
void CreatePipeline();
|
void CreatePipeline();
|
||||||
void CreateDescriptorSet();
|
void CreateDescriptorSet();
|
||||||
|
|
||||||
void UploadTasks(const SurfaceTask* tasks, size_t size);
|
void UploadTasks(const TraceTask* tasks, size_t size);
|
||||||
void BeginTracing();
|
void BeginTracing();
|
||||||
void RunTrace(const Uniforms& uniforms, const VkStridedDeviceAddressRegionKHR& rgenShader);
|
void RunTrace(const Uniforms& uniforms, const VkStridedDeviceAddressRegionKHR& rgenShader);
|
||||||
void EndTracing();
|
void EndTracing();
|
||||||
void DownloadTasks(const SurfaceTask* tasks, size_t size);
|
void DownloadTasks(const TraceTask* tasks, size_t size);
|
||||||
void SubmitCommands();
|
void SubmitCommands();
|
||||||
|
|
||||||
void PrintVulkanInfo();
|
void PrintVulkanInfo();
|
||||||
|
|
||||||
void RaytraceProbeSample(LightProbeSample* probe);
|
|
||||||
Vec3 TracePath(const Vec3& pos, const Vec3& dir, int sampleIndex, int depth = 0);
|
|
||||||
|
|
||||||
Vec3 GetLightEmittance(Surface* surface, const Vec3& pos);
|
|
||||||
Vec3 GetSurfaceEmittance(Surface* surface, float distance);
|
|
||||||
|
|
||||||
static float RadicalInverse_VdC(uint32_t bits);
|
static float RadicalInverse_VdC(uint32_t bits);
|
||||||
static Vec2 Hammersley(uint32_t i, uint32_t N);
|
static Vec2 Hammersley(uint32_t i, uint32_t N);
|
||||||
static Vec3 ImportanceSampleGGX(Vec2 Xi, Vec3 N, float roughness);
|
|
||||||
|
|
||||||
const int coverageSampleCount = 256;
|
const int coverageSampleCount = 256;
|
||||||
const int bounceSampleCount = 2048;
|
const int bounceSampleCount = 2048;
|
||||||
|
@ -117,7 +110,7 @@ private:
|
||||||
std::unique_ptr<VulkanBuffer> tlAccelStructBuffer;
|
std::unique_ptr<VulkanBuffer> tlAccelStructBuffer;
|
||||||
std::unique_ptr<VulkanAccelerationStructure> tlAccelStruct;
|
std::unique_ptr<VulkanAccelerationStructure> tlAccelStruct;
|
||||||
|
|
||||||
std::unique_ptr<VulkanShader> rgenBounce, rgenLight, rgenSun;
|
std::unique_ptr<VulkanShader> rgenBounce, rgenLight;
|
||||||
std::unique_ptr<VulkanShader> rmissBounce, rmissLight, rmissSun;
|
std::unique_ptr<VulkanShader> rmissBounce, rmissLight, rmissSun;
|
||||||
std::unique_ptr<VulkanShader> rchitBounce, rchitLight, rchitSun;
|
std::unique_ptr<VulkanShader> rchitBounce, rchitLight, rchitSun;
|
||||||
|
|
||||||
|
@ -128,7 +121,7 @@ private:
|
||||||
std::unique_ptr<VulkanBuffer> shaderBindingTable;
|
std::unique_ptr<VulkanBuffer> shaderBindingTable;
|
||||||
std::unique_ptr<VulkanBuffer> sbtTransferBuffer;
|
std::unique_ptr<VulkanBuffer> sbtTransferBuffer;
|
||||||
|
|
||||||
VkStridedDeviceAddressRegionKHR rgenBounceRegion = {}, rgenLightRegion = {}, rgenSunRegion = {};
|
VkStridedDeviceAddressRegionKHR rgenBounceRegion = {}, rgenLightRegion = {};
|
||||||
VkStridedDeviceAddressRegionKHR missRegion = {};
|
VkStridedDeviceAddressRegionKHR missRegion = {};
|
||||||
VkStridedDeviceAddressRegionKHR hitRegion = {};
|
VkStridedDeviceAddressRegionKHR hitRegion = {};
|
||||||
VkStridedDeviceAddressRegionKHR callRegion = {};
|
VkStridedDeviceAddressRegionKHR callRegion = {};
|
||||||
|
|
Loading…
Reference in a new issue