Archived
1
Fork 0

Add moving camera

This commit is contained in:
Joshua Goins 2018-10-25 08:57:36 -04:00
parent 82ede190a6
commit dd8131a059
6 changed files with 82 additions and 63 deletions

8
include/camera.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#include <glm/glm.hpp>
class Camera {
public:
glm::vec3 position, target;
};

View file

@ -19,11 +19,11 @@ struct RenderTarget {
VkImage* offscreenColorImages = nullptr;
VkDeviceMemory* offscreenColorMemory = nullptr;
VkImageView* offscreenColorImageViews = nullptr;
VkImage* offscreenDepthImages = nullptr;
VkDeviceMemory* offscreenDepthMemory = nullptr;
VkImageView* offscreenDepthImageViews = nullptr;
VkFramebuffer* offscreenFramebuffers = nullptr;
VkCommandBuffer* commandBuffers = nullptr;
@ -37,17 +37,18 @@ struct RenderTarget {
class World;
class Mesh;
class Camera;
class Renderer {
public:
Renderer();
~Renderer();
void render(World& world, RenderTarget* target);
void render(World& world, Camera& camera, RenderTarget* target);
RenderTarget* createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTarget* oldRenderTarget = nullptr);
void destroyRenderTarget(RenderTarget* target);
void takeScreenshot(RenderTarget* target);
VkShaderModule createShader(const char* path);

View file

@ -5,13 +5,14 @@
class Renderer;
class World;
struct RenderTarget;
class Camera;
class WorldPass {
public:
WorldPass(Renderer& renderer);
~WorldPass();
void render(VkCommandBuffer commandBuffer, World& world, RenderTarget* target);
void render(VkCommandBuffer commandBuffer, World& world, Camera& camera, RenderTarget* target);
VkRenderPass getRenderPass() const {
return renderPass_;
@ -23,17 +24,17 @@ private:
void createPipeline();
void createUniformBuffer();
void createDescriptorSet();
VkRenderPass renderPass_ = nullptr;
VkDescriptorSetLayout setLayout_ = nullptr;
VkPipelineLayout pipelineLayout_ = nullptr;
VkPipeline pipeline_ = nullptr;
VkDeviceMemory lightMemory_ = nullptr;
VkBuffer lightBuffer_ = nullptr;
VkDescriptorSet descriptorSet_ = nullptr;
Renderer& renderer_;

View file

@ -13,6 +13,7 @@
#include "world.h"
#include "mesh.h"
#include "light.h"
#include "camera.h"
SDL_Window* window = nullptr;
@ -145,6 +146,10 @@ int main(int, char*[]) {
world.lights.push_back(light);
Camera camera;
camera.position.y = 1;
camera.position.z = 3;
bool running = true;
while(running) {
SDL_Event event = {};
@ -174,7 +179,9 @@ int main(int, char*[]) {
}
}
renderer->render(world, target);
camera.position.x = sin(platform::getTime() / 500.0f);
renderer->render(world, camera, target);
}
delete light;

View file

@ -10,6 +10,7 @@
#include "platform.h"
#include "mesh.h"
#include "camera.h"
Renderer::Renderer() {
createInstance();
@ -47,12 +48,12 @@ Renderer::~Renderer() {
vkDestroyInstance(instance_, nullptr);
}
void Renderer::render(World& world, RenderTarget* target) {
void Renderer::render(World& world, Camera& camera, RenderTarget* target) {
vkAcquireNextImageKHR(device_, target->swapchain, UINT64_MAX, target->imageAvailableSemaphore, nullptr, &target->currentImage);
vkWaitForFences(device_, 1, &target->fences[target->currentImage], true, UINT64_MAX);
vkResetFences(device_, 1, &target->fences[target->currentImage]);
const VkCommandBuffer commandBuffer = target->commandBuffers[target->currentImage];
VkCommandBufferBeginInfo beginInfo = {};
@ -72,7 +73,7 @@ void Renderer::render(World& world, RenderTarget* target) {
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
worldPass_->render(commandBuffer, world, target);
worldPass_->render(commandBuffer, world, camera, target);
VkClearValue clearColor = {};
@ -258,7 +259,7 @@ RenderTarget* Renderer::createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTa
vkCreateImageView(device_, &createInfo, nullptr, &target->offscreenColorImageViews[i]);
}
// offscreen depth image
{
VkImageCreateInfo imageCreateInfo = {};
@ -273,21 +274,21 @@ RenderTarget* Renderer::createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTa
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
vkCreateImage(device_, &imageCreateInfo, nullptr, &target->offscreenDepthImages[i]);
VkMemoryRequirements memoryRequirements = {};
vkGetImageMemoryRequirements(device_, target->offscreenDepthImages[i], &memoryRequirements);
VkMemoryAllocateInfo allocateInfo = {};
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
vkAllocateMemory(device_, &allocateInfo, nullptr, &target->offscreenDepthMemory[i]);
vkBindImageMemory(device_, target->offscreenDepthImages[i], target->offscreenDepthMemory[i], 0);
}
// offscreen depth image view
{
VkImageViewCreateInfo createInfo = {};
@ -298,7 +299,7 @@ RenderTarget* Renderer::createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTa
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.layerCount = 1;
vkCreateImageView(device_, &createInfo, nullptr, &target->offscreenDepthImageViews[i]);
}
@ -308,7 +309,7 @@ RenderTarget* Renderer::createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTa
target->offscreenColorImageViews[i],
target->offscreenDepthImageViews[i]
};
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = worldPass_->getRenderPass();
@ -371,11 +372,11 @@ void Renderer::destroyRenderTarget(RenderTarget* target) {
for(uint32_t i = 0; i < target->numImages; i++) {
vkDestroyFramebuffer(device_, target->offscreenFramebuffers[i], nullptr);
vkDestroyImageView(device_, target->offscreenDepthImageViews[i], nullptr);
vkFreeMemory(device_, target->offscreenDepthMemory[i], nullptr);
vkDestroyImage(device_, target->offscreenDepthImages[i], nullptr);
vkDestroyImageView(device_, target->offscreenColorImageViews[i], nullptr);
vkFreeMemory(device_, target->offscreenColorMemory[i], nullptr);
vkDestroyImage(device_, target->offscreenColorImages[i], nullptr);
@ -383,7 +384,7 @@ void Renderer::destroyRenderTarget(RenderTarget* target) {
vkDestroyFramebuffer(device_, target->swapchainFramebuffers[i], nullptr);
vkDestroyImageView(device_, target->swapchainImageViews[i], nullptr);
}
delete[] target->offscreenFramebuffers;
delete[] target->offscreenDepthImageViews;
delete[] target->offscreenDepthMemory;
@ -395,7 +396,7 @@ void Renderer::destroyRenderTarget(RenderTarget* target) {
delete[] target->swapchainFramebuffers;
delete[] target->swapchainImageViews;
delete[] target->swapchainImages;
delete[] target->postSets;
vkDestroySwapchainKHR(device_, target->swapchain, nullptr);
@ -416,35 +417,35 @@ void Renderer::takeScreenshot(RenderTarget* target) {
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkImage image = nullptr;
vkCreateImage(device_, &imageCreateInfo, nullptr, &image);
VkMemoryRequirements memoryRequirements = {};
vkGetImageMemoryRequirements(device_, image, &memoryRequirements);
VkMemoryAllocateInfo allocateInfo = {};
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VkDeviceMemory imageMemory = nullptr;
vkAllocateMemory(device_, &allocateInfo, nullptr, &imageMemory);
vkBindImageMemory(device_, image, imageMemory, 0);
VkCommandBufferAllocateInfo bufferAllocateInfo = {};
bufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
bufferAllocateInfo.commandPool = commandPool_;
bufferAllocateInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer = nullptr;
vkAllocateCommandBuffers(device_, &bufferAllocateInfo, &commandBuffer);
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(commandBuffer, &beginInfo);
// change screenshot image to transfer dst layout
{
VkImageMemoryBarrier imageMemoryBarrier = {};
@ -455,7 +456,7 @@ void Renderer::takeScreenshot(RenderTarget* target) {
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageMemoryBarrier.subresourceRange.layerCount = 1;
imageMemoryBarrier.subresourceRange.levelCount = 1;
vkCmdPipelineBarrier(
commandBuffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
@ -465,9 +466,9 @@ void Renderer::takeScreenshot(RenderTarget* target) {
0, nullptr,
1, &imageMemoryBarrier);
}
const VkImage srcImage = target->swapchainImages[0]; // FIXME: use previous image
// change offscreen image to transfer src layout
{
VkImageMemoryBarrier imageMemoryBarrier = {};
@ -480,7 +481,7 @@ void Renderer::takeScreenshot(RenderTarget* target) {
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageMemoryBarrier.subresourceRange.layerCount = 1;
imageMemoryBarrier.subresourceRange.levelCount = 1;
vkCmdPipelineBarrier(
commandBuffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
@ -490,7 +491,7 @@ void Renderer::takeScreenshot(RenderTarget* target) {
0, nullptr,
1, &imageMemoryBarrier);
}
VkImageCopy imageCopy = {};
imageCopy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageCopy.srcSubresource.layerCount = 1;
@ -499,7 +500,7 @@ void Renderer::takeScreenshot(RenderTarget* target) {
imageCopy.extent.width = target->extent.width;
imageCopy.extent.height = target->extent.height;
imageCopy.extent.depth = 1;
// Issue the copy command
vkCmdCopyImage(
commandBuffer,
@ -509,7 +510,7 @@ void Renderer::takeScreenshot(RenderTarget* target) {
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&imageCopy);
// change screenshot image from transfer dst to general (for mapping memory)
{
VkImageMemoryBarrier imageMemoryBarrier = {};
@ -522,7 +523,7 @@ void Renderer::takeScreenshot(RenderTarget* target) {
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageMemoryBarrier.subresourceRange.layerCount = 1;
imageMemoryBarrier.subresourceRange.levelCount = 1;
vkCmdPipelineBarrier(
commandBuffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
@ -532,7 +533,7 @@ void Renderer::takeScreenshot(RenderTarget* target) {
0, nullptr,
1, &imageMemoryBarrier);
}
// change offscreen image layout back to normal
{
VkImageMemoryBarrier imageMemoryBarrier = {};
@ -545,7 +546,7 @@ void Renderer::takeScreenshot(RenderTarget* target) {
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageMemoryBarrier.subresourceRange.layerCount = 1;
imageMemoryBarrier.subresourceRange.levelCount = 1;
vkCmdPipelineBarrier(
commandBuffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
@ -555,54 +556,54 @@ void Renderer::takeScreenshot(RenderTarget* target) {
0, nullptr,
1, &imageMemoryBarrier);
}
vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
VkFenceCreateInfo fenceCreateInfo = {};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
VkFence fence = nullptr;
vkCreateFence(device_, &fenceCreateInfo, nullptr, &fence);
vkQueueSubmit(graphicsQueue_, 1, &submitInfo, fence);
vkWaitForFences(device_, 1, &fence, true, -1);
vkDestroyFence(device_, fence, nullptr);
vkFreeCommandBuffers(device_, commandPool_, 1, &commandBuffer);
VkImageSubresource subResource = {};
subResource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
VkSubresourceLayout subResourceLayout = {};
vkGetImageSubresourceLayout(device_, image, &subResource, &subResourceLayout);
const char* data = nullptr;
vkMapMemory(device_, imageMemory, 0, VK_WHOLE_SIZE, 0, (void**)&data);
data += subResourceLayout.offset;
std::ofstream file("screenshot.ppm", std::ios::out | std::ios::binary);
file << "P6\n" << target->extent.width << "\n" << target->extent.height << "\n" << 255 << "\n";
for(uint32_t y = 0; y < target->extent.height; y++) {
const unsigned int* row = reinterpret_cast<const unsigned int*>(data);
for(uint32_t x = 0; x < target->extent.width; x++) {
file.write(reinterpret_cast<const char*>(row), 3);
row++;
}
data += subResourceLayout.rowPitch;
}
file.close();
vkUnmapMemory(device_, imageMemory);
vkFreeMemory(device_, imageMemory, nullptr);
vkDestroyImage(device_, image, nullptr);
}

View file

@ -7,6 +7,7 @@
#include "world.h"
#include "mesh.h"
#include "light.h"
#include "camera.h"
WorldPass::WorldPass(Renderer& renderer) : renderer_(renderer) {
createRenderPass();
@ -28,7 +29,7 @@ WorldPass::~WorldPass() {
vkDestroyBuffer(renderer_.getDevice(), lightBuffer_, nullptr);
}
void WorldPass::render(VkCommandBuffer commandBuffer, World& world, RenderTarget* target) {
void WorldPass::render(VkCommandBuffer commandBuffer, World& world, Camera& camera, RenderTarget* target) {
struct ShaderLight {
glm::vec4 position;
glm::vec3 color;
@ -65,7 +66,7 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, RenderTarget
for(const auto& mesh : world.meshes) {
glm::mat4 mvp;
mvp = glm::perspective(glm::radians(75.0f), (float)target->extent.width / target->extent.height, 0.1f, 100.0f);
mvp *= glm::lookAt(glm::vec3(2), glm::vec3(0), glm::vec3(0, -1, 0));
mvp *= glm::lookAt(camera.position, camera.target, glm::vec3(0, -1, 0));
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &mvp);