From 3dbb4d7b9c7be8836efdc6259102e5b06aae24b3 Mon Sep 17 00:00:00 2001 From: dpjudas Date: Mon, 19 May 2025 17:23:28 +0200 Subject: [PATCH] Add lightmap and dynamic lights --- .../rendering/vulkan/textures/vk_texture.cpp | 31 ++++- .../static/shaders/scene/layout_shared.glsl | 1 + wadsrc/static/shaders/scene/lightmode.glsl | 114 +++++++++++++++++- 3 files changed, 139 insertions(+), 7 deletions(-) diff --git a/src/common/rendering/vulkan/textures/vk_texture.cpp b/src/common/rendering/vulkan/textures/vk_texture.cpp index 52e9111f0..79f25f12d 100644 --- a/src/common/rendering/vulkan/textures/vk_texture.cpp +++ b/src/common/rendering/vulkan/textures/vk_texture.cpp @@ -237,7 +237,7 @@ void VkTextureManager::CreateGamePalette() { GamePalette = ImageBuilder() .Format(VK_FORMAT_B8G8R8A8_UNORM) - .Size(256, 1) + .Size(512, 512) .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) .DebugName("VkDescriptorSetManager.GamePalette") .Create(fb->GetDevice()); @@ -250,6 +250,25 @@ void VkTextureManager::CreateGamePalette() void VkTextureManager::SetGamePalette() { + std::shared_ptr data(new uint32_t[512 * 512], [](void* p) { delete[](uint32_t*)p; }); + uint8_t* lut = (uint8_t*)data.get(); + for (int r = 0; r < 64; r++) + { + for (int g = 0; g < 64; g++) + { + for (int b = 0; b < 64; b++) + { + // Do not tonemap this. Must match the RGB666 lookup table from the software renderer exactly. + PalEntry color = GPalette.BaseColors[ColorMatcher.Pick((r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4))]; + int index = ((r * 64 + g) * 64 + b) * 4; + lut[index] = color.b; + lut[index + 1] = color.g; + lut[index + 2] = color.r; + lut[index + 3] = 255; + } + } + } + auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); PipelineBarrier() @@ -257,21 +276,21 @@ void VkTextureManager::SetGamePalette() .Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); auto stagingBuffer = BufferBuilder() - .Size(256 * 4) + .Size(512 * 512 * 4) .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) .DebugName("VkDescriptorSetManager.GamePaletteStagingBuffer") .Create(fb->GetDevice()); - void* data = stagingBuffer->Map(0, 256 * 4); - memcpy(data, GPalette.BaseColors, 256 * 4); + void* dest = stagingBuffer->Map(0, 512 * 512 * 4); + memcpy(dest, data.get(), 512 * 512 * 4); stagingBuffer->Unmap(); VkBufferImageCopy region = {}; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.layerCount = 1; region.imageExtent.depth = 1; - region.imageExtent.width = 256; - region.imageExtent.height = 1; + region.imageExtent.width = 512; + region.imageExtent.height = 512; cmdbuffer->copyBufferToImage(stagingBuffer->buffer, GamePalette->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer)); diff --git a/wadsrc/static/shaders/scene/layout_shared.glsl b/wadsrc/static/shaders/scene/layout_shared.glsl index e4351a049..53202a183 100644 --- a/wadsrc/static/shaders/scene/layout_shared.glsl +++ b/wadsrc/static/shaders/scene/layout_shared.glsl @@ -25,6 +25,7 @@ #endif #define BrdfLUT 1 // the BRDF convoluted texture is always in this texture slot +#define PaletteLUT 2 // the RGB666 lookup table from a color to the game palette is always in this texture slot #define uObjectColor data[uDataIndex].uObjectColor #define uObjectColor2 data[uDataIndex].uObjectColor2 diff --git a/wadsrc/static/shaders/scene/lightmode.glsl b/wadsrc/static/shaders/scene/lightmode.glsl index 76c01b255..c5b5ad129 100644 --- a/wadsrc/static/shaders/scene/lightmode.glsl +++ b/wadsrc/static/shaders/scene/lightmode.glsl @@ -6,6 +6,23 @@ #include "shaders/scene/material.glsl" #include "shaders/scene/fogball.glsl" +#ifndef SIMPLE3D +vec3 swLightContribution(DynLightInfo light, vec3 normal); +float distanceAttenuation(float dist, float radius, float strength, float linearity); +float spotLightAttenuation(vec3 lightpos, vec3 spotdir, float lightCosInnerAngle, float lightCosOuterAngle); +float traceSun(vec3 SunDir); +float shadowAttenuation(vec3 lightpos, int shadowIndex, float softShadowRadius, int flags); +#endif + +vec3 PickGamePaletteColor(vec3 color) +{ + ivec3 c = ivec3(clamp(color.rgb, vec3(0.0), vec3(1.0)) * 63.0 + 0.5); + int index = (c.r * 64 + c.g) * 64 + c.b; + int tx = index % 512; + int ty = index / 512; + return texelFetch(textures[PaletteLUT], ivec2(tx, ty), 0).rgb; +} + //=========================================================================== // // Calculate light @@ -38,7 +55,49 @@ vec4 getLightColor(Material material) float shade = 2.0 - (L + 12.0) / 128.0; int light = max(int((shade - vis) * 32), 0); - return vec4(texelFetch(textures[uColormapIndex], ivec2(color, light), 0).rgb, 1.0); + vec3 matColor = texelFetch(textures[uColormapIndex], ivec2(color, 0), 0).rgb; + vec4 frag = vec4(texelFetch(textures[uColormapIndex], ivec2(color, light), 0).rgb, 1.0); + + vec4 dynlight = uDynLightColor; + + if (vLightmap.z >= 0.0) + { + dynlight.rgb += texture(LightMap, vLightmap).rgb; + } + + vec3 normal = material.Normal; + + #ifndef SIMPLE3D + #ifndef UBERSHADER + #ifdef SHADE_VERTEX + dynlight.rgb += vLightColor; + #else + if (uLightIndex >= 0) + { + ivec4 lightRange = getLightRange(); + + if (lightRange.z > lightRange.x) + { + // modulated lights + for(int i=lightRange.x; i 0.0) // Skip shadow map test if possible + { + if((light.flags & (LIGHTINFO_SUN | LIGHTINFO_TRACE)) == (LIGHTINFO_SUN | LIGHTINFO_TRACE)) + { + attenuation *= traceSun(lightdir); + } + else if((light.flags & (LIGHTINFO_SHADOWMAPPED | LIGHTINFO_SUN)) == LIGHTINFO_SHADOWMAPPED) + { + attenuation *= shadowAttenuation(light.pos.xyz, light.shadowIndex, light.softShadowRadius, light.flags); + } + + return light.color.rgb * attenuation; + } + else + { + return vec3(0.0); + } + } +#endif