Archived
1
Fork 0

Add visual selection feedback

This commit is contained in:
Joshua Goins 2018-12-25 10:57:12 -05:00
parent 462462331a
commit 2b65968452
13 changed files with 432 additions and 10 deletions

View file

@ -57,7 +57,8 @@ set(ENGINE_SRC
src/worldmanager.cpp
src/assetmanager.cpp
src/entityparser.cpp
src/smaapass.cpp)
src/smaapass.cpp
src/debugpass.cpp)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(ENGINE_SRC
@ -112,7 +113,9 @@ add_shaders(Graph
shaders/edge.vert
shaders/edge.frag
shaders/blend.vert
shaders/blend.frag)
shaders/blend.frag
shaders/sobel.vert
shaders/sobel.frag)
add_data(Graph
data/suzanne.obj

32
include/debugpass.h Normal file
View file

@ -0,0 +1,32 @@
#pragma once
#include <vulkan/vulkan.h>
#include <glm/glm.hpp>
class Renderer;
struct RenderTarget;
struct RenderCollection;
struct RenderExtraInfo;
class DebugPass {
public:
DebugPass(Renderer& renderer);
~DebugPass();
void render(VkCommandBuffer commandBuffer, RenderCollection& collection, RenderExtraInfo* extraInfo, RenderTarget* target);
VkRenderPass getRenderPass() const {
return renderPass_;
}
private:
void createRenderPass();
void createPipeline();
VkRenderPass renderPass_ = nullptr;
VkPipeline pipeline_ = nullptr;
VkPipelineLayout pipelineLayout_ = nullptr;
Renderer& renderer_;
};

View file

@ -7,12 +7,16 @@ struct MeshComponent;
struct LightComponent;
struct CameraComponent;
using EntityID = uint64_t;
struct RenderLight {
TransformComponent* transform = nullptr;
LightComponent* light = nullptr;
};
struct RenderMesh {
EntityID entity;
TransformComponent* transform = nullptr;
MeshComponent* mesh = nullptr;
};
@ -25,6 +29,6 @@ struct RenderCamera {
struct RenderCollection {
std::vector<RenderLight> lights;
std::vector<RenderMesh> meshes;
RenderCamera camera;
};

View file

@ -9,6 +9,7 @@
#include "skypass.h"
#include "shadowpass.h"
#include "smaapass.h"
#include "debugpass.h"
constexpr int numFrameResources = 2;
@ -36,6 +37,13 @@ struct RenderTarget {
VkFramebuffer* offscreenFramebuffers = nullptr;
// sobel
VkImage* sobelImages = nullptr;
VkDeviceMemory* sobelMemorys = nullptr;
VkImageView* sobelImageViews = nullptr;
VkFramebuffer* sobelFramebuffers = nullptr;
// near field
VkImage* nearFieldImages = nullptr;
VkDeviceMemory* nearFieldMemory = nullptr;
@ -90,6 +98,13 @@ struct GraphicsConfig {
#endif
};
using EntityID = uint64_t;
struct RenderExtraInfo {
EntityID* selectedEntities = nullptr;
size_t numSelectedEntities = 0;
};
struct World;
class MeshAsset;
class Camera;
@ -100,7 +115,7 @@ public:
Renderer(GraphicsConfig config);
~Renderer();
void render(World& world, RenderTarget* target);
void render(World& world, RenderTarget* target, RenderExtraInfo* extraInfo = nullptr);
RenderTarget* createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTarget* oldTarget = nullptr);
void destroyRenderTarget(RenderTarget* target);
@ -219,4 +234,5 @@ private:
SkyPass* skyPass_ = nullptr;
ShadowPass* shadowPass_ = nullptr;
SMAAPass* smaaPass_ = nullptr;
DebugPass* debugPass_ = nullptr;
};

View file

@ -22,6 +22,11 @@ layout(binding = 1) uniform sampler2D depthSampler;
layout(binding = 2) uniform sampler2D nearFieldSampler;
layout(binding = 3) uniform sampler2D farFieldSampler;
layout(binding = 4) uniform sampler2D blendSampler;
layout(binding = 5) uniform sampler2D sobelSampler;
layout(push_constant) uniform PushConstants {
vec4 viewport;
} pushConstants;
void main() {
vec3 sceneColor = vec3(0);
@ -43,5 +48,27 @@ void main() {
//float coc2 = texture(nearFieldSampler, inUV).a;
//vec3 finalColor = mix(farColorBlurred, nearColor, clamp(clamp(-coc2 - 1.0, 0.0, 1.0) + texture(nearFieldSampler, inUV).a * 8.0, 0.0, 1.0));
float thickness = 3.0;
float thicknessX = thickness * pushConstants.viewport.x * (pushConstants.viewport.z / 1920.0);
float thicknessY = thickness * pushConstants.viewport.y * (pushConstants.viewport.w / 1080.0);
vec4 top = texture(sobelSampler, vec2(inUV.x, inUV.y + thicknessY));
vec4 bottom = texture(sobelSampler, vec2(inUV.x, inUV.y - thicknessY));
vec4 left = texture(sobelSampler, vec2(inUV.x - thicknessX, inUV.y));
vec4 right = texture(sobelSampler, vec2(inUV.x + thicknessX, inUV.y));
vec4 topLeft = texture(sobelSampler, vec2(inUV.x - thicknessX, inUV.y + thicknessY));
vec4 topRight = texture(sobelSampler, vec2(inUV.x + thicknessX, inUV.y + thicknessY));
vec4 bottomLeft = texture(sobelSampler, vec2(inUV.x - thicknessX, inUV.y - thicknessY));
vec4 bottomRight = texture(sobelSampler, vec2(inUV.x + thicknessX, inUV.y - thicknessY));
vec4 sx = -topLeft - 2 * left - bottomLeft + topRight + 2 * right + bottomRight;
vec4 sy = -topLeft - 2 * top - topRight + bottomLeft + 2 * bottom + bottomRight;
vec4 sobel = sqrt(sx * sx + sy * sy);
sobel = clamp(sobel / 5.0, 0.0, 1.0);
vec4 outlineColor = vec4(0.1, 0.5, 0.9, 1.0);
outColor = vec4(farColorBlurred, 1.0);
outColor = outlineColor*sobel + outColor*(1.0 - sobel);
outColor += outlineColor * texture(sobelSampler, inUV) * 0.3;
}

7
shaders/sobel.frag Executable file
View file

@ -0,0 +1,7 @@
#version 450 core
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(1.0);
}

12
shaders/sobel.vert Executable file
View file

@ -0,0 +1,12 @@
#version 450 core
layout(location = 0) in vec3 inPosition;
layout(push_constant) uniform PushConsts {
mat4 mvp;
} pushConstants;
void main() {
gl_Position = pushConstants.mvp * vec4(inPosition, 1.0);
}

197
src/debugpass.cpp Normal file
View file

@ -0,0 +1,197 @@
#include "debugpass.h"
#include <glm/gtc/matrix_transform.hpp>
#include "rendercollection.h"
#include "renderer.h"
#include "ecs.h"
#include "mesh.h"
DebugPass::DebugPass(Renderer& renderer) : renderer_(renderer) {
createRenderPass();
createPipeline();
}
DebugPass::~DebugPass() {
}
void DebugPass::render(VkCommandBuffer commandBuffer, RenderCollection& collection, RenderExtraInfo* extraInfo, RenderTarget* target) {
VkClearValue clearValue = {};
clearValue.color = {0.0f, 0.0f, 0.0f, 0.0f};
VkRenderPassBeginInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = renderPass_;
renderPassInfo.framebuffer = target->sobelFramebuffers[target->currentResource];
renderPassInfo.renderArea.extent = target->extent;
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearValue;
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
for(auto mesh : collection.meshes) {
bool shouldRender = false;
for(int i = 0; i < extraInfo->numSelectedEntities; i++) {
if(extraInfo->selectedEntities[i] == mesh.entity)
shouldRender = true;
}
if(shouldRender) {
glm::mat4 mvp;
mvp = glm::perspective(glm::radians(collection.camera.camera->fov), (float)target->extent.width / target->extent.height, collection.camera.camera->near, collection.camera.camera->far);
mvp *= glm::lookAt(collection.camera.transform->position, collection.camera.camera->target, glm::vec3(0, -1, 0));
mvp = glm::translate(mvp, mesh.transform->position);
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &mvp);
const VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh.mesh->mesh->vertexBuffer, offsets);
vkCmdBindIndexBuffer(commandBuffer, mesh.mesh->mesh->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(commandBuffer, mesh.mesh->mesh->indices.size(), 1, 0, 0, 0);
}
}
vkCmdEndRenderPass(commandBuffer);
}
void DebugPass::createRenderPass() {
VkAttachmentDescription colorAttachment = {};
colorAttachment.format = VK_FORMAT_R16G16B16A16_SFLOAT;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkAttachmentReference colorAttachmentRef = {};
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
VkSubpassDependency dependency = {};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &colorAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency;
vkCreateRenderPass(renderer_.getDevice(), &renderPassInfo, nullptr, &renderPass_);
}
void DebugPass::createPipeline() {
VkShaderModule vertShaderModule = renderer_.createShader("shaders/sobel.vert.spv");
VkShaderModule fragShaderModule = renderer_.createShader("shaders/sobel.frag.spv");
VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
const std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages = {vertShaderStageInfo, fragShaderStageInfo};
VkVertexInputBindingDescription vertexBindingDescription = {};
vertexBindingDescription.stride = sizeof(Vertex);
VkVertexInputAttributeDescription positionAttributeDescription = {};
positionAttributeDescription.format = VK_FORMAT_R32G32B32_SFLOAT;
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDescription;
vertexInputInfo.vertexAttributeDescriptionCount = 1;
vertexInputInfo.pVertexAttributeDescriptions = &positionAttributeDescription;
VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
VkPipelineViewportStateCreateInfo viewportState = {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
VkPipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.cullMode = VK_CULL_MODE_NONE;
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer.lineWidth = 1.0f;
VkPipelineMultisampleStateCreateInfo multisampling = {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
VkPipelineColorBlendStateCreateInfo colorBlending = {};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
const std::array<VkDynamicState, 2> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState = {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = dynamicStates.size();
dynamicState.pDynamicStates = dynamicStates.data();
VkPushConstantRange pushConstant = {};
pushConstant.size = sizeof(glm::mat4);
pushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConstant;
vkCreatePipelineLayout(renderer_.getDevice(), &pipelineLayoutInfo, nullptr, &pipelineLayout_);
VkGraphicsPipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = shaderStages.size();
pipelineInfo.pStages = shaderStages.data();
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = pipelineLayout_;
pipelineInfo.renderPass = renderPass_;
vkCreateGraphicsPipelines(renderer_.getDevice(), nullptr, 1, &pipelineInfo, nullptr, &pipeline_);
vkDestroyShaderModule(renderer_.getDevice(), fragShaderModule, nullptr);
vkDestroyShaderModule(renderer_.getDevice(), vertShaderModule, nullptr);
}

View file

@ -22,6 +22,15 @@ PostPass::~PostPass() {
void PostPass::render(VkCommandBuffer commandBuffer, RenderTarget* target) {
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &target->postSets[target->currentResource], 0, nullptr);
glm::vec4 viewport;
viewport.x = 1.0 / target->extent.width;
viewport.y = 1.0 / target->extent.height;
viewport.z = target->extent.width;
viewport.w = target->extent.height;
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(glm::vec4), &viewport);
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
}
@ -69,6 +78,11 @@ void PostPass::createDescriptorSet(RenderTarget* target) {
blendImageInfo.imageView = target->blendImageViews[i];
blendImageInfo.sampler = offscreenSampler_;
VkDescriptorImageInfo sobelImageInfo = {};
sobelImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
sobelImageInfo.imageView = target->sobelImageViews[i];
sobelImageInfo.sampler = offscreenSampler_;
VkWriteDescriptorSet sceneDescriptorWrite = {};
sceneDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
sceneDescriptorWrite.descriptorCount = 1;
@ -108,12 +122,21 @@ void PostPass::createDescriptorSet(RenderTarget* target) {
blendDescriptorWrite.dstSet = target->postSets[i];
blendDescriptorWrite.pImageInfo = &blendImageInfo;
const std::array<VkWriteDescriptorSet, 5> descriptorWrites = {
VkWriteDescriptorSet sobelDescriptorWrite = {};
sobelDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
sobelDescriptorWrite.descriptorCount = 1;
sobelDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
sobelDescriptorWrite.dstBinding = 5;
sobelDescriptorWrite.dstSet = target->postSets[i];
sobelDescriptorWrite.pImageInfo = &sobelImageInfo;
const std::array<VkWriteDescriptorSet, 6> descriptorWrites = {
sceneDescriptorWrite,
depthDescriptorWrite,
nearFieldDescriptorWrite,
farFieldDescriptorWrite,
blendDescriptorWrite
blendDescriptorWrite,
sobelDescriptorWrite
};
vkUpdateDescriptorSets(renderer_.getDevice(), descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
@ -150,12 +173,19 @@ void PostPass::createDescriptorSetLayout() {
blendSamplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
blendSamplerBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
const std::array<VkDescriptorSetLayoutBinding, 5> bindings = {
VkDescriptorSetLayoutBinding sobelSamplerBinding = {};
sobelSamplerBinding.binding = 5;
sobelSamplerBinding.descriptorCount = 1;
sobelSamplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
sobelSamplerBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
const std::array<VkDescriptorSetLayoutBinding, 6> bindings = {
offscreenSamplerBinding,
depthSamplerBinding,
nearFieldSamplerBinding,
farFieldSamplerBinding,
blendSamplerBinding
blendSamplerBinding,
sobelSamplerBinding
};
VkDescriptorSetLayoutCreateInfo createInfo = {};
@ -226,10 +256,16 @@ void PostPass::createPipeline() {
dynamicState.dynamicStateCount = dynamicStates.size();
dynamicState.pDynamicStates = dynamicStates.data();
VkPushConstantRange pushConstant = {};
pushConstant.size = sizeof(glm::vec4);
pushConstant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &setLayout_;
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConstant;
vkCreatePipelineLayout(renderer_.getDevice(), &pipelineLayoutInfo, nullptr, &pipelineLayout_);

View file

@ -39,11 +39,13 @@ Renderer::Renderer(GraphicsConfig config) : config_(config) {
#endif
skyPass_ = new SkyPass(*this);
smaaPass_ = new SMAAPass(*this);
debugPass_ = new DebugPass(*this);
}
Renderer::~Renderer() {
vkDeviceWaitIdle(device_);
delete debugPass_;
delete smaaPass_;
delete skyPass_;
#ifdef DEBUG
@ -72,7 +74,7 @@ Renderer::~Renderer() {
vkDestroyInstance(instance_, nullptr);
}
void Renderer::render(World& world, RenderTarget* target) {
void Renderer::render(World& world, RenderTarget* target, RenderExtraInfo* extraInfo) {
RenderCollection collection;
// generate collection
@ -80,6 +82,7 @@ void Renderer::render(World& world, RenderTarget* target) {
auto meshes = ECS::getWorldComponents<MeshComponent>(&world);
for(auto [id, mesh] : meshes) {
RenderMesh renderMesh;
renderMesh.entity = id;
renderMesh.mesh = mesh;
renderMesh.transform = ECS::getComponent<TransformComponent>(id);
@ -149,6 +152,9 @@ void Renderer::render(World& world, RenderTarget* target) {
vkCmdEndRenderPass(commandBuffer);
if(extraInfo)
debugPass_->render(commandBuffer, collection, extraInfo, target);
dofPass_->render(commandBuffer, *collection.camera.camera, target);
// reset after dof pass
@ -308,6 +314,13 @@ RenderTarget* Renderer::createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTa
target->offscreenFramebuffers = new VkFramebuffer[numFrameResources];
// sobel
target->sobelImages = new VkImage[numFrameResources];
target->sobelMemorys = new VkDeviceMemory[numFrameResources];
target->sobelImageViews = new VkImageView[numFrameResources];
target->sobelFramebuffers = new VkFramebuffer[numFrameResources];
// dof
target->nearFieldImages = new VkImage[numFrameResources];
target->nearFieldMemory = new VkDeviceMemory[numFrameResources];
@ -446,6 +459,63 @@ RenderTarget* Renderer::createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTa
vkCreateFramebuffer(device_, &framebufferInfo, nullptr, &target->offscreenFramebuffers[i]);
}
// sobel image
{
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;
imageCreateInfo.extent.width = target->extent.width;
imageCreateInfo.extent.height = target->extent.height;
imageCreateInfo.extent.depth = 1;
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
vkCreateImage(device_, &imageCreateInfo, nullptr, &target->sobelImages[i]);
VkMemoryRequirements memoryRequirements = {};
vkGetImageMemoryRequirements(device_, target->sobelImages[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->sobelMemorys[i]);
vkBindImageMemory(device_, target->sobelImages[i], target->sobelMemorys[i], 0);
}
// sobel image view
{
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = target->sobelImages[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.layerCount = 1;
vkCreateImageView(device_, &createInfo, nullptr, &target->sobelImageViews[i]);
}
// sobel framebuffer
{
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = debugPass_->getRenderPass();
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = &target->sobelImageViews[i];
framebufferInfo.width = target->extent.width;
framebufferInfo.height = target->extent.height;
framebufferInfo.layers = 1;
vkCreateFramebuffer(device_, &framebufferInfo, nullptr, &target->sobelFramebuffers[i]);
}
// near field color
{
VkImageCreateInfo imageCreateInfo = {};

View file

@ -2,6 +2,10 @@
class Renderer;
using EntityID = uint64_t;
struct Context {
Renderer* renderer;
std::vector<EntityID> selectedEntities;
};

View file

@ -50,7 +50,11 @@ void RendererWindow::render() {
if(target->extent.width != width || target->extent.height != height)
target = context.renderer->createSurfaceRenderTarget(surface, target);
context.renderer->render(*worldManager.getCurrentWorld(), target);
RenderExtraInfo extraInfo;
extraInfo.selectedEntities = context.selectedEntities.data();
extraInfo.numSelectedEntities = context.selectedEntities.size();
context.renderer->render(*worldManager.getCurrentWorld(), target, &extraInfo);
vulkanInstance()->presentQueued(this);
requestUpdate();

View file

@ -15,6 +15,16 @@ Hierarchy::Hierarchy(Context& context, QWidget* parent) : QWidget(parent), conte
listView = new QListView();
layout->addWidget(listView);
connect(listView, &QListView::clicked, [&context](QModelIndex index) {
context.selectedEntities.clear();
if(index.isValid()) {
const auto entity = ECS::getWorldEntities(worldManager.getCurrentWorld())[index.row()];
context.selectedEntities.push_back(entity);
}
});
listModel = new QStringListModel();
listView->setModel(listModel);