Skip to content

Commit 879a09f

Browse files
authored
Magic Lens (#59)
* create new pipeline class * populate pipeline * create magiclens test * don't cull * Don't do lighting * Create Uniform Buffer * more dev * Implement effects * magnification fix * const * update max magnification
1 parent b573060 commit 879a09f

11 files changed

+495
-12
lines changed

source/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ add_library(${PROJECT_NAME}
7575
pipelines/custom/TexturedPlane.h
7676
pipelines/custom/GraphicsPipelineStates.h
7777
pipelines/Particle.h
78+
pipelines/custom/MagnifyWhirlMosaicPipeline.cpp
79+
pipelines/custom/MagnifyWhirlMosaicPipeline.h
7880
)
7981

8082
# Noise

source/VulkanEngine.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ void VulkanEngine::render()
5555
createNewFrame();
5656
}
5757

58-
std::shared_ptr<Texture> VulkanEngine::loadTexture(const char* path)
58+
std::shared_ptr<Texture> VulkanEngine::loadTexture(const char* path, const bool repeat)
5959
{
6060
auto texture = std::make_shared<Texture>(physicalDevice, logicalDevice);
61-
texture->init(commandPool, path, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
61+
texture->init(commandPool, path, repeat ? VK_SAMPLER_ADDRESS_MODE_REPEAT : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
6262
textures.push_back(texture);
6363

6464
return texture;
@@ -192,6 +192,9 @@ void VulkanEngine::initVulkan()
192192
texturedPlanePipeline = std::make_unique<TexturedPlane>(physicalDevice, logicalDevice, renderPass, descriptorPool,
193193
objectDescriptorSetLayout);
194194

195+
magnifyWhirlMosaicPipeline = std::make_unique<MagnifyWhirlMosaicPipeline>(physicalDevice, logicalDevice, renderPass,
196+
descriptorPool, objectDescriptorSetLayout);
197+
195198
guiPipeline = std::make_unique<GuiPipeline>(physicalDevice, logicalDevice, renderPass,
196199
vulkanEngineOptions.MAX_IMGUI_TEXTURES);
197200

@@ -496,6 +499,12 @@ void VulkanEngine::renderGraphicsPipelines(const VkCommandBuffer& commandBuffer,
496499
renderObjectsToRender.at(PipelineType::texturedPlane));
497500
}
498501

502+
if (renderObjectsToRender.contains(PipelineType::magnifyWhirlMosaic))
503+
{
504+
magnifyWhirlMosaicPipeline->render(commandBuffer, currentFrame, viewPosition, viewMatrix, extent,
505+
renderObjectsToRender.at(PipelineType::magnifyWhirlMosaic));
506+
}
507+
499508
if (vulkanEngineOptions.DO_DOTS)
500509
{
501510
dotsPipeline->render(commandBuffer, currentFrame, extent);

source/VulkanEngine.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "pipelines/custom/EllipticalDots.h"
2929
#include "pipelines/custom/NoisyEllipticalDots.h"
3030
#include "pipelines/custom/TexturedPlane.h"
31+
#include "pipelines/custom/MagnifyWhirlMosaicPipeline.h"
3132

3233
#include "objects/Texture.h"
3334
#include "objects/Model.h"
@@ -39,12 +40,13 @@
3940
constexpr int MAX_FRAMES_IN_FLIGHT = 2;
4041

4142
enum class PipelineType {
42-
object,
43-
ellipticalDots,
44-
noisyEllipticalDots,
4543
bumpyCurtain,
4644
curtain,
4745
cubeMap,
46+
ellipticalDots,
47+
magnifyWhirlMosaic,
48+
noisyEllipticalDots,
49+
object,
4850
texturedPlane
4951
};
5052

@@ -57,7 +59,7 @@ class VulkanEngine {
5759

5860
void render();
5961

60-
std::shared_ptr<Texture> loadTexture(const char* path);
62+
std::shared_ptr<Texture> loadTexture(const char* path, bool repeat = true);
6163
std::shared_ptr<Model> loadModel(const char* path, glm::vec3 rotation = { 0, 0, 0 });
6264
[[nodiscard]] std::shared_ptr<RenderObject> loadRenderObject(const std::shared_ptr<Texture>& texture,
6365
const std::shared_ptr<Texture>& specularMap,
@@ -97,6 +99,7 @@ class VulkanEngine {
9799
std::unique_ptr<BumpyCurtain> bumpyCurtainPipeline;
98100
std::unique_ptr<CubeMapPipeline> cubeMapPipeline;
99101
std::unique_ptr<TexturedPlane> texturedPlanePipeline;
102+
std::unique_ptr<MagnifyWhirlMosaicPipeline> magnifyWhirlMosaicPipeline;
100103

101104
std::unique_ptr<ImGuiInstance> imGuiInstance;
102105

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
#include "MagnifyWhirlMosaicPipeline.h"
2+
#include "GraphicsPipelineStates.h"
3+
#include "Uniforms.h"
4+
#include "../RenderPass.h"
5+
#include "../../components/Camera.h"
6+
#include "../../components/LogicalDevice.h"
7+
#include "../../components/PhysicalDevice.h"
8+
#include "../../objects/RenderObject.h"
9+
#include "../../objects/UniformBuffer.h"
10+
#include <imgui.h>
11+
#include <stdexcept>
12+
13+
constexpr int MAX_FRAMES_IN_FLIGHT = 2; // TODO: link this better
14+
15+
MagnifyWhirlMosaicPipeline::MagnifyWhirlMosaicPipeline(const std::shared_ptr<PhysicalDevice>& physicalDevice,
16+
const std::shared_ptr<LogicalDevice>& logicalDevice,
17+
const std::shared_ptr<RenderPass>& renderPass,
18+
VkDescriptorPool descriptorPool,
19+
VkDescriptorSetLayout objectDescriptorSetLayout)
20+
: GraphicsPipeline(physicalDevice, logicalDevice), descriptorPool(descriptorPool),
21+
objectDescriptorSetLayout(objectDescriptorSetLayout)
22+
{
23+
createUniforms();
24+
25+
createGlobalDescriptorSetLayout();
26+
27+
createDescriptorSets();
28+
29+
createPipeline(renderPass->getRenderPass());
30+
}
31+
32+
MagnifyWhirlMosaicPipeline::~MagnifyWhirlMosaicPipeline()
33+
{
34+
vkDestroyDescriptorSetLayout(logicalDevice->getDevice(), globalDescriptorSetLayout, nullptr);
35+
}
36+
37+
void MagnifyWhirlMosaicPipeline::render(const VkCommandBuffer& commandBuffer, const uint32_t currentFrame,
38+
const glm::vec3 viewPosition, const glm::mat4& viewMatrix,
39+
const VkExtent2D swapChainExtent,
40+
const std::vector<std::shared_ptr<RenderObject>>& objects)
41+
{
42+
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
43+
44+
const VkViewport viewport {
45+
.x = 0.0f,
46+
.y = 0.0f,
47+
.width = static_cast<float>(swapChainExtent.width),
48+
.height = static_cast<float>(swapChainExtent.height),
49+
.minDepth = 0.0f,
50+
.maxDepth = 1.0f
51+
};
52+
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
53+
54+
const VkRect2D scissor {
55+
.offset = {0, 0},
56+
.extent = swapChainExtent
57+
};
58+
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
59+
60+
const CameraUniform cameraUBO {
61+
.position = viewPosition
62+
};
63+
cameraUniform->update(currentFrame, &cameraUBO, sizeof(CameraUniform));
64+
65+
ImGui::Begin("Magnify Whirl Mosaic");
66+
67+
ImGui::SliderFloat("Lens S Center", &magnifyWhirlMosaicUBO.lensS, 0.0f, 1.0f);
68+
ImGui::SliderFloat("Lens T Center", &magnifyWhirlMosaicUBO.lensT, 0.0f, 1.0f);
69+
ImGui::SliderFloat("Lens Radius", &magnifyWhirlMosaicUBO.lensRadius, 0.01f, 0.75f);
70+
71+
ImGui::Separator();
72+
73+
ImGui::SliderFloat("Magnification", &magnifyWhirlMosaicUBO.magnification, 0.1f, 7.5f);
74+
ImGui::SliderFloat("Whirl", &magnifyWhirlMosaicUBO.whirl, -30.0f, 30.0f);
75+
ImGui::SliderFloat("Mosaic", &magnifyWhirlMosaicUBO.mosaic, 0.001f, 0.1f);
76+
77+
ImGui::End();
78+
magnifyWhirlMosaicUniform->update(currentFrame, &magnifyWhirlMosaicUBO, sizeof(MagnifyWhirlMosaicUniform));
79+
80+
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1,
81+
&descriptorSets[currentFrame], 0, nullptr);
82+
83+
glm::mat4 projectionMatrix = glm::perspective(
84+
glm::radians(45.0f),
85+
static_cast<float>(swapChainExtent.width) / static_cast<float>(swapChainExtent.height),
86+
0.1f,
87+
1000.0f
88+
);
89+
90+
projectionMatrix[1][1] *= -1;
91+
92+
for (const auto& object : objects)
93+
{
94+
object->updateUniformBuffer(currentFrame, viewMatrix, projectionMatrix);
95+
96+
object->draw(commandBuffer, pipelineLayout, currentFrame);
97+
}
98+
}
99+
100+
void MagnifyWhirlMosaicPipeline::loadGraphicsShaders()
101+
{
102+
createShader("assets/shaders/StandardObject.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
103+
createShader("assets/shaders/MagnifyWhirlMosaic.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
104+
}
105+
106+
void MagnifyWhirlMosaicPipeline::loadGraphicsDescriptorSetLayouts()
107+
{
108+
loadDescriptorSetLayout(globalDescriptorSetLayout);
109+
loadDescriptorSetLayout(objectDescriptorSetLayout);
110+
}
111+
112+
void MagnifyWhirlMosaicPipeline::defineStates()
113+
{
114+
defineColorBlendState(GraphicsPipelineStates::colorBlendState);
115+
defineDepthStencilState(GraphicsPipelineStates::depthStencilState);
116+
defineDynamicState(GraphicsPipelineStates::dynamicState);
117+
defineInputAssemblyState(GraphicsPipelineStates::inputAssemblyStateTriangleList);
118+
defineMultisampleState(GraphicsPipelineStates::getMultsampleState(physicalDevice));
119+
defineRasterizationState(GraphicsPipelineStates::rasterizationStateNoCull);
120+
defineVertexInputState(GraphicsPipelineStates::vertexInputStateVertex);
121+
defineViewportState(GraphicsPipelineStates::viewportState);
122+
}
123+
124+
void MagnifyWhirlMosaicPipeline::createGlobalDescriptorSetLayout()
125+
{
126+
constexpr VkDescriptorSetLayoutBinding cameraLayout {
127+
.binding = 3,
128+
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
129+
.descriptorCount = 1,
130+
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
131+
};
132+
133+
constexpr VkDescriptorSetLayoutBinding magnifyWhirlMosaicLayout {
134+
.binding = 4,
135+
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
136+
.descriptorCount = 1,
137+
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
138+
};
139+
140+
constexpr std::array<VkDescriptorSetLayoutBinding, 2> globalBindings {
141+
cameraLayout,
142+
magnifyWhirlMosaicLayout
143+
};
144+
145+
const VkDescriptorSetLayoutCreateInfo globalLayoutCreateInfo {
146+
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
147+
.bindingCount = static_cast<uint32_t>(globalBindings.size()),
148+
.pBindings = globalBindings.data()
149+
};
150+
151+
if (vkCreateDescriptorSetLayout(logicalDevice->getDevice(), &globalLayoutCreateInfo, nullptr, &globalDescriptorSetLayout) != VK_SUCCESS)
152+
{
153+
throw std::runtime_error("failed to create global descriptor set layout!");
154+
}
155+
}
156+
157+
void MagnifyWhirlMosaicPipeline::createDescriptorSets()
158+
{
159+
const std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, globalDescriptorSetLayout);
160+
const VkDescriptorSetAllocateInfo allocateInfo {
161+
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
162+
.descriptorPool = descriptorPool,
163+
.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT),
164+
.pSetLayouts = layouts.data()
165+
};
166+
167+
descriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
168+
if (vkAllocateDescriptorSets(logicalDevice->getDevice(), &allocateInfo, descriptorSets.data()) != VK_SUCCESS)
169+
{
170+
throw std::runtime_error("failed to allocate descriptor sets!");
171+
}
172+
173+
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
174+
{
175+
std::array<VkWriteDescriptorSet, 2> descriptorWrites{{
176+
cameraUniform->getDescriptorSet(3, descriptorSets[i], i),
177+
magnifyWhirlMosaicUniform->getDescriptorSet(4, descriptorSets[i], i)
178+
}};
179+
180+
vkUpdateDescriptorSets(logicalDevice->getDevice(), descriptorWrites.size(),
181+
descriptorWrites.data(), 0, nullptr);
182+
}
183+
}
184+
185+
void MagnifyWhirlMosaicPipeline::createUniforms()
186+
{
187+
cameraUniform = std::make_unique<UniformBuffer>(logicalDevice, physicalDevice, MAX_FRAMES_IN_FLIGHT,
188+
sizeof(CameraUniform));
189+
190+
magnifyWhirlMosaicUniform = std::make_unique<UniformBuffer>(logicalDevice, physicalDevice, MAX_FRAMES_IN_FLIGHT,
191+
sizeof(MagnifyWhirlMosaicUniform));
192+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#ifndef MAGNIFYWHIRLMOSAIC_H
2+
#define MAGNIFYWHIRLMOSAIC_H
3+
4+
#include "Uniforms.h"
5+
#include "../GraphicsPipeline.h"
6+
#include <vulkan/vulkan.h>
7+
#include <glm/glm.hpp>
8+
#include <vector>
9+
#include <memory>
10+
11+
class LogicalDevice;
12+
class PhysicalDevice;
13+
class RenderPass;
14+
class RenderObject;
15+
class UniformBuffer;
16+
17+
class MagnifyWhirlMosaicPipeline final : public GraphicsPipeline {
18+
public:
19+
MagnifyWhirlMosaicPipeline(const std::shared_ptr<PhysicalDevice>& physicalDevice,
20+
const std::shared_ptr<LogicalDevice>& logicalDevice,
21+
const std::shared_ptr<RenderPass>& renderPass,
22+
VkDescriptorPool descriptorPool,
23+
VkDescriptorSetLayout objectDescriptorSetLayout);
24+
25+
~MagnifyWhirlMosaicPipeline() override;
26+
27+
void render(const VkCommandBuffer& commandBuffer, uint32_t currentFrame, glm::vec3 viewPosition,
28+
const glm::mat4& viewMatrix, VkExtent2D swapChainExtent,
29+
const std::vector<std::shared_ptr<RenderObject>>& objects);
30+
31+
private:
32+
MagnifyWhirlMosaicUniform magnifyWhirlMosaicUBO {
33+
.lensS = 0.5f,
34+
.lensT = 0.5f,
35+
.lensRadius = 0.25f,
36+
.magnification = 1.0f,
37+
.whirl = 0.0f,
38+
.mosaic = 0.001f
39+
};
40+
41+
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
42+
std::vector<VkDescriptorSet> descriptorSets;
43+
44+
VkDescriptorSetLayout globalDescriptorSetLayout = VK_NULL_HANDLE;
45+
VkDescriptorSetLayout objectDescriptorSetLayout = VK_NULL_HANDLE;
46+
47+
std::unique_ptr<UniformBuffer> cameraUniform;
48+
std::unique_ptr<UniformBuffer> magnifyWhirlMosaicUniform;
49+
50+
void loadGraphicsShaders() override;
51+
52+
void loadGraphicsDescriptorSetLayouts() override;
53+
54+
void defineStates() override;
55+
56+
void createGlobalDescriptorSetLayout();
57+
58+
void createDescriptorSets();
59+
60+
void createUniforms();
61+
};
62+
63+
64+
65+
#endif //MAGNIFYWHIRLMOSAIC_H

source/pipelines/custom/Uniforms.h

+9
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,13 @@ struct CubeMapUniform {
3737
float whiteMix;
3838
};
3939

40+
struct MagnifyWhirlMosaicUniform {
41+
float lensS;
42+
float lensT;
43+
float lensRadius;
44+
float magnification;
45+
float whirl;
46+
float mosaic;
47+
};
48+
4049
#endif //VULKANPROJECT_UNIFORMS_H

0 commit comments

Comments
 (0)