mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-22 03:51:26 +00:00
Some initial support for doing GPU ray tracing without RTX
This commit is contained in:
parent
e225118e8e
commit
c80f611924
7 changed files with 151 additions and 53 deletions
|
@ -1,9 +1,23 @@
|
|||
static const char* glsl_frag = R"glsl(
|
||||
|
||||
#version 460
|
||||
#extension GL_EXT_ray_query : require
|
||||
|
||||
#if defined(USE_RAYQUERY)
|
||||
layout(set = 0, binding = 0) uniform accelerationStructureEXT acc;
|
||||
#else
|
||||
struct CollisionNode
|
||||
{
|
||||
vec3 center;
|
||||
float padding1;
|
||||
vec3 extents;
|
||||
float padding2;
|
||||
int left;
|
||||
int right;
|
||||
int element_index;
|
||||
int padding3;
|
||||
};
|
||||
layout(set = 1, binding = 0) buffer NodeBuffer { CollisionNode nodes[]; };
|
||||
layout(set = 1, binding = 1) buffer VertexBuffer { vec3 vertices[]; };
|
||||
layout(set = 1, binding = 2) buffer ElementBuffer { vec3 elements[]; };
|
||||
#endif
|
||||
|
||||
layout(set = 0, binding = 1) uniform Uniforms
|
||||
{
|
||||
|
@ -62,6 +76,10 @@ float TraceAmbientOcclusion(vec3 origin, vec3 normal);
|
|||
vec2 Hammersley(uint i, uint N);
|
||||
float RadicalInverse_VdC(uint bits);
|
||||
|
||||
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax);
|
||||
int TraceFirstHitTriangle(vec3 origin, float tmin, vec3 dir, float tmax);
|
||||
int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out float t);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 normal = surfaces[SurfaceIndex].Normal;
|
||||
|
@ -105,12 +123,7 @@ vec3 TraceLight(vec3 origin, vec3 normal, LightInfo light)
|
|||
float attenuation = distAttenuation * angleAttenuation * spotAttenuation;
|
||||
if (attenuation > 0.0)
|
||||
{
|
||||
rayQueryEXT rayQuery;
|
||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, minDistance, dir, dist);
|
||||
|
||||
while(rayQueryProceedEXT(rayQuery)) { }
|
||||
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT)
|
||||
if (TraceAnyHit(origin, minDistance, dir, dist))
|
||||
{
|
||||
incoming.rgb += light.Color * (attenuation * light.Intensity);
|
||||
}
|
||||
|
@ -125,20 +138,9 @@ vec3 TraceSunLight(vec3 origin)
|
|||
vec3 incoming = vec3(0.0);
|
||||
const float dist = 32768.0;
|
||||
|
||||
rayQueryEXT rayQuery;
|
||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, minDistance, SunDir, dist);
|
||||
|
||||
while(rayQueryProceedEXT(rayQuery))
|
||||
int primitiveID = TraceFirstHitTriangle(origin, minDistance, SunDir, dist);
|
||||
if (primitiveID != -1)
|
||||
{
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
rayQueryConfirmIntersectionEXT(rayQuery);
|
||||
}
|
||||
}
|
||||
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
int primitiveID = rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
incoming.rgb += SunColor * SunIntensity * surface.Sky;
|
||||
}
|
||||
|
@ -163,24 +165,13 @@ float TraceAmbientOcclusion(vec3 origin, vec3 normal)
|
|||
vec3 H = normalize(vec3(Xi.x * 2.0f - 1.0f, Xi.y * 2.0f - 1.0f, 1.5 - length(Xi)));
|
||||
vec3 L = H.x * tangent + H.y * bitangent + H.z * N;
|
||||
|
||||
rayQueryEXT rayQuery;
|
||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, minDistance, L, aoDistance);
|
||||
|
||||
while(rayQueryProceedEXT(rayQuery))
|
||||
float hitDistance;
|
||||
int primitiveID = TraceFirstHitTriangleT(origin, minDistance, L, aoDistance, hitDistance);
|
||||
if (primitiveID != -1)
|
||||
{
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
rayQueryConfirmIntersectionEXT(rayQuery);
|
||||
}
|
||||
}
|
||||
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
int primitiveID = rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
if (surface.Sky == 0.0)
|
||||
{
|
||||
float hitDistance = rayQueryGetIntersectionTEXT(rayQuery, true);
|
||||
ambience += clamp(hitDistance / aoDistance, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
@ -207,4 +198,84 @@ float RadicalInverse_VdC(uint bits)
|
|||
return float(bits) * 2.3283064365386963e-10f; // / 0x100000000
|
||||
}
|
||||
|
||||
#if defined(USE_RAYQUERY)
|
||||
|
||||
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
rayQueryEXT rayQuery;
|
||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, tmin, dir, tmax);
|
||||
while(rayQueryProceedEXT(rayQuery)) { }
|
||||
return rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT;
|
||||
}
|
||||
|
||||
int TraceFirstHitTriangle(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
rayQueryEXT rayQuery;
|
||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, tmin, dir, tmax);
|
||||
|
||||
while(rayQueryProceedEXT(rayQuery))
|
||||
{
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
rayQueryConfirmIntersectionEXT(rayQuery);
|
||||
}
|
||||
}
|
||||
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
return rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out float t)
|
||||
{
|
||||
rayQueryEXT rayQuery;
|
||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsTerminateOnFirstHitEXT, 0xFF, origin, tmin, dir, tmax);
|
||||
|
||||
while(rayQueryProceedEXT(rayQuery))
|
||||
{
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, false) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
rayQueryConfirmIntersectionEXT(rayQuery);
|
||||
}
|
||||
}
|
||||
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
t = rayQueryGetIntersectionTEXT(rayQuery, true);
|
||||
return rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
// To do: port TriangleMeshShape::find_any_hit(TriangleMeshShape *shape, const vec3 &ray_start, const vec3 &ray_end) to glsl
|
||||
return false;
|
||||
}
|
||||
|
||||
int TraceFirstHitTriangle(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
float t;
|
||||
return TraceFirstHitTriangleT(origin, tmin, dir, tmax, t);
|
||||
}
|
||||
|
||||
int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out float t)
|
||||
{
|
||||
// To do: port TriangleMeshShape::find_first_hit(TriangleMeshShape *shape, const vec3 &ray_start, const vec3 &ray_end) to glsl
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
)glsl";
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
static const char* glsl_frag_resolve = R"glsl(
|
||||
|
||||
#version 460
|
||||
#extension GL_EXT_ray_query : require
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2DMS tex;
|
||||
|
||||
layout(location = 0) in vec3 worldpos;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
static const char* glsl_vert = R"glsl(
|
||||
|
||||
#version 460
|
||||
|
||||
layout(push_constant) uniform PushConstants
|
||||
{
|
||||
uint LightStart;
|
||||
|
|
|
@ -337,8 +337,15 @@ void GPURaytracer::CreateVulkanObjects()
|
|||
CreateSceneLightBuffer();
|
||||
CreateVertexAndIndexBuffers();
|
||||
CreateUniformBuffer();
|
||||
if (useRayQuery)
|
||||
{
|
||||
CreateBottomLevelAccelerationStructure();
|
||||
CreateTopLevelAccelerationStructure();
|
||||
}
|
||||
else
|
||||
{
|
||||
// To do: upload mesh->Collision->nodes (vertices and elements are already uploaded in CreateVertexAndIndexBuffers)
|
||||
}
|
||||
CreateShaders();
|
||||
CreateRaytracePipeline();
|
||||
CreateResolvePipeline();
|
||||
|
@ -429,8 +436,9 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
|||
.Usage(
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||
(useRayQuery ?
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
|
||||
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |
|
||||
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0) |
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
|
||||
.Size(vertexbuffersize)
|
||||
.DebugName("vertexBuffer")
|
||||
|
@ -440,8 +448,9 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
|||
.Usage(
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||
(useRayQuery ?
|
||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
|
||||
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |
|
||||
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0) |
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
|
||||
.Size(indexbuffersize)
|
||||
.DebugName("indexBuffer")
|
||||
|
@ -479,7 +488,7 @@ void GPURaytracer::CreateVertexAndIndexBuffers()
|
|||
|
||||
PipelineBarrier()
|
||||
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
||||
.Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
|
||||
.Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, useRayQuery ? VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
void GPURaytracer::CreateBottomLevelAccelerationStructure()
|
||||
|
@ -623,24 +632,35 @@ void GPURaytracer::CreateTopLevelAccelerationStructure()
|
|||
|
||||
void GPURaytracer::CreateShaders()
|
||||
{
|
||||
FString prefix = "#version 460\r\n#line 1\r\n";
|
||||
FString traceprefix = "#version 460\r\n";
|
||||
if (useRayQuery) // To do: check if ray query is available
|
||||
{
|
||||
traceprefix += "#extension GL_EXT_ray_query : require\r\n";
|
||||
traceprefix += "#define USE_RAYQUERY\r\n";
|
||||
}
|
||||
traceprefix += "#line 1\r\n";
|
||||
|
||||
vertShader = ShaderBuilder()
|
||||
.VertexShader(glsl_vert)
|
||||
.VertexShader(prefix + glsl_vert)
|
||||
.DebugName("vertShader")
|
||||
.Create("vertShader", device.get());
|
||||
|
||||
fragShader = ShaderBuilder()
|
||||
.FragmentShader(glsl_frag)
|
||||
.FragmentShader(traceprefix + glsl_frag)
|
||||
.DebugName("fragShader")
|
||||
.Create("fragShader", device.get());
|
||||
|
||||
fragResolveShader = ShaderBuilder()
|
||||
.FragmentShader(glsl_frag_resolve)
|
||||
.FragmentShader(prefix + glsl_frag_resolve)
|
||||
.DebugName("fragResolveShader")
|
||||
.Create("fragResolveShader", device.get());
|
||||
}
|
||||
|
||||
void GPURaytracer::CreateRaytracePipeline()
|
||||
{
|
||||
// To do: use rayQuery boolean to specify the alternative descriptor set
|
||||
|
||||
raytrace.descriptorSetLayout = DescriptorSetLayoutBuilder()
|
||||
.AddBinding(0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
|
|
|
@ -50,6 +50,18 @@ struct LightInfo
|
|||
float Padding2;
|
||||
};
|
||||
|
||||
struct CollisionNode
|
||||
{
|
||||
vec3 center;
|
||||
float padding1;
|
||||
vec3 extents;
|
||||
float padding2;
|
||||
int left;
|
||||
int right;
|
||||
int element_index;
|
||||
int padding3;
|
||||
};
|
||||
|
||||
struct LightmapImage
|
||||
{
|
||||
struct
|
||||
|
@ -120,6 +132,8 @@ private:
|
|||
|
||||
std::unique_ptr<VulkanDevice> device;
|
||||
|
||||
bool useRayQuery = true;
|
||||
|
||||
static const int SceneVertexBufferSize = 1 * 1024 * 1024;
|
||||
std::unique_ptr<VulkanBuffer> sceneVertexBuffer;
|
||||
SceneVertex* sceneVertices = nullptr;
|
||||
|
|
|
@ -10,5 +10,4 @@ LightmapTexture::LightmapTexture(int width, int height) : textureWidth(width), t
|
|||
#else
|
||||
mPixels.resize(width * height * 3, 0);
|
||||
#endif
|
||||
allocBlocks.resize(width);
|
||||
}
|
||||
|
|
|
@ -17,5 +17,4 @@ private:
|
|||
int textureWidth;
|
||||
int textureHeight;
|
||||
std::vector<uint16_t> mPixels;
|
||||
std::vector<int> allocBlocks;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue