diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index 63b57d5e3..18f138682 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -704,6 +704,8 @@ public: virtual void EndQuery() { } virtual void GetQueryResults(int start, int count, TArray& results) { } + virtual void RaytraceScene(const FVector3& cameraPos, const VSMatrix& viewToWorld, float fovy, float aspect) { } + friend class Mesh; }; diff --git a/src/common/rendering/vulkan/vk_levelmesh.cpp b/src/common/rendering/vulkan/vk_levelmesh.cpp index fd3dc6d2e..9b79e9b80 100644 --- a/src/common/rendering/vulkan/vk_levelmesh.cpp +++ b/src/common/rendering/vulkan/vk_levelmesh.cpp @@ -24,13 +24,17 @@ #include "zvulkan/vulkanbuilders.h" #include "vulkan/vk_renderdevice.h" #include "vulkan/commands/vk_commandbuffer.h" +#include "vulkan/descriptorsets/vk_descriptorset.h" +#include "vulkan/pipelines/vk_renderpass.h" #include "hw_levelmesh.h" #include "hw_material.h" #include "texturemanager.h" +#include "cmdlib.h" VkLevelMesh::VkLevelMesh(VulkanRenderDevice* fb) : fb(fb) { useRayQuery = fb->IsRayQueryEnabled(); + CreateViewerObjects(); SetLevelMesh(nullptr); } @@ -196,6 +200,24 @@ void VkLevelMesh::BeginFrame() .AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); } + + WriteDescriptors write; + write.AddBuffer(Viewer.DescriptorSet.get(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetSurfaceIndexBuffer()); + write.AddBuffer(Viewer.DescriptorSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetSurfaceBuffer()); + write.AddBuffer(Viewer.DescriptorSet.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetLightBuffer()); + write.AddBuffer(Viewer.DescriptorSet.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetLightIndexBuffer()); + write.AddBuffer(Viewer.DescriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetPortalBuffer()); + if (useRayQuery) + { + write.AddAccelerationStructure(Viewer.DescriptorSet.get(), 5, GetAccelStruct()); + } + else + { + write.AddBuffer(Viewer.DescriptorSet.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetNodeBuffer()); + } + write.AddBuffer(Viewer.DescriptorSet.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetVertexBuffer()); + write.AddBuffer(Viewer.DescriptorSet.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, GetIndexBuffer()); + write.Execute(fb->GetDevice()); } void VkLevelMesh::UploadMeshes() @@ -336,6 +358,7 @@ VkLevelMesh::BLAS VkLevelMesh::CreateBLAS(bool preferFastBuild, int indexOffset, .Create(fb->GetDevice()); blas.DeviceAddress = blas.AccelStruct->GetDeviceAddress(); + blas.InstanceCustomIndex = indexOffset / 3; buildInfo.dstAccelerationStructure = blas.AccelStruct->accelstruct; buildInfo.scratchData.deviceAddress = blas.ScratchBuffer->GetDeviceAddress(); @@ -452,6 +475,7 @@ void VkLevelMesh::UploadTLASInstanceBuffer() auto data = (uint8_t*)TopLevelAS.TransferBuffer->Map(0, sizeof(VkAccelerationStructureInstanceKHR) * DynamicBLAS.size()); for (BLAS& blas : DynamicBLAS) { + instance.instanceCustomIndex = blas.InstanceCustomIndex; instance.accelerationStructureReference = blas.DeviceAddress; memcpy(data, &instance, sizeof(VkAccelerationStructureInstanceKHR)); @@ -462,6 +486,195 @@ void VkLevelMesh::UploadTLASInstanceBuffer() fb->GetCommands()->GetTransferCommands()->copyBuffer(TopLevelAS.TransferBuffer.get(), TopLevelAS.InstanceBuffer.get()); } +void VkLevelMesh::RaytraceScene(const VkRenderPassKey& renderPassKey, VulkanCommandBuffer* commands, const FVector3& cameraPos, const VSMatrix& viewToWorld, float fovy, float aspect) +{ + auto& pipeline = Viewer.Pipeline[renderPassKey]; + if (!pipeline) + { + GraphicsPipelineBuilder builder; + builder.RenderPass(fb->GetRenderPassManager()->GetRenderPass(renderPassKey)->GetRenderPass(0)); + builder.Layout(Viewer.PipelineLayout.get()); + builder.Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); + builder.AddVertexShader(Viewer.VertexShader.get()); + builder.AddFragmentShader(Viewer.FragmentShader.get()); + builder.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT); + builder.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR); + builder.RasterizationSamples((VkSampleCountFlagBits)renderPassKey.Samples); + builder.DebugName("Viewer.Pipeline"); + pipeline = builder.Create(fb->GetDevice()); + } + + /* + RenderPassBegin() + .RenderPass(Viewer.RenderPass.get()) + .Framebuffer(Framebuffers[imageIndex].get()) + .RenderArea(0, 0, CurrentWidth, CurrentHeight) + .AddClearColor(0.0f, 0.0f, 0.0f, 1.0f) + .AddClearDepth(1.0f) + .Execute(commands); + + VkViewport viewport = {}; + viewport.width = (float)CurrentWidth; + viewport.height = (float)CurrentHeight; + viewport.maxDepth = 1.0f; + commands->setViewport(0, 1, &viewport); + + VkRect2D scissor = {}; + scissor.extent.width = CurrentWidth; + scissor.extent.height = CurrentHeight; + commands->setScissor(0, 1, &scissor); + */ + + float f = 1.0f / std::tan(fovy * (pi::pif() / 360.0f)); + + ViewerPushConstants pushconstants; + pushconstants.ViewToWorld = viewToWorld; + pushconstants.CameraPos = cameraPos; + pushconstants.ProjX = f / aspect; + pushconstants.ProjY = f; + pushconstants.SunDir = FVector3(Mesh->SunDirection.X, Mesh->SunDirection.Z, Mesh->SunDirection.Y); + pushconstants.SunColor = Mesh->SunColor; + pushconstants.SunIntensity = 1.0f; + + commands->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, Viewer.PipelineLayout.get(), 0, Viewer.DescriptorSet.get()); + commands->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, Viewer.PipelineLayout.get(), 1, fb->GetDescriptorSetManager()->GetBindlessSet()); + commands->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get()); + commands->pushConstants(Viewer.PipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ViewerPushConstants), &pushconstants); + commands->draw(4, 1, 0, 0); + + //commands->endRenderPass(); +} + +void VkLevelMesh::CreateViewerObjects() +{ + DescriptorSetLayoutBuilder builder; + builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + if (useRayQuery) + { + builder.AddBinding(5, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + } + else + { + builder.AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + } + builder.AddBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.DebugName("Viewer.DescriptorSetLayout"); + Viewer.DescriptorSetLayout = builder.Create(fb->GetDevice()); + + Viewer.DescriptorPool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 6) + .MaxSets(1) + .DebugName("Viewer.DescriptorPool") + .Create(fb->GetDevice()); + + Viewer.DescriptorSet = Viewer.DescriptorPool->allocate(Viewer.DescriptorSetLayout.get()); + Viewer.DescriptorSet->SetDebugName("raytrace.descriptorSet1"); + + std::string versionBlock = R"( + #version 460 + #extension GL_GOOGLE_include_directive : enable + #extension GL_EXT_nonuniform_qualifier : enable + )"; + + if (useRayQuery) + { + versionBlock += "#extension GL_EXT_ray_query : require\r\n"; + versionBlock += "#define USE_RAYQUERY\r\n"; + } + + auto onIncludeLocal = [](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, false); }; + auto onIncludeSystem = [](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, true); }; + + Viewer.VertexShader = ShaderBuilder() + .Type(ShaderType::Vertex) + .AddSource("versionblock", versionBlock) + .AddSource("vert_viewer.glsl", LoadPrivateShaderLump("shaders/lightmap/vert_viewer.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("Viewer.VertexShader") + .Create("vertex", fb->GetDevice()); + + Viewer.FragmentShader = ShaderBuilder() + .Type(ShaderType::Fragment) + .AddSource("versionblock", versionBlock) + .AddSource("frag_viewer.glsl", LoadPrivateShaderLump("shaders/lightmap/frag_viewer.glsl").GetChars()) + .OnIncludeLocal(onIncludeLocal) + .OnIncludeSystem(onIncludeSystem) + .DebugName("Viewer.FragmentShader") + .Create("vertex", fb->GetDevice()); + + Viewer.PipelineLayout = PipelineLayoutBuilder() + .AddSetLayout(Viewer.DescriptorSetLayout.get()) + .AddSetLayout(fb->GetDescriptorSetManager()->GetBindlessLayout()) + .AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ViewerPushConstants)) + .DebugName("Viewer.PipelineLayout") + .Create(fb->GetDevice()); + + /* + Viewer.RenderPass = RenderPassBuilder() + .AddAttachment(VK_FORMAT_B8G8R8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) + .AddSubpass() + .AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .Create(fb->GetDevice()); + + Viewer.Pipeline = GraphicsPipelineBuilder() + .RenderPass(Viewer.RenderPass.get()) + .Layout(Viewer.PipelineLayout.get()) + .Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) + .AddVertexShader(Viewer.VertexShader.get()) + .AddFragmentShader(Viewer.FragmentShader.get()) + .AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT) + .AddDynamicState(VK_DYNAMIC_STATE_SCISSOR) + .DebugName("Viewer.Pipeline") + .Create(fb->GetDevice()); + */ +} + +FString VkLevelMesh::LoadPrivateShaderLump(const char* lumpname) +{ + int lump = fileSystem.CheckNumForFullName(lumpname, 0); + if (lump == -1) I_Error("Unable to load '%s'", lumpname); + return GetStringFromLump(lump); +} + +FString VkLevelMesh::LoadPublicShaderLump(const char* lumpname) +{ + int lump = fileSystem.CheckNumForFullName(lumpname, 0); + if (lump == -1) lump = fileSystem.CheckNumForFullName(lumpname); + if (lump == -1) I_Error("Unable to load '%s'", lumpname); + return GetStringFromLump(lump); +} + +ShaderIncludeResult VkLevelMesh::OnInclude(FString headerName, FString includerName, size_t depth, bool system) +{ + if (depth > 8) + I_Error("Too much include recursion!"); + + FString includeguardname; + includeguardname << "_HEADERGUARD_" << headerName.GetChars(); + includeguardname.ReplaceChars("/\\.", '_'); + + FString code; + code << "#ifndef " << includeguardname.GetChars() << "\n"; + code << "#define " << includeguardname.GetChars() << "\n"; + code << "#line 1\n"; + + if (system) + code << LoadPrivateShaderLump(headerName.GetChars()).GetChars() << "\n"; + else + code << LoadPublicShaderLump(headerName.GetChars()).GetChars() << "\n"; + + code << "#endif\n"; + + return ShaderIncludeResult(headerName.GetChars(), code.GetChars()); +} + ///////////////////////////////////////////////////////////////////////////// VkLevelMeshUploader::VkLevelMeshUploader(VkLevelMesh* mesh) : Mesh(mesh) diff --git a/src/common/rendering/vulkan/vk_levelmesh.h b/src/common/rendering/vulkan/vk_levelmesh.h index 9bdad073e..1d8e8382a 100644 --- a/src/common/rendering/vulkan/vk_levelmesh.h +++ b/src/common/rendering/vulkan/vk_levelmesh.h @@ -4,8 +4,11 @@ #include "zvulkan/vulkanobjects.h" #include "hw_levelmesh.h" #include "common/utility/matrix.h" +#include class VulkanRenderDevice; +class ShaderIncludeResult; +class VkRenderPassKey; struct CollisionNodeBufferHeader { @@ -62,6 +65,17 @@ struct LightInfo float Padding3; }; +struct ViewerPushConstants +{ + VSMatrix ViewToWorld; + FVector3 CameraPos; + float ProjX; + FVector3 SunDir; + float ProjY; + FVector3 SunColor; + float SunIntensity; +}; + static_assert(sizeof(LightInfo) == sizeof(float) * 20); class VkLevelMesh @@ -72,6 +86,8 @@ public: void SetLevelMesh(LevelMesh* mesh); void BeginFrame(); + void RaytraceScene(const VkRenderPassKey& renderPassKey, VulkanCommandBuffer* commands, const FVector3& cameraPos, const VSMatrix& viewToWorld, float fovy, float aspect); + VulkanAccelerationStructure* GetAccelStruct() { return TopLevelAS.AccelStruct.get(); } VulkanBuffer* GetVertexBuffer() { return VertexBuffer.get(); } VulkanBuffer* GetUniformIndexBuffer() { return UniformIndexBuffer.get(); } @@ -94,6 +110,7 @@ private: std::unique_ptr AccelStructBuffer; std::unique_ptr AccelStruct; VkDeviceAddress DeviceAddress = 0; + int InstanceCustomIndex = 0; bool NeedsUpdate = false; }; @@ -109,6 +126,12 @@ private: BLAS CreateBLAS(bool preferFastBuild, int indexOffset, int indexCount); + void CreateViewerObjects(); + + static FString LoadPrivateShaderLump(const char* lumpname); + static FString LoadPublicShaderLump(const char* lumpname); + static ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system); + VulkanRenderDevice* fb = nullptr; bool useRayQuery = true; @@ -142,6 +165,18 @@ private: std::unique_ptr AccelStruct; } TopLevelAS; + struct + { + std::unique_ptr DescriptorSetLayout; + std::unique_ptr DescriptorPool; + std::unique_ptr DescriptorSet; + std::unique_ptr VertexShader; + std::unique_ptr FragmentShader; + //std::unique_ptr RenderPass; + std::unique_ptr PipelineLayout; + std::map> Pipeline; + } Viewer; + friend class VkLevelMeshUploader; }; diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 478036583..e7836519d 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -829,6 +829,24 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer) mClearTargets = 0; } +void VkRenderState::RaytraceScene(const FVector3& cameraPos, const VSMatrix& viewToWorld, float fovy, float aspect) +{ + ApplyMatrices(); + ApplyRenderPass(DT_Triangles); + ApplyScissor(); + ApplyViewport(); + ApplyStencilRef(); + ApplyDepthBias(); + mNeedApply = true; + + VkRenderPassKey key = {}; + key.DrawBufferFormat = mRenderTarget.Format; + key.Samples = mRenderTarget.Samples; + key.DrawBuffers = mRenderTarget.DrawBuffers; + key.DepthStencil = !!mRenderTarget.DepthStencil; + fb->GetLevelMesh()->RaytraceScene(key, mCommandBuffer, cameraPos, viewToWorld, fovy, aspect); +} + void VkRenderState::ApplyLevelMesh() { ApplyMatrices(); diff --git a/src/common/rendering/vulkan/vk_renderstate.h b/src/common/rendering/vulkan/vk_renderstate.h index 9cf1fdb5d..76d2efab0 100644 --- a/src/common/rendering/vulkan/vk_renderstate.h +++ b/src/common/rendering/vulkan/vk_renderstate.h @@ -63,6 +63,8 @@ public: void EndQuery() override; void GetQueryResults(int start, int count, TArray& results) override; + void RaytraceScene(const FVector3& cameraPos, const VSMatrix& viewToWorld, float fovy, float aspect) override; + // Worker threads void FlushCommands() override { EndRenderPass(); } diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index 8a2a2bc8b..bc216dbb7 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -54,6 +54,8 @@ EXTERN_CVAR(Bool, cl_capfps) EXTERN_CVAR(Float, r_visibility) EXTERN_CVAR(Bool, gl_bandedswlight) +CVAR(Bool, gl_raytrace, false, 0/*CVAR_ARCHIVE | CVAR_GLOBALCONFIG*/) + extern bool NoInterpolateView; static SWSceneDrawer *swdrawer; @@ -174,7 +176,21 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees()); di->SetupView(RenderState, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false); - di->ProcessScene(toscreen, *screen->RenderState()); + if (gl_raytrace) + { + VSMatrix viewToWorld; + di->VPUniforms.mViewMatrix.inverseMatrix(viewToWorld); + + auto DEG2RAD = [](float deg) { return deg * float(M_PI / 180.0); }; + auto RAD2DEG = [](float rad) { return rad * float(180. / M_PI); }; + float fovy = (float)(2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovratio))); + + RenderState.RaytraceScene(FVector3(vp.Pos.X, vp.Pos.Z, vp.Pos.Y), viewToWorld, fovy, ratio); + } + else + { + di->ProcessScene(toscreen, RenderState); + } if (mainview) { diff --git a/wadsrc/static/shaders/lightmap/binding_viewer.glsl b/wadsrc/static/shaders/lightmap/binding_viewer.glsl new file mode 100644 index 000000000..8701703db --- /dev/null +++ b/wadsrc/static/shaders/lightmap/binding_viewer.glsl @@ -0,0 +1,94 @@ + +struct SurfaceInfo +{ + vec3 Normal; + float Sky; + uint PortalIndex; + int TextureIndex; + float Alpha; + float Padding0; + uint LightStart; + uint LightEnd; + uint Padding1; + uint Padding2; +}; + +struct PortalInfo +{ + mat4 Transformation; +}; + +struct LightInfo +{ + vec3 Origin; + float Padding0; + vec3 RelativeOrigin; + float Padding1; + float Radius; + float Intensity; + float InnerAngleCos; + float OuterAngleCos; + vec3 SpotDir; + float SoftShadowRadius; + vec3 Color; + float Padding3; +}; + +layout(set = 0, binding = 0, std430) buffer SurfaceIndexBuffer { uint surfaceIndices[]; }; +layout(set = 0, binding = 1, std430) buffer SurfaceBuffer { SurfaceInfo surfaces[]; }; +layout(set = 0, binding = 2, std430) buffer LightBuffer { LightInfo lights[]; }; +layout(set = 0, binding = 3, std430) buffer LightIndexBuffer { int lightIndexes[]; }; +layout(set = 0, binding = 4, std430) buffer PortalBuffer { PortalInfo portals[]; }; + +#if defined(USE_RAYQUERY) + +layout(set = 0, binding = 5) 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 = 0, binding = 5, std430) buffer NodeBuffer +{ + int nodesRoot; + int nodebufferPadding1; + int nodebufferPadding2; + int nodebufferPadding3; + CollisionNode nodes[]; +}; + +#endif + +struct SurfaceVertex // Note: this must always match the FFlatVertex struct +{ + vec3 pos; + float lindex; + vec2 uv; + vec2 luv; +}; + +layout(set = 0, binding = 6, std430) buffer VertexBuffer { SurfaceVertex vertices[]; }; +layout(set = 0, binding = 7, std430) buffer ElementBuffer { int elements[]; }; + +layout(set = 1, binding = 0) uniform sampler2D textures[]; + +layout(push_constant) uniform PushConstants +{ + mat4 ViewToWorld; + vec3 CameraPos; + float ProjX; + vec3 SunDir; + float ProjY; + vec3 SunColor; + float SunIntensity; +}; diff --git a/wadsrc/static/shaders/lightmap/frag_viewer.glsl b/wadsrc/static/shaders/lightmap/frag_viewer.glsl new file mode 100644 index 000000000..d77d6ae2b --- /dev/null +++ b/wadsrc/static/shaders/lightmap/frag_viewer.glsl @@ -0,0 +1,59 @@ + +#include +#include +#include +#include +#include +#include + +layout(location = 0) in vec3 FragRay; +layout(location = 0) out vec4 fragcolor; + +void main() +{ + vec3 incoming = vec3(0.1); + + vec3 origin = CameraPos; + vec3 L = normalize(FragRay); + TraceResult result = TraceFirstHit(origin, 0.0, L, 10000.0); + if (result.primitiveIndex != -1) + { + SurfaceInfo surface = GetSurface(result.primitiveIndex); + vec3 surfacepos = origin + L * result.t; + + if (surface.Sky == 0.0) + { + incoming += TraceSunLight(surfacepos, surface.Normal); + + uint LightStart = surface.LightStart; + uint LightEnd = surface.LightEnd; + for (uint j = LightStart; j < LightEnd; j++) + { + incoming += TraceLight(surfacepos, surface.Normal, lights[lightIndexes[j]], 0.0); + } + + // incoming *= TraceAmbientOcclusion(surfacepos, surface.Normal); + } + else + { + incoming = SunColor; + } + + if (surface.TextureIndex != 0) + { + vec2 uv = GetSurfaceUV(result.primitiveIndex, result.primitiveWeights); + vec4 color = texture(textures[surface.TextureIndex], uv); + incoming *= color.rgb; + } + else + { + incoming = vec3(0.0, 0.0, 1.0); + } + } + else + { + incoming = vec3(1.0, 0.0, 0.0); + } + + fragcolor = vec4(incoming, 1.0); +} diff --git a/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl b/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl index 83f0f514a..425a99301 100644 --- a/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl +++ b/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl @@ -30,7 +30,9 @@ TraceResult TraceFirstHit(vec3 origin, float tmin, vec3 dir, float tmax) result.primitiveWeights.xy = rayQueryGetIntersectionBarycentricsEXT(rayQuery, true); result.primitiveWeights.z = 1.0 - result.primitiveWeights.x - result.primitiveWeights.y; - result.primitiveIndex = rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true); + result.primitiveIndex = + rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true) + + rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true); } else { diff --git a/wadsrc/static/shaders/lightmap/vert_viewer.glsl b/wadsrc/static/shaders/lightmap/vert_viewer.glsl new file mode 100644 index 000000000..4d82f47d3 --- /dev/null +++ b/wadsrc/static/shaders/lightmap/vert_viewer.glsl @@ -0,0 +1,21 @@ + +#include + +layout(location = 0) out vec3 FragRay; + +vec2 positions[4] = vec2[]( + vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + vec2(1.0, 1.0) +); + +void main() +{ + vec4 viewpos = vec4(positions[gl_VertexIndex] * 2.0 - 1.0, -1.0, 1.0); + viewpos.x /= ProjX; + viewpos.y = -viewpos.y / ProjY; + FragRay = ((ViewToWorld * viewpos).xyz - CameraPos); + + gl_Position = vec4((positions[gl_VertexIndex] * 2.0 - 1.0) * vec2(1.0, -1.0), 1.0, 1.0); +}