Hook up some more PBR stuff

This commit is contained in:
Magnus Norddahl 2024-10-03 02:37:08 +02:00
commit c0bbe3a43a
11 changed files with 333 additions and 54 deletions

View file

@ -119,6 +119,8 @@ class ImageBuilder
public:
ImageBuilder();
ImageBuilder& Type(VkImageType type);
ImageBuilder& Flags(VkImageCreateFlags flags);
ImageBuilder& Size(int width, int height, int miplevels = 1, int arrayLayers = 1);
ImageBuilder& Samples(VkSampleCountFlagBits samples);
ImageBuilder& Format(VkFormat format);

View file

@ -276,6 +276,18 @@ ImageBuilder::ImageBuilder()
imageInfo.flags = 0;
}
ImageBuilder& ImageBuilder::Type(VkImageType type)
{
imageInfo.imageType = type;
return *this;
}
ImageBuilder& ImageBuilder::Flags(VkImageCreateFlags flags)
{
imageInfo.flags = flags;
return *this;
}
ImageBuilder& ImageBuilder::Size(int width, int height, int mipLevels, int arrayLayers)
{
imageInfo.extent.width = width;
@ -1759,6 +1771,7 @@ std::vector<VulkanCompatibleDevice> VulkanDeviceBuilder::FindDevices(const std::
enabledFeatures.Features.shaderClipDistance = deviceFeatures.Features.shaderClipDistance;
enabledFeatures.Features.multiDrawIndirect = deviceFeatures.Features.multiDrawIndirect;
enabledFeatures.Features.independentBlend = deviceFeatures.Features.independentBlend;
enabledFeatures.Features.imageCubeArray = deviceFeatures.Features.imageCubeArray;
enabledFeatures.BufferDeviceAddress.bufferDeviceAddress = deviceFeatures.BufferDeviceAddress.bufferDeviceAddress;
enabledFeatures.AccelerationStructure.accelerationStructure = deviceFeatures.AccelerationStructure.accelerationStructure;
enabledFeatures.RayQuery.rayQuery = deviceFeatures.RayQuery.rayQuery;

View file

@ -143,17 +143,19 @@ void VkDescriptorSetManager::UpdateFixedSet()
WriteDescriptors update;
update.AddCombinedImageSampler(Fixed.Set.get(), 0, fb->GetTextureManager()->Shadowmap.View.get(), fb->GetSamplerManager()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
update.AddCombinedImageSampler(Fixed.Set.get(), 1, fb->GetTextureManager()->Lightmap.View.get(), fb->GetSamplerManager()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
update.AddCombinedImageSampler(Fixed.Set.get(), 1, fb->GetTextureManager()->Lightmap.Image.View.get(), fb->GetSamplerManager()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
update.AddCombinedImageSampler(Fixed.Set.get(), 2, fb->GetBuffers()->SceneLinearDepth.View.get(), fb->GetSamplerManager()->Get(PPFilterMode::Nearest, PPWrapMode::Clamp), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
update.AddCombinedImageSampler(Fixed.Set.get(), 3, fb->GetTextureManager()->Irradiancemap.Image.View.get(), fb->GetSamplerManager()->IrradiancemapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
update.AddCombinedImageSampler(Fixed.Set.get(), 4, fb->GetTextureManager()->Prefiltermap.Image.View.get(), fb->GetSamplerManager()->PrefiltermapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if (fb->IsRayQueryEnabled())
{
update.AddAccelerationStructure(Fixed.Set.get(), 3, fb->GetLevelMesh()->GetAccelStruct());
update.AddAccelerationStructure(Fixed.Set.get(), 5, fb->GetLevelMesh()->GetAccelStruct());
}
else
{
update.AddBuffer(Fixed.Set.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetNodeBuffer());
update.AddBuffer(Fixed.Set.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer());
update.AddBuffer(Fixed.Set.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer());
update.AddBuffer(Fixed.Set.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetNodeBuffer());
update.AddBuffer(Fixed.Set.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer());
update.AddBuffer(Fixed.Set.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer());
}
update.Execute(fb->GetDevice());
}
@ -269,15 +271,17 @@ void VkDescriptorSetManager::CreateFixedLayout()
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
if (fb->IsRayQueryEnabled())
{
builder.AddBinding(3, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
builder.AddBinding(5, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
}
else
{
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);
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("VkDescriptorSetManager.Fixed.SetLayout");
Fixed.Layout = builder.Create(fb->GetDevice());
@ -343,7 +347,7 @@ void VkDescriptorSetManager::CreateRSBufferPool()
void VkDescriptorSetManager::CreateFixedPool()
{
DescriptorPoolBuilder poolbuilder;
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3 * MaxFixedSets);
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 5 * MaxFixedSets);
if (fb->IsRayQueryEnabled())
{
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * MaxFixedSets);

View file

@ -130,6 +130,8 @@ VkSamplerManager::VkSamplerManager(VulkanRenderDevice* fb) : fb(fb)
CreateShadowmapSampler();
CreateLightmapSampler();
CreateZMinMaxSampler();
CreateIrradiancemapSampler();
CreatePrefiltermapSampler();
}
VkSamplerManager::~VkSamplerManager()
@ -325,3 +327,19 @@ void VkSamplerManager::CreateZMinMaxSampler()
.DebugName("VkRenderBuffers.ZMinMaxSampler")
.Create(fb->GetDevice());
}
void VkSamplerManager::CreateIrradiancemapSampler()
{
IrradiancemapSampler = SamplerBuilder()
.AddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
.DebugName("VkRenderBuffers.IrradiancemapSampler")
.Create(fb->GetDevice());
}
void VkSamplerManager::CreatePrefiltermapSampler()
{
PrefiltermapSampler = SamplerBuilder()
.AddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
.DebugName("VkRenderBuffers.PrefiltermapSampler")
.Create(fb->GetDevice());
}

View file

@ -29,6 +29,8 @@ public:
std::unique_ptr<VulkanSampler> ShadowmapSampler;
std::unique_ptr<VulkanSampler> LightmapSampler;
std::unique_ptr<VulkanSampler> ZMinMaxSampler;
std::unique_ptr<VulkanSampler> IrradiancemapSampler;
std::unique_ptr<VulkanSampler> PrefiltermapSampler;
private:
void CreateHWSamplers();
@ -36,6 +38,8 @@ private:
void CreateShadowmapSampler();
void CreateLightmapSampler();
void CreateZMinMaxSampler();
void CreateIrradiancemapSampler();
void CreatePrefiltermapSampler();
VulkanRenderDevice* fb = nullptr;
std::array<std::unique_ptr<VulkanSampler>, NUMSAMPLERS> mSamplers;

View file

@ -32,6 +32,8 @@ VkTextureManager::VkTextureManager(VulkanRenderDevice* fb) : fb(fb)
CreateNullTexture();
CreateShadowmap();
CreateLightmap();
CreateIrradiancemap();
CreatePrefiltermap();
}
VkTextureManager::~VkTextureManager()
@ -192,32 +194,64 @@ void VkTextureManager::CreateLightmap()
CreateLightmap(1, 1, std::move(data));
}
void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray<uint16_t>&& newPixelData)
void VkTextureManager::CreateIrradiancemap()
{
if (LMTextureSize == newLMTextureSize && LMTextureCount == newLMTextureCount + 1 && newPixelData.Size() == 0)
TArray<uint16_t> data;
for (int arrayIndex = 0; arrayIndex < 6; arrayIndex++)
{
data.Push(0);
data.Push(0);
data.Push(0);
}
CreateIrradiancemap(1, 6, std::move(data));
}
void VkTextureManager::CreatePrefiltermap()
{
TArray<uint16_t> data;
int size = 1 << MAX_REFLECTION_LOD;
for (int arrayIndex = 0; arrayIndex < 6; arrayIndex++)
{
for (int level = 0; level < MAX_REFLECTION_LOD; level++)
{
int mipsize = size >> level;
for (int i = 0; i < mipsize; i++)
{
data.Push(0);
data.Push(0);
data.Push(0);
}
}
}
CreatePrefiltermap(size, 6, std::move(data));
}
void VkTextureManager::CreateIrradiancemap(int size, int count, TArray<uint16_t>&& newPixelData)
{
if (Irradiancemap.Size == size && Irradiancemap.Count == count && newPixelData.Size() == 0)
return;
LMTextureSize = newLMTextureSize;
LMTextureCount = newLMTextureCount + 1; // the extra texture is for the dynamic lightmap
int w = newLMTextureSize;
int h = newLMTextureSize;
int count = newLMTextureCount;
Irradiancemap.Size = size;
Irradiancemap.Count = count;
int w = size;
int h = size;
int pixelsize = 8;
Lightmap.Reset(fb);
Irradiancemap.Image.Reset(fb);
Lightmap.Image = ImageBuilder()
.Size(w, h, 1, LMTextureCount)
Irradiancemap.Image.Image = ImageBuilder()
.Size(w, h, 1, count)
.Format(VK_FORMAT_R16G16B16A16_SFLOAT)
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
.DebugName("VkRenderBuffers.Lightmap")
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
.Flags(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
.DebugName("VkTextureManager.Irradiancemap")
.Create(fb->GetDevice());
Lightmap.View = ImageViewBuilder()
.Type(VK_IMAGE_VIEW_TYPE_2D_ARRAY)
.Image(Lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT)
.DebugName("VkRenderBuffers.LightmapView")
Irradiancemap.Image.View = ImageViewBuilder()
.Type(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
.Image(Irradiancemap.Image.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT)
.DebugName("VkTextureManager.IrradiancemapView")
.Create(fb->GetDevice());
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
@ -231,7 +265,7 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun
auto stagingBuffer = BufferBuilder()
.Size(totalSize)
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
.DebugName("VkHardwareTexture.mStagingBuffer")
.DebugName("VkRenderBuffers.IrradiancemapStagingBuffer")
.Create(fb->GetDevice());
uint16_t one = 0x3c00; // half-float 1.0
@ -247,7 +281,7 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun
stagingBuffer->Unmap();
VkImageTransition()
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, 1, 0, LMTextureCount)
.AddImage(&Irradiancemap.Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, 1, 0, count)
.Execute(cmdbuffer);
VkBufferImageCopy region = {};
@ -256,7 +290,176 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun
region.imageExtent.depth = 1;
region.imageExtent.width = w;
region.imageExtent.height = h;
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Irradiancemap.Image.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
newPixelData.Clear();
}
VkImageTransition()
.AddImage(&Irradiancemap.Image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, 1, 0, count)
.Execute(cmdbuffer);
}
void VkTextureManager::CreatePrefiltermap(int size, int count, TArray<uint16_t>&& newPixelData)
{
if (Prefiltermap.Size == size && Prefiltermap.Count == count && newPixelData.Size() == 0)
return;
Prefiltermap.Size = size;
Prefiltermap.Count = count;
int w = size;
int h = size;
int pixelsize = 8;
int miplevels = MAX_REFLECTION_LOD + 1;
Prefiltermap.Image.Reset(fb);
Prefiltermap.Image.Image = ImageBuilder()
.Size(w, h, miplevels, count)
.Format(VK_FORMAT_R16G16B16A16_SFLOAT)
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
.Flags(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
.DebugName("VkTextureManager.Prefiltermap")
.Create(fb->GetDevice());
Prefiltermap.Image.View = ImageViewBuilder()
.Type(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
.Image(Prefiltermap.Image.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT)
.DebugName("VkTextureManager.PrefiltermapView")
.Create(fb->GetDevice());
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
if (count > 0 && newPixelData.Size() >= (size_t)w * h * count * 3)
{
assert(newPixelData.Size() == (size_t)w * h * count * 3);
int totalSize = 0;
for (int level = 0; level < miplevels; level++)
{
int mipwidth = std::max(w >> level, 1);
int mipheight = std::max(h >> level, 1);
totalSize += mipwidth * mipheight * count * pixelsize;
}
auto stagingBuffer = BufferBuilder()
.Size(totalSize)
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
.DebugName("VkTextureManager.PrefiltermapStagingBuffer")
.Create(fb->GetDevice());
uint16_t one = 0x3c00; // half-float 1.0
const uint16_t* src = newPixelData.Data();
uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize);
for (int i = w * h * count; i > 0; i--)
{
*(data++) = *(src++);
*(data++) = *(src++);
*(data++) = *(src++);
*(data++) = one;
}
stagingBuffer->Unmap();
VkImageTransition()
.AddImage(&Prefiltermap.Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, miplevels, 0, count)
.Execute(cmdbuffer);
int offset = 0;
for (int level = 0; level < miplevels; level++)
{
VkBufferImageCopy region = {};
region.bufferOffset = offset;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.layerCount = count;
region.imageSubresource.mipLevel = level;
region.imageExtent.depth = 1;
region.imageExtent.width = w;
region.imageExtent.height = h;
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Prefiltermap.Image.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
int mipwidth = std::max(w >> level, 1);
int mipheight = std::max(h >> level, 1);
offset += mipwidth * mipheight * count * pixelsize;
}
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
newPixelData.Clear();
}
VkImageTransition()
.AddImage(&Prefiltermap.Image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, miplevels, 0, count)
.Execute(cmdbuffer);
}
void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray<uint16_t>&& newPixelData)
{
if (Lightmap.Size == newLMTextureSize && Lightmap.Count == newLMTextureCount + 1 && newPixelData.Size() == 0)
return;
Lightmap.Size = newLMTextureSize;
Lightmap.Count = newLMTextureCount + 1; // the extra texture is for the dynamic lightmap
int w = newLMTextureSize;
int h = newLMTextureSize;
int count = newLMTextureCount;
int pixelsize = 8;
Lightmap.Image.Reset(fb);
Lightmap.Image.Image = ImageBuilder()
.Size(w, h, 1, Lightmap.Count)
.Format(VK_FORMAT_R16G16B16A16_SFLOAT)
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
.DebugName("VkTextureManager.Lightmap")
.Create(fb->GetDevice());
Lightmap.Image.View = ImageViewBuilder()
.Type(VK_IMAGE_VIEW_TYPE_2D_ARRAY)
.Image(Lightmap.Image.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT)
.DebugName("VkTextureManager.LightmapView")
.Create(fb->GetDevice());
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
if (count > 0 && newPixelData.Size() >= (size_t)w * h * count * 3)
{
assert(newPixelData.Size() == (size_t)w * h * count * 3);
int totalSize = w * h * count * pixelsize;
auto stagingBuffer = BufferBuilder()
.Size(totalSize)
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
.DebugName("VkTextureManager.LightmapStagingBuffer")
.Create(fb->GetDevice());
uint16_t one = 0x3c00; // half-float 1.0
const uint16_t* src = newPixelData.Data();
uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize);
for (int i = w * h * count; i > 0; i--)
{
*(data++) = *(src++);
*(data++) = *(src++);
*(data++) = *(src++);
*(data++) = one;
}
stagingBuffer->Unmap();
VkImageTransition()
.AddImage(&Lightmap.Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, 1, 0, Lightmap.Count)
.Execute(cmdbuffer);
VkBufferImageCopy region = {};
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.layerCount = count;
region.imageExtent.depth = 1;
region.imageExtent.width = w;
region.imageExtent.height = h;
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Lightmap.Image.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
@ -264,13 +467,13 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun
}
VkImageTransition()
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, 1, 0, LMTextureCount)
.AddImage(&Lightmap.Image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, 1, 0, Lightmap.Count)
.Execute(cmdbuffer);
}
void VkTextureManager::DownloadLightmap(int arrayIndex, uint16_t* buffer)
{
unsigned int totalSize = LMTextureSize * LMTextureSize * 4;
unsigned int totalSize = Lightmap.Size * Lightmap.Size * 4;
auto stagingBuffer = BufferBuilder()
.Size(totalSize * sizeof(uint16_t))
@ -281,7 +484,7 @@ void VkTextureManager::DownloadLightmap(int arrayIndex, uint16_t* buffer)
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
PipelineBarrier()
.AddImage(Lightmap.Image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, arrayIndex, 1)
.AddImage(Lightmap.Image.Image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, arrayIndex, 1)
.Execute(cmdbuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
VkBufferImageCopy region = {};
@ -289,13 +492,13 @@ void VkTextureManager::DownloadLightmap(int arrayIndex, uint16_t* buffer)
region.imageSubresource.baseArrayLayer = arrayIndex;
region.imageSubresource.layerCount = 1;
region.imageSubresource.mipLevel = 0;
region.imageExtent.width = LMTextureSize;
region.imageExtent.height = LMTextureSize;
region.imageExtent.width = Lightmap.Size;
region.imageExtent.height = Lightmap.Size;
region.imageExtent.depth = 1;
cmdbuffer->copyImageToBuffer(Lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer->buffer, 1, &region);
cmdbuffer->copyImageToBuffer(Lightmap.Image.Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer->buffer, 1, &region);
PipelineBarrier()
.AddImage(Lightmap.Image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, arrayIndex, 1)
.AddImage(Lightmap.Image.Image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, arrayIndex, 1)
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
fb->GetCommands()->WaitForCommands(false);

View file

@ -23,7 +23,9 @@ public:
void BeginFrame();
void CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray<uint16_t>&& newPixelData);
void CreateLightmap(int size, int count, TArray<uint16_t>&& data);
void CreateIrradiancemap(int size, int count, TArray<uint16_t>&& data);
void CreatePrefiltermap(int size, int count, TArray<uint16_t>&& data);
void DownloadLightmap(int arrayIndex, uint16_t* buffer);
VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex);
@ -41,14 +43,22 @@ public:
int GetHWTextureCount() { return (int)Textures.size(); }
VkTextureImage Shadowmap;
VkTextureImage Lightmap;
int LMTextureSize = 0;
int LMTextureCount = 0;
struct
{
VkTextureImage Image;
int Size = 0;
int Count = 0;
} Lightmap, Irradiancemap, Prefiltermap;
static const int MAX_REFLECTION_LOD = 4; // Note: must match what lightmodel_pbr.glsl expects
private:
void CreateNullTexture();
void CreateShadowmap();
void CreateLightmap();
void CreateIrradiancemap();
void CreatePrefiltermap();
VkPPTexture* GetVkTexture(PPTexture* texture);

View file

@ -378,8 +378,8 @@ void VkLightmapper::CopyResult()
if (pixels == 0)
return;
VkTextureImage* destTexture = &fb->GetTextureManager()->Lightmap;
int destSize = fb->GetTextureManager()->LMTextureSize;
VkTextureImage* destTexture = &fb->GetTextureManager()->Lightmap.Image;
int destSize = fb->GetTextureManager()->Lightmap.Size;
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();

View file

@ -2,10 +2,12 @@
layout(set = 0, binding = 0) uniform sampler2D ShadowMap;
layout(set = 0, binding = 1) uniform sampler2DArray LightMap;
layout(set = 0, binding = 2) uniform sampler2D LinearDepth;
layout(set = 0, binding = 3) uniform samplerCubeArray IrradianceMap;
layout(set = 0, binding = 4) uniform samplerCubeArray PrefilterMap;
#if defined(USE_RAYTRACE)
#if defined(SUPPORTS_RAYQUERY)
layout(set = 0, binding = 3) uniform accelerationStructureEXT TopLevelAS;
layout(set = 0, binding = 5) uniform accelerationStructureEXT TopLevelAS;
#else
struct CollisionNode
{
@ -18,7 +20,7 @@ struct CollisionNode
int element_index;
int padding3;
};
layout(std430, set = 0, binding = 3) buffer NodeBuffer
layout(std430, set = 0, binding = 5) buffer NodeBuffer
{
int nodesRoot;
int nodebufferPadding1;
@ -33,7 +35,7 @@ struct SurfaceVertex // Note: this must always match the FFlatVertex struct
vec2 uv;
vec2 luv;
};
layout(std430, set = 0, binding = 4) buffer VertexBuffer { SurfaceVertex vertices[]; };
layout(std430, set = 0, binding = 5) buffer ElementBuffer { int elements[]; };
layout(std430, set = 0, binding = 6) buffer VertexBuffer { SurfaceVertex vertices[]; };
layout(std430, set = 0, binding = 7) buffer ElementBuffer { int elements[]; };
#endif
#endif

View file

@ -38,6 +38,8 @@ layout(push_constant) uniform PushConstants
#define glowtexture texture4
#endif
#define BrdfLUT 0 // the BRDF convoluted texture is always in this texture slot
#define uObjectColor data[uDataIndex].uObjectColor
#define uObjectColor2 data[uDataIndex].uObjectColor2
#define uDynLightColor data[uDataIndex].uDynLightColor

View file

@ -66,8 +66,7 @@ vec3 ProcessMaterialLight(Material material, vec3 ambientLight)
{
vec3 worldpos = pixelpos.xyz;
vec3 albedo = pow(material.Base.rgb, vec3(2.2)); // sRGB to linear
ambientLight = pow(ambientLight, vec3(2.2));
vec3 albedo = material.Base.rgb;
float metallic = material.Metallic;
float roughness = material.Roughness;
@ -168,28 +167,50 @@ vec3 ProcessMaterialLight(Material material, vec3 ambientLight)
}
}
// Pretend we sampled the sector light level from an irradiance map
// Treat the ambient sector light as if it is a light source next to the wall
{
vec3 NN = N;
vec3 VV = V;
vec3 LL = N;
vec3 HH = normalize(VV + LL);
vec3 radiance = ambientLight.rgb * 2.5;
// cook-torrance brdf
float NDF = DistributionGGX(NN, HH, roughness);
float G = GeometrySmith(NN, VV, LL, roughness);
vec3 F = fresnelSchlick(clamp(dot(HH, VV), 0.0, 1.0), F0);
vec3 kS = F;
vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic);
vec3 nominator = NDF * G * F;
float denominator = 4.0 * clamp(dot(NN, VV), 0.0, 1.0) * clamp(dot(NN, LL), 0.0, 1.0);
vec3 specular = nominator / max(denominator, 0.001);
specular = metallic * albedo * 0.40;
Lo += (kD * albedo / PI + specular) * radiance;
}
float probeIndex = 0.0; // To do: get this from an uniform
vec3 F = fresnelSchlickRoughness(clamp(dot(N, V), 0.0, 1.0), F0, roughness);
vec3 kS = F;
vec3 kD = 1.0 - kS;
vec3 irradiance = ambientLight; // texture(irradianceMap, N).rgb
vec3 irradiance = texture(IrradianceMap, vec4(N, probeIndex)).rgb;
vec3 diffuse = irradiance * albedo;
//kD *= 1.0 - metallic;
//const float MAX_REFLECTION_LOD = 4.0;
//vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb;
//vec2 envBRDF = texture(brdfLUT, vec2(clamp(dot(N, V), 0.0, 1.0), roughness)).rg;
//vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y);
kD *= 1.0 - metallic;
const float MAX_REFLECTION_LOD = 4.0;
vec3 R = reflect(-V, N);
vec3 prefilteredColor = textureLod(PrefilterMap, vec4(R, probeIndex), roughness * MAX_REFLECTION_LOD).rgb;
vec2 envBRDF = texture(BrdfLUT, vec2(clamp(dot(N, V), 0.0, 1.0), roughness)).rg;
vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y);
//vec3 ambient = (kD * diffuse + specular) * ao;
vec3 ambient = (kD * diffuse) * ao;
vec3 ambient = (kD * diffuse + specular) * ao;
vec3 color = max(ambient + Lo, vec3(0.0));
// Tonemap (reinhard) and apply sRGB gamma
//color = color / (color + vec3(1.0));
return pow(color, vec3(1.0 / 2.2));
return color;
}