Jump to content

Starting with Shadowmaps on Vulkan

Josh

145 views

Now that we have lights working in our clustered forward Vulkan renderer (same great technique the latest DOOM games are using) I am starting to implement shadow maps. The first issue that came up was managing render-to-texture when the texture might still be in use rendering the previous frame. At first I thought multiple shadowmaps would be needed per light, like a double-buffering system, but that would double the number of shadow textures and video memory. Instead, I created a simple object pool which stores spare shadowmaps that can be swapped around and used as they are needed.

It turns out I already have pretty much all the code I need because Vulkan's swapchain creation works exactly the same way, by rendering to a series of images. I worked through the code slowly and came up with this by the end of the day, which runs successfully without throwing any validation errors:

	bool RenderBuffer::Initialize(shared_ptr<RenderContext> context, const int width, const int height, const int depth, const int colorcomponents, const bool depthcomponent, const int samples)
	{
		this->device = GameEngine::Get()->renderingthreadmanager->instance;

		int totalcomponents = colorcomponents;
		if (depthcomponent) totalcomponents++;

		std::fill(colortexture.begin(), colortexture.end(), nullptr);
		depthtexture = nullptr;

		//Create color images
		for (int i = 0; i < colorcomponents; ++i)
		{
			colortexture[i] = make_shared<RenderTexture>();
			colortexture[i]->Initialize(VK_IMAGE_TYPE_2D, device->chaininfo.imageFormat, width, height, 1, 0, false, -1,-1,-1,-1,1, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
			colorimages[i] = colortexture[i]->vkimage;
		}

		//Create depth image
		if (depthcomponent)
		{
			depthtexture = make_shared<RenderTexture>();
			depthtexture->Initialize(VK_IMAGE_TYPE_2D, device->depthformat, width, height, 1, samples, false, -1, -1, -1, -1, 1, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
		}

		//Create image views
		imageviews.resize(totalcomponents);
		VkImageViewCreateInfo createInfo = {};
		createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
		createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
		createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
		createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
		createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
		createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
		createInfo.subresourceRange.baseMipLevel = 0;
		createInfo.subresourceRange.levelCount = 1;
		createInfo.subresourceRange.baseArrayLayer = 0;
		createInfo.subresourceRange.layerCount = 1;

		// Create color image views
		for (size_t i = 0; i < colorcomponents; i++)
		{
			createInfo.image = colorimages[i];			
			createInfo.format = device->chaininfo.imageFormat;
			createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
			VkAssert(vkCreateImageView(device->device, &createInfo, nullptr, &imageviews[i]));
		}

		//Create depth image view
		if (depthcomponent)
		{
			createInfo.image = depthtexture->vkimage;
			createInfo.format = depthtexture->format;
			createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
			VkAssert(vkCreateImageView(device->device, &createInfo, nullptr, &imageviews[colorcomponents]));
		}

		//Create framebuffer
		VkFramebufferCreateInfo framebufferInfo = {};
		framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
		framebufferInfo.renderPass = device->renderpass->pass;
		framebufferInfo.attachmentCount = 2;
		framebufferInfo.pAttachments = imageviews.data();
		framebufferInfo.width = width;
		framebufferInfo.height = height;
		framebufferInfo.layers = 1;
		VkAssert(vkCreateFramebuffer(device->device, &framebufferInfo, nullptr, &framebuffer));

		return true;
	}

The blog cover image isn't the Vulkan renderer, I just found a random image of Leadwerks shadows.

  • Like 2


0 Comments


Recommended Comments

There are no comments to display.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...