diff --git a/pbr/pbr.cpp b/pbr/pbr.cpp new file mode 100644 index 00000000..cd7a95dd --- /dev/null +++ b/pbr/pbr.cpp @@ -0,0 +1,481 @@ +/* +* Vulkan Example - Physical based rendering (incl. IBL) +* +* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de +* +* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) +*/ + +#include +#include +#include +#include +#include + +#define GLM_FORCE_RADIANS +#define GLM_FORCE_DEPTH_ZERO_TO_ONE +#include +#include + +#include + +#include +#include "vulkanexamplebase.h" +#include "VulkanBuffer.hpp" +#include "VulkanTexture.hpp" +#include "VulkanModel.hpp" + +#define VERTEX_BUFFER_BIND_ID 0 +#define ENABLE_VALIDATION false +#define GRID_DIM 7 +#define OBJ_DIM 0.05f + +struct Material { + float roughness; + float metallic; + float ao; + float rim = 0.15f; +}; + +class VulkanExample : public VulkanExampleBase +{ +public: + bool displaySkybox = true; + + vks::TextureCubeMap envmap; + vks::TextureCubeMap irradiancemap; + + // Vertex layout for the models + vks::VertexLayout vertexLayout = vks::VertexLayout({ + vks::VERTEX_COMPONENT_POSITION, + vks::VERTEX_COMPONENT_NORMAL, + vks::VERTEX_COMPONENT_UV, + }); + + struct Meshes { + vks::Model skybox; + std::vector objects; + uint32_t objectIndex = 0; + } models; + + struct { + vks::Buffer object; + vks::Buffer skybox; + } uniformBuffers; + + struct UBOVS { + glm::mat4 projection; + glm::mat4 model; + glm::mat4 view; + glm::vec3 camPos; + } uboVS; + + struct { + VkPipeline skybox; + VkPipeline pbr; + } pipelines; + + struct { + VkDescriptorSet object; + VkDescriptorSet skybox; + } descriptorSets; + + VkPipelineLayout pipelineLayout; + VkDescriptorSetLayout descriptorSetLayout; + + VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) + { + title = "Vulkan Example - Physical based rendering"; + enableTextOverlay = true; + camera.type = Camera::CameraType::firstperson; + camera.setPosition(glm::vec3(-15.0f, 4.0f, -4.0f)); + camera.setRotation(glm::vec3(-15.0f, -70.0f, 0.0f)); + camera.movementSpeed = 4.0f; + camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); + camera.rotationSpeed = 0.25f; + width = 1920; + height = 1080; + } + + ~VulkanExample() + { + vkDestroyPipeline(device, pipelines.skybox, nullptr); + vkDestroyPipeline(device, pipelines.pbr, nullptr); + + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + + for (auto& model : models.objects) { + model.destroy(); + } + models.skybox.destroy(); + + uniformBuffers.object.destroy(); + uniformBuffers.skybox.destroy(); + envmap.destroy(); + irradiancemap.destroy(); + } + + void reBuildCommandBuffers() + { + if (!checkCommandBuffers()) + { + destroyCommandBuffers(); + createCommandBuffers(); + } + buildCommandBuffers(); + } + + void buildCommandBuffers() + { + VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); + + VkClearValue clearValues[2]; + clearValues[0].color = { { 0.1f, 0.1f, 0.1f, 1.0f } }; + clearValues[1].depthStencil = { 1.0f, 0 }; + + VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); + renderPassBeginInfo.renderPass = renderPass; + renderPassBeginInfo.renderArea.offset.x = 0; + renderPassBeginInfo.renderArea.offset.y = 0; + renderPassBeginInfo.renderArea.extent.width = width; + renderPassBeginInfo.renderArea.extent.height = height; + renderPassBeginInfo.clearValueCount = 2; + renderPassBeginInfo.pClearValues = clearValues; + + for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) + { + // Set target frame buffer + renderPassBeginInfo.framebuffer = frameBuffers[i]; + + VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); + + vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); + vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); + + VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); + vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); + + VkDeviceSize offsets[1] = { 0 }; + + // Skybox + if (displaySkybox) + { + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.skybox, 0, NULL); + vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &models.skybox.vertices.buffer, offsets); + vkCmdBindIndexBuffer(drawCmdBuffers[i], models.skybox.indices.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skybox); + vkCmdDrawIndexed(drawCmdBuffers[i], models.skybox.indexCount, 1, 0, 0, 0); + } + + // Objects + vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.object, 0, NULL); + vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &models.objects[models.objectIndex].vertices.buffer, offsets); + vkCmdBindIndexBuffer(drawCmdBuffers[i], models.objects[models.objectIndex].indices.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.pbr); + + Material mat; + mat.ao = 1.0f; + for (uint32_t y = 0; y < GRID_DIM; y++) { + for (uint32_t x = 0; x < GRID_DIM; x++) { + glm::vec3 pos = glm::vec3(float(x - (GRID_DIM / 2.0f)) * 2.5f, 0.0f, float(y - (GRID_DIM / 2.0f)) * 2.5f); + vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::vec3), &pos); + mat.metallic = (float)x / (float)GRID_DIM; + mat.roughness = glm::clamp((float)y / (float)(GRID_DIM - 1), 0.05f, 1.0f); + vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(glm::vec3), sizeof(Material), &mat); + vkCmdDrawIndexed(drawCmdBuffers[i], models.objects[models.objectIndex].indexCount, 1, 0, 0, 0); + } + } + + vkCmdEndRenderPass(drawCmdBuffers[i]); + + VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); + } + } + + void loadAssets() + { + // Skybox + models.skybox.loadFromFile(getAssetPath() + "models/cube.obj", vertexLayout, 1.0f, vulkanDevice, queue); + // Objects + std::vector filenames = { "sphere.obj", "teapot.dae", "torusknot.obj", "venus.fbx" }; + for (auto file : filenames) { + vks::Model model; + model.loadFromFile(getAssetPath() + "models/" + file, vertexLayout, OBJ_DIM * (file == "venus.fbx" ? 3.0f : 1.0f) , vulkanDevice, queue); + models.objects.push_back(model); + } + envmap.loadFromFile(getAssetPath() + "textures/cube_env_01_bc3.ktx", VK_FORMAT_BC3_UNORM_BLOCK, vulkanDevice, queue); + irradiancemap.loadFromFile(getAssetPath() + "textures/cube_env_01_irradiance_rgba8.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); + } + + void setupDescriptorSetLayout() + { + std::vector setLayoutBindings = { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), + }; + + VkDescriptorSetLayoutCreateInfo descriptorLayout = + vks::initializers::descriptorSetLayoutCreateInfo( + setLayoutBindings.data(), + setLayoutBindings.size()); + + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); + + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = + vks::initializers::pipelineLayoutCreateInfo( + &descriptorSetLayout, + 1); + + std::vector pushConstantRanges = { + vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::vec3), 0), + vks::initializers::pushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(Material), sizeof(glm::vec3)), + }; + + pipelineLayoutCreateInfo.pushConstantRangeCount = 2; + pipelineLayoutCreateInfo.pPushConstantRanges = pushConstantRanges.data(); + + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + } + + void setupDescriptorSets() + { + // Descriptor Pool + std::vector poolSizes = { + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4) + }; + + VkDescriptorPoolCreateInfo descriptorPoolInfo = + vks::initializers::descriptorPoolCreateInfo(poolSizes.size(), poolSizes.data(), 2); + + VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); + + // Descriptor sets + + VkDescriptorSetAllocateInfo allocInfo = + vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); + + // 3D object descriptor set + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.object)); + + std::vector writeDescriptorSets = { + vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.object.descriptor), + vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &envmap.descriptor), + vks::initializers::writeDescriptorSet(descriptorSets.object, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &irradiancemap.descriptor), + }; + vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); + + // Sky box descriptor set + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.skybox)); + + writeDescriptorSets = { + vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.skybox.descriptor), + vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &envmap.descriptor), + vks::initializers::writeDescriptorSet(descriptorSets.skybox, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &irradiancemap.descriptor), + }; + vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); + } + + void preparePipelines() + { + VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = + vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); + + VkPipelineRasterizationStateCreateInfo rasterizationState = + vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE); + + VkPipelineColorBlendAttachmentState blendAttachmentState = + vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); + + VkPipelineColorBlendStateCreateInfo colorBlendState = + vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); + + VkPipelineDepthStencilStateCreateInfo depthStencilState = + vks::initializers::pipelineDepthStencilStateCreateInfo(VK_FALSE, VK_FALSE, VK_COMPARE_OP_LESS_OR_EQUAL); + + VkPipelineViewportStateCreateInfo viewportState = + vks::initializers::pipelineViewportStateCreateInfo(1, 1); + + VkPipelineMultisampleStateCreateInfo multisampleState = + vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT); + + std::vector dynamicStateEnables = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + VkPipelineDynamicStateCreateInfo dynamicState = + vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), dynamicStateEnables.size()); + + VkGraphicsPipelineCreateInfo pipelineCreateInfo = + vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); + + std::array shaderStages; + + pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; + pipelineCreateInfo.pRasterizationState = &rasterizationState; + pipelineCreateInfo.pColorBlendState = &colorBlendState; + pipelineCreateInfo.pMultisampleState = &multisampleState; + pipelineCreateInfo.pViewportState = &viewportState; + pipelineCreateInfo.pDepthStencilState = &depthStencilState; + pipelineCreateInfo.pDynamicState = &dynamicState; + pipelineCreateInfo.stageCount = shaderStages.size(); + pipelineCreateInfo.pStages = shaderStages.data(); + + // Vertex bindings an attributes + // Binding description + std::vector vertexInputBindings = { + vks::initializers::vertexInputBindingDescription(0, vertexLayout.stride(), VK_VERTEX_INPUT_RATE_VERTEX), + }; + + // Attribute descriptions + std::vector vertexInputAttributes = { + vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Position + vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Normal + vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32_SFLOAT, sizeof(float) * 5), // UV + }; + + VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); + vertexInputState.vertexBindingDescriptionCount = static_cast(vertexInputBindings.size()); + vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data(); + vertexInputState.vertexAttributeDescriptionCount = static_cast(vertexInputAttributes.size()); + vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data(); + + pipelineCreateInfo.pVertexInputState = &vertexInputState; + + // Skybox pipeline (background cube) + shaderStages[0] = loadShader(getAssetPath() + "shaders/pbr/skybox.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getAssetPath() + "shaders/pbr/skybox.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.skybox)); + + // PBR pipeline + shaderStages[0] = loadShader(getAssetPath() + "shaders/pbr/pbr.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getAssetPath() + "shaders/pbr/pbr.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + // Enable depth test and write + depthStencilState.depthWriteEnable = VK_TRUE; + depthStencilState.depthTestEnable = VK_TRUE; + // Flip cull mode + rasterizationState.cullMode = VK_CULL_MODE_NONE; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.pbr)); + } + + // Prepare and initialize uniform buffer containing shader uniforms + void prepareUniformBuffers() + { + // Objact vertex shader uniform buffer + VK_CHECK_RESULT(vulkanDevice->createBuffer( + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &uniformBuffers.object, + sizeof(uboVS))); + + // Skybox vertex shader uniform buffer + VK_CHECK_RESULT(vulkanDevice->createBuffer( + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &uniformBuffers.skybox, + sizeof(uboVS))); + + // Map persistent + VK_CHECK_RESULT(uniformBuffers.object.map()); + VK_CHECK_RESULT(uniformBuffers.skybox.map()); + + updateUniformBuffers(); + } + + void updateUniformBuffers() + { + // 3D object + uboVS.projection = camera.matrices.perspective; + uboVS.view = camera.matrices.view; + uboVS.model = glm::rotate(glm::mat4(), glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 0.0f)); + uboVS.camPos = camera.position * -1.0f; + memcpy(uniformBuffers.object.mapped, &uboVS, sizeof(uboVS)); + + // Skybox + uboVS.model = glm::mat4(glm::mat3(camera.matrices.view)); + memcpy(uniformBuffers.skybox.mapped, &uboVS, sizeof(uboVS)); + } + + void draw() + { + VulkanExampleBase::prepareFrame(); + + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; + VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + + VulkanExampleBase::submitFrame(); + } + + void prepare() + { + VulkanExampleBase::prepare(); + loadAssets(); + prepareUniformBuffers(); + setupDescriptorSetLayout(); + preparePipelines(); + setupDescriptorSets(); + buildCommandBuffers(); + prepared = true; + } + + virtual void render() + { + if (!prepared) + return; + draw(); + } + + virtual void viewChanged() + { + updateUniformBuffers(); + } + + void toggleSkyBox() + { + displaySkybox = !displaySkybox; + reBuildCommandBuffers(); + } + + void toggleObject() + { + models.objectIndex++; + if (models.objectIndex >= static_cast(models.objects.size())) + { + models.objectIndex = 0; + } + reBuildCommandBuffers(); + } + + virtual void keyPressed(uint32_t keyCode) + { + switch (keyCode) + { + case KEY_F2: + case GAMEPAD_BUTTON_A: + toggleSkyBox(); + break; + case KEY_SPACE: + case GAMEPAD_BUTTON_X: + toggleObject(); + break; + } + } + + virtual void getOverlayText(VulkanTextOverlay *textOverlay) + { +#if defined(__ANDROID__) + textOverlay->addText("\"Button A\" to toggle skybox", 5.0f, 85.0f, VulkanTextOverlay::alignLeft); + textOverlay->addText("\"Button X\" to toggle object", 5.0f, 100.0f, VulkanTextOverlay::alignLeft); +#else + textOverlay->addText("\"F2\" to toggle skybox", 5.0f, 85.0f, VulkanTextOverlay::alignLeft); + textOverlay->addText("\"space\" to toggle object", 5.0f, 100.0f, VulkanTextOverlay::alignLeft); +#endif + } +}; + +VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/pbr/pbr.vcxproj b/pbr/pbr.vcxproj new file mode 100644 index 00000000..3d97df15 --- /dev/null +++ b/pbr/pbr.vcxproj @@ -0,0 +1,101 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {92B2640A-0CC5-48EA-B34C-520BA13938D1} + Win32Proj + 8.1 + + + + Application + true + v140 + + + Application + false + v140 + + + + + + + + + + + + + true + $(SolutionDir)\bin\ + $(SolutionDir)\bin\intermediate\$(ProjectName)\$(ConfigurationName) + + + true + $(SolutionDir)\bin\ + $(SolutionDir)\bin\intermediate\$(ProjectName)\$(ConfigurationName) + + + + WIN32;_DEBUG;_WINDOWS;VK_USE_PLATFORM_WIN32_KHR;_USE_MATH_DEFINES;NOMINMAX;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + ..\base;..\external\glm;..\external\gli;..\external\assimp;..\external;%(AdditionalIncludeDirectories) + /FS %(AdditionalOptions) + + + true + Windows + ..\libs\vulkan\vulkan-1.lib;..\libs\assimp\assimp.lib;%(AdditionalDependencies) + + + + + WIN32;NDEBUG;_WINDOWS;VK_USE_PLATFORM_WIN32_KHR;_USE_MATH_DEFINES;NOMINMAX;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + ..\base;..\external\glm;..\external\gli;..\external\assimp;..\external;%(AdditionalIncludeDirectories) + + + true + Windows + true + true + ..\libs\vulkan\vulkan-1.lib;..\libs\assimp\assimp.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pbr/pbr.vcxproj.filters b/pbr/pbr.vcxproj.filters new file mode 100644 index 00000000..a3554449 --- /dev/null +++ b/pbr/pbr.vcxproj.filters @@ -0,0 +1,59 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + {3adf072b-32a9-412a-8eb5-5329a601df1a} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + \ No newline at end of file diff --git a/vulkanExamples.sln b/vulkanExamples.sln index e9cc074b..79f9f5a1 100644 --- a/vulkanExamples.sln +++ b/vulkanExamples.sln @@ -137,6 +137,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "specializationconstants", " EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hdr", "hdr\hdr.vcxproj", "{582913B3-9B37-48CA-AEBD-69023DA9F7C8}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pbr", "pbr\pbr.vcxproj", "{92B2640A-0CC5-48EA-B34C-520BA13938D1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -335,6 +337,10 @@ Global {582913B3-9B37-48CA-AEBD-69023DA9F7C8}.Debug|x64.Build.0 = Debug|x64 {582913B3-9B37-48CA-AEBD-69023DA9F7C8}.Release|x64.ActiveCfg = Release|x64 {582913B3-9B37-48CA-AEBD-69023DA9F7C8}.Release|x64.Build.0 = Release|x64 + {92B2640A-0CC5-48EA-B34C-520BA13938D1}.Debug|x64.ActiveCfg = Debug|x64 + {92B2640A-0CC5-48EA-B34C-520BA13938D1}.Debug|x64.Build.0 = Debug|x64 + {92B2640A-0CC5-48EA-B34C-520BA13938D1}.Release|x64.ActiveCfg = Release|x64 + {92B2640A-0CC5-48EA-B34C-520BA13938D1}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE