From 4f9d40f3b238ebd4a13cab277dca2f480a8f8f92 Mon Sep 17 00:00:00 2001 From: Benau Date: Sun, 21 Aug 2022 14:09:56 +0800 Subject: [PATCH] Add GEVulkanSkyBoxRenderer --- data/shaders/ge_shaders/fullscreen_quad.vert | 7 + data/shaders/ge_shaders/skybox.frag | 18 + data/shaders/ge_shaders/utils/spm_layout.h | 1 + lib/graphics_engine/CMakeLists.txt | 1 + .../include/ge_vulkan_driver.hpp | 1 + .../src/ge_vulkan_camera_scene_node.cpp | 3 + .../src/ge_vulkan_camera_scene_node.hpp | 3 +- .../src/ge_vulkan_draw_call.cpp | 3 +- lib/graphics_engine/src/ge_vulkan_driver.cpp | 23 +- .../src/ge_vulkan_scene_manager.cpp | 8 + .../src/ge_vulkan_skybox_renderer.cpp | 385 ++++++++++++++++++ .../src/ge_vulkan_skybox_renderer.hpp | 29 ++ lib/irrlicht/include/IImage.h | 2 + lib/irrlicht/source/Irrlicht/CImage.cpp | 5 + lib/irrlicht/source/Irrlicht/CImage.h | 2 + 15 files changed, 487 insertions(+), 4 deletions(-) create mode 100644 data/shaders/ge_shaders/fullscreen_quad.vert create mode 100644 data/shaders/ge_shaders/skybox.frag create mode 100644 lib/graphics_engine/src/ge_vulkan_skybox_renderer.cpp create mode 100644 lib/graphics_engine/src/ge_vulkan_skybox_renderer.hpp diff --git a/data/shaders/ge_shaders/fullscreen_quad.vert b/data/shaders/ge_shaders/fullscreen_quad.vert new file mode 100644 index 000000000..961eb8981 --- /dev/null +++ b/data/shaders/ge_shaders/fullscreen_quad.vert @@ -0,0 +1,7 @@ +layout (location = 0) out vec2 f_uv; + +void main() +{ + f_uv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); + gl_Position = vec4(f_uv * 2.0 - 1.0, 1.0, 1.0); +} diff --git a/data/shaders/ge_shaders/skybox.frag b/data/shaders/ge_shaders/skybox.frag new file mode 100644 index 000000000..563d975cb --- /dev/null +++ b/data/shaders/ge_shaders/skybox.frag @@ -0,0 +1,18 @@ +layout(push_constant) uniform Constants +{ + mat4 m_inverse_projection_view_matrix; +} u_push_constants; + +layout(location = 0) in vec2 f_uv; +layout(binding = 0) uniform samplerCube f_skybox_texture; + +layout(location = 0) out vec4 o_color; + +void main() +{ + vec2 uv = 2.0f * f_uv - 1.0f; + vec4 front = u_push_constants.m_inverse_projection_view_matrix * vec4(uv, -1.0, 1.0); + vec4 back = u_push_constants.m_inverse_projection_view_matrix * vec4(uv, 1.0, 1.0); + vec3 dir = back.xyz / back.w - front.xyz / front.w; + o_color = texture(f_skybox_texture, dir); +} diff --git a/data/shaders/ge_shaders/utils/spm_layout.h b/data/shaders/ge_shaders/utils/spm_layout.h index fa738a677..8534e50d4 100644 --- a/data/shaders/ge_shaders/utils/spm_layout.h +++ b/data/shaders/ge_shaders/utils/spm_layout.h @@ -5,6 +5,7 @@ layout(std140, set = 1, binding = 0) uniform CameraBuffer mat4 m_inverse_view_matrix; mat4 m_inverse_projection_matrix; mat4 m_projection_view_matrix; + mat4 m_inverse_projection_view_matrix; } u_camera; struct ObjectData diff --git a/lib/graphics_engine/CMakeLists.txt b/lib/graphics_engine/CMakeLists.txt index 101437ea7..cf6b242bd 100644 --- a/lib/graphics_engine/CMakeLists.txt +++ b/lib/graphics_engine/CMakeLists.txt @@ -85,6 +85,7 @@ set(GE_SOURCES src/ge_vulkan_mesh_scene_node.cpp src/ge_vulkan_scene_manager.cpp src/ge_vulkan_shader_manager.cpp + src/ge_vulkan_skybox_renderer.cpp src/ge_vulkan_texture.cpp src/ge_vulkan_texture_descriptor.cpp src/ge_gl_texture.cpp diff --git a/lib/graphics_engine/include/ge_vulkan_driver.hpp b/lib/graphics_engine/include/ge_vulkan_driver.hpp index d5d62dede..40e17a87c 100644 --- a/lib/graphics_engine/include/ge_vulkan_driver.hpp +++ b/lib/graphics_engine/include/ge_vulkan_driver.hpp @@ -31,6 +31,7 @@ namespace GE { GVS_MIN = 0, GVS_NEAREST = GVS_MIN, + GVS_SKYBOX, GVS_3D_MESH_MIPMAP_2, GVS_3D_MESH_MIPMAP_4, GVS_3D_MESH_MIPMAP_16, diff --git a/lib/graphics_engine/src/ge_vulkan_camera_scene_node.cpp b/lib/graphics_engine/src/ge_vulkan_camera_scene_node.cpp index a97599145..ece59ddc5 100644 --- a/lib/graphics_engine/src/ge_vulkan_camera_scene_node.cpp +++ b/lib/graphics_engine/src/ge_vulkan_camera_scene_node.cpp @@ -52,6 +52,9 @@ void GEVulkanCameraSceneNode::render() mat = m_ubo_data.m_projection_matrix * m_ubo_data.m_view_matrix; m_ubo_data.m_projection_view_matrix = mat; + + m_ubo_data.m_projection_view_matrix.getInverse( + m_ubo_data.m_inverse_projection_view_matrix); } // render // ---------------------------------------------------------------------------- diff --git a/lib/graphics_engine/src/ge_vulkan_camera_scene_node.hpp b/lib/graphics_engine/src/ge_vulkan_camera_scene_node.hpp index 790808310..5a290812e 100644 --- a/lib/graphics_engine/src/ge_vulkan_camera_scene_node.hpp +++ b/lib/graphics_engine/src/ge_vulkan_camera_scene_node.hpp @@ -14,6 +14,7 @@ irr::core::matrix4 m_projection_matrix; irr::core::matrix4 m_inverse_view_matrix; irr::core::matrix4 m_inverse_projection_matrix; irr::core::matrix4 m_projection_view_matrix; +irr::core::matrix4 m_inverse_projection_view_matrix; }; class GEVulkanCameraSceneNode : public irr::scene::CCameraSceneNode @@ -40,7 +41,7 @@ public: // ------------------------------------------------------------------------ irr::core::matrix4 getPVM() const; // ------------------------------------------------------------------------ - void* getUBOData() const { return (void*)&m_ubo_data; } + const GEVulkanCameraUBO* const getUBOData() const { return &m_ubo_data; } }; // GEVulkanCameraSceneNode } diff --git a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp index 0bdd07930..32b25119d 100644 --- a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp +++ b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp @@ -798,7 +798,8 @@ void GEVulkanDrawCall::uploadDynamicData(GEVulkanDriver* vk, } } - m_data_uploading.emplace_back(cam->getUBOData(), sizeof(GEVulkanCameraUBO)); + m_data_uploading.emplace_back((void*)cam->getUBOData(), + sizeof(GEVulkanCameraUBO)); object_data_uploading.insert(object_data_uploading.end(), m_data_uploading.begin(), m_data_uploading.end()); std::swap(m_data_uploading, object_data_uploading); diff --git a/lib/graphics_engine/src/ge_vulkan_driver.cpp b/lib/graphics_engine/src/ge_vulkan_driver.cpp index 30d3c144e..eb7d16412 100644 --- a/lib/graphics_engine/src/ge_vulkan_driver.cpp +++ b/lib/graphics_engine/src/ge_vulkan_driver.cpp @@ -13,6 +13,7 @@ #include "ge_vulkan_mesh_cache.hpp" #include "ge_vulkan_scene_manager.hpp" #include "ge_vulkan_shader_manager.hpp" +#include "ge_vulkan_skybox_renderer.hpp" #include "ge_vulkan_texture_descriptor.hpp" #include "ISceneManager.h" @@ -629,6 +630,7 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params, GE::setVideoDriver(this); createUnicolorTextures(); GEVulkan2dRenderer::init(this); + GEVulkanSkyBoxRenderer::init(); m_mesh_texture_descriptor = new GEVulkanTextureDescriptor( GEVulkanShaderManager::getSamplerSize(), GEVulkanShaderManager::getMeshTextureLayer(), @@ -680,6 +682,7 @@ void GEVulkanDriver::destroyVulkan() m_irrlicht_device->getSceneManager()->getMeshCache()) getVulkanMeshCache()->destroy(); delete m_mesh_texture_descriptor; + GEVulkanSkyBoxRenderer::destroy(); GEVulkan2dRenderer::destroy(); GEVulkanShaderManager::destroy(); @@ -1358,11 +1361,27 @@ void GEVulkanDriver::createSamplers() throw std::runtime_error("vkCreateSampler failed for GVS_NEAREST"); m_vk->samplers[GVS_NEAREST] = sampler; - const float max_aniso = m_properties.limits.maxSamplerAnisotropy; - // GVS_3D_MESH_MIPMAP_2 + // GVS_SKYBOX + sampler_info.anisotropyEnable = false; sampler_info.magFilter = VK_FILTER_LINEAR; sampler_info.minFilter = VK_FILTER_LINEAR; sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + result = vkCreateSampler(m_vk->device, &sampler_info, NULL, + &sampler); + + if (result != VK_SUCCESS) + throw std::runtime_error("vkCreateSampler failed for GVS_SKYBOX"); + m_vk->samplers[GVS_SKYBOX] = sampler; + + const float max_aniso = m_properties.limits.maxSamplerAnisotropy; + // GVS_3D_MESH_MIPMAP_2 + sampler_info.anisotropyEnable = supported_anisotropy; + sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; sampler_info.maxAnisotropy = std::min(2.0f, max_aniso); result = vkCreateSampler(m_vk->device, &sampler_info, NULL, &sampler); diff --git a/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp b/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp index 84c45c75c..6237d0e39 100644 --- a/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp +++ b/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp @@ -13,6 +13,7 @@ #include "ge_vulkan_fbo_texture.hpp" #include "ge_vulkan_mesh_cache.hpp" #include "ge_vulkan_mesh_scene_node.hpp" +#include "ge_vulkan_skybox_renderer.hpp" #include "ge_vulkan_texture_descriptor.hpp" #include "mini_glm.hpp" @@ -43,6 +44,7 @@ void GEVulkanSceneManager::clear() irr::scene::CSceneManager::clear(); static_cast(getVideoDriver()) ->getMeshTextureDescriptor()->clear(); + GEVulkanSkyBoxRenderer::destroy(); } // clear // ---------------------------------------------------------------------------- @@ -265,6 +267,12 @@ irr::u32 GEVulkanSceneManager::registerNodeForRendering( GEVulkanCameraSceneNode* cam = static_cast< GEVulkanCameraSceneNode*>(getActiveCamera()); + if (node->getType() == irr::scene::ESNT_SKY_BOX) + { + GEVulkanSkyBoxRenderer::addSkyBox(cam, node); + return 1; + } + if ((node->getType() == irr::scene::ESNT_ANIMATED_MESH && pass != irr::scene::ESNRP_SOLID) || (node->getType() == irr::scene::ESNT_MESH && diff --git a/lib/graphics_engine/src/ge_vulkan_skybox_renderer.cpp b/lib/graphics_engine/src/ge_vulkan_skybox_renderer.cpp new file mode 100644 index 000000000..2543b1608 --- /dev/null +++ b/lib/graphics_engine/src/ge_vulkan_skybox_renderer.cpp @@ -0,0 +1,385 @@ +#include "ge_vulkan_skybox_renderer.hpp" + +#include "ge_main.hpp" +#include "ge_vma.hpp" +#include "ge_vulkan_array_texture.hpp" +#include "ge_vulkan_camera_scene_node.hpp" +#include "ge_vulkan_driver.hpp" +#include "ge_vulkan_features.hpp" +#include "ge_vulkan_fbo_texture.hpp" +#include "ge_vulkan_shader_manager.hpp" + +#include +#include +#include + +namespace GE +{ +namespace GEVulkanSkyBoxRenderer +{ +// ============================================================================ +irr::scene::ISceneNode* g_skybox = NULL; +std::unordered_map g_render_skybox; + +GEVulkanArrayTexture* g_texture_cubemap = NULL; +bool g_updated_texture_descriptor = false; + +VkDescriptorSetLayout g_descriptor_layout = VK_NULL_HANDLE; +VkDescriptorPool g_descriptor_pool = VK_NULL_HANDLE; +VkDescriptorSet g_descriptor_set = VK_NULL_HANDLE; +VkPipelineLayout g_pipeline_layout = VK_NULL_HANDLE; +VkPipeline g_graphics_pipeline = VK_NULL_HANDLE; +} // GEVulkanSkyBoxRenderer + +// ============================================================================ +void GEVulkanSkyBoxRenderer::init() +{ + g_skybox = NULL; + g_render_skybox.clear(); + g_descriptor_layout = VK_NULL_HANDLE; + g_descriptor_pool = VK_NULL_HANDLE; + g_descriptor_set = VK_NULL_HANDLE; + g_pipeline_layout = VK_NULL_HANDLE; + g_graphics_pipeline = VK_NULL_HANDLE; + g_updated_texture_descriptor = true; +} // init + +// ---------------------------------------------------------------------------- +void GEVulkanSkyBoxRenderer::destroy() +{ + GEVulkanDriver* vk = getVKDriver(); + if (!vk) + return; + vk->waitIdle(); + + if (g_texture_cubemap != NULL) + { + g_texture_cubemap->drop(); + g_texture_cubemap = NULL; + } + + if (g_graphics_pipeline != VK_NULL_HANDLE) + vkDestroyPipeline(vk->getDevice(), g_graphics_pipeline, NULL); + g_graphics_pipeline = VK_NULL_HANDLE; + + if (g_pipeline_layout != VK_NULL_HANDLE) + vkDestroyPipelineLayout(vk->getDevice(), g_pipeline_layout, NULL); + g_pipeline_layout = VK_NULL_HANDLE; + + if (g_descriptor_pool != VK_NULL_HANDLE) + vkDestroyDescriptorPool(vk->getDevice(), g_descriptor_pool, NULL); + g_descriptor_pool = VK_NULL_HANDLE; + + if (g_descriptor_layout != VK_NULL_HANDLE) + { + vkDestroyDescriptorSetLayout(vk->getDevice(), g_descriptor_layout, + NULL); + } + g_descriptor_layout = VK_NULL_HANDLE; + + g_descriptor_set = VK_NULL_HANDLE; + g_skybox = NULL; + g_render_skybox.clear(); + g_updated_texture_descriptor = true; +} // destroy + +// ---------------------------------------------------------------------------- +void GEVulkanSkyBoxRenderer::render(VkCommandBuffer cmd, + GEVulkanCameraSceneNode* cam) +{ + if (g_render_skybox.find(cam) == g_render_skybox.end() || + !g_render_skybox.at(cam)) + return; + g_render_skybox.at(cam) = false; + + if (!g_updated_texture_descriptor) + { + g_updated_texture_descriptor = true; + + GEVulkanDriver* vk = getVKDriver(); + VkDescriptorImageInfo info; + info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + info.sampler = vk->getSampler(GVS_SKYBOX); + info.imageView = (VkImageView)g_texture_cubemap->getTextureHandler(); + + VkWriteDescriptorSet write_descriptor_set = {}; + write_descriptor_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptor_set.dstBinding = 0; + write_descriptor_set.dstArrayElement = 0; + write_descriptor_set.descriptorType = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_descriptor_set.descriptorCount = 1; + write_descriptor_set.pBufferInfo = 0; + write_descriptor_set.dstSet = g_descriptor_set; + write_descriptor_set.pImageInfo = &info; + + vkUpdateDescriptorSets(vk->getDevice(), 1, &write_descriptor_set, 0, + NULL); + } + + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, g_graphics_pipeline); + + vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + g_pipeline_layout, 0, 1, &g_descriptor_set, 0, NULL); + + vkCmdPushConstants(cmd, g_pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, + sizeof(irr::core::matrix4), + cam->getUBOData()->m_inverse_projection_view_matrix.pointer()); + + vkCmdDraw(cmd, 3, 1, 0, 0); +} // render + +// ---------------------------------------------------------------------------- +void GEVulkanSkyBoxRenderer::addSkyBox(GEVulkanCameraSceneNode* cam, + irr::scene::ISceneNode* skybox) +{ + if (skybox->getType() != irr::scene::ESNT_SKY_BOX) + return; + if (g_skybox == skybox) + { + g_render_skybox[cam] = true; + return; + } + + destroy(); + std::vector sky_tex; + std::array order = {{ 1, 3, 4, 5, 2, 0}}; + + for (unsigned i = 0; i < 6; i++) + { + video::ITexture* tex = skybox->getMaterial(order[i]).getTexture(0); + if (!tex) + return; + sky_tex.push_back(static_cast(tex)); + } + + auto swap_pixels = [](video::IImage* img, unsigned idx) + { + if (!(idx == 2 || idx == 3)) + return; + unsigned width = img->getDimension().Width; + uint8_t* tmp = new uint8_t[width * width * 4]; + uint32_t* tmp_array = (uint32_t*)tmp; + uint32_t* img_data = (uint32_t*)img->lock(); + for (unsigned i = 0; i < width; i++) + { + for (unsigned j = 0; j < width; j++) + tmp_array[j * width + i] = img_data[i * width + (width - j - 1)]; + } + uint8_t* u8_data = (uint8_t*)img->lock(); + delete [] u8_data; + img->setMemory(tmp); + }; + g_texture_cubemap = new GEVulkanArrayTexture(sky_tex, + VK_IMAGE_VIEW_TYPE_CUBE, swap_pixels); + g_updated_texture_descriptor = false; + + g_skybox = skybox; + g_render_skybox[cam] = true; + GEVulkanDriver* vk = getVKDriver(); + + // g_descriptor_layout + VkDescriptorSetLayoutBinding texture_layout_binding; + texture_layout_binding.binding = 0; + texture_layout_binding.descriptorCount = 1; + texture_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + texture_layout_binding.pImmutableSamplers = NULL; + texture_layout_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + + VkDescriptorSetLayoutCreateInfo setinfo = {}; + setinfo.flags = 0; + setinfo.pNext = NULL; + setinfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + setinfo.pBindings = &texture_layout_binding; + setinfo.bindingCount = 1; + if (vkCreateDescriptorSetLayout(vk->getDevice(), &setinfo, + NULL, &g_descriptor_layout) != VK_SUCCESS) + { + throw std::runtime_error("vkCreateDescriptorSetLayout failed for " + "addSkyBox"); + } + + // g_descriptor_pool + VkDescriptorPoolSize pool_size; + pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + pool_size.descriptorCount = 1; + + VkDescriptorPoolCreateInfo pool_info = {}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.flags = 0; + pool_info.maxSets = 1; + pool_info.poolSizeCount = 1; + pool_info.pPoolSizes = &pool_size; + if (vkCreateDescriptorPool(vk->getDevice(), &pool_info, NULL, + &g_descriptor_pool) != VK_SUCCESS) + { + throw std::runtime_error("vkCreateDescriptorPool failed for " + "addSkyBox"); + } + + // g_descriptor_set + std::vector layouts(1, g_descriptor_layout); + + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = g_descriptor_pool; + alloc_info.descriptorSetCount = layouts.size(); + alloc_info.pSetLayouts = layouts.data(); + + if (vkAllocateDescriptorSets(vk->getDevice(), &alloc_info, + &g_descriptor_set) != VK_SUCCESS) + { + throw std::runtime_error("vkAllocateDescriptorSets failed for " + "addSkyBox"); + } + + + // g_pipeline_layout + VkPipelineLayoutCreateInfo pipeline_layout_info = {}; + pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeline_layout_info.setLayoutCount = 1; + pipeline_layout_info.pSetLayouts = &g_descriptor_layout; + + VkPushConstantRange push_constant; + push_constant.offset = 0; + push_constant.size = sizeof(irr::core::matrix4); + push_constant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + pipeline_layout_info.pPushConstantRanges = &push_constant; + pipeline_layout_info.pushConstantRangeCount = 1; + + if (vkCreatePipelineLayout(vk->getDevice(), &pipeline_layout_info, + NULL, &g_pipeline_layout) != VK_SUCCESS) + { + throw std::runtime_error("vkCreatePipelineLayout failed for " + "addSkyBox"); + } + + // g_graphics_pipeline + VkPipelineShaderStageCreateInfo vert_shader_stage_info = {}; + vert_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vert_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT; + vert_shader_stage_info.module = GEVulkanShaderManager::getShader("fullscreen_quad.vert"); + vert_shader_stage_info.pName = "main"; + + VkPipelineShaderStageCreateInfo frag_shader_stage_info = {}; + frag_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + frag_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + frag_shader_stage_info.module = GEVulkanShaderManager::getShader("skybox.frag"); + frag_shader_stage_info.pName = "main"; + + std::array shader_stages = + {{ + vert_shader_stage_info, + frag_shader_stage_info + }}; + + VkPipelineVertexInputStateCreateInfo vertex_input_info = {}; + vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_input_info.vertexBindingDescriptionCount = 0; + vertex_input_info.vertexAttributeDescriptionCount = 0; + vertex_input_info.pVertexBindingDescriptions = NULL; + vertex_input_info.pVertexAttributeDescriptions = NULL; + + VkPipelineInputAssemblyStateCreateInfo input_assembly = {}; + input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + input_assembly.primitiveRestartEnable = VK_FALSE; + + VkViewport viewport = {}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = (float)vk->getSwapChainExtent().width; + viewport.height = (float)vk->getSwapChainExtent().height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor = {}; + scissor.offset = {0, 0}; + scissor.extent = vk->getSwapChainExtent(); + + VkPipelineViewportStateCreateInfo viewport_state = {}; + viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_state.viewportCount = 1; + viewport_state.pViewports = &viewport; + viewport_state.scissorCount = 1; + viewport_state.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterizer = {}; + rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.depthClampEnable = VK_FALSE; + rasterizer.rasterizerDiscardEnable = VK_FALSE; + rasterizer.polygonMode = VK_POLYGON_MODE_FILL; + rasterizer.lineWidth = 1.0f; + rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT; + rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterizer.depthBiasEnable = VK_FALSE; + + VkPipelineMultisampleStateCreateInfo multisampling = {}; + multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.sampleShadingEnable = VK_FALSE; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineDepthStencilStateCreateInfo depth_stencil = {}; + depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil.depthTestEnable = VK_TRUE; + depth_stencil.depthWriteEnable = VK_FALSE; + depth_stencil.depthCompareOp = VK_COMPARE_OP_EQUAL; + depth_stencil.depthBoundsTestEnable = VK_FALSE; + depth_stencil.stencilTestEnable = VK_FALSE; + + VkPipelineColorBlendAttachmentState color_blend_attachment = {}; + color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | + VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT; + color_blend_attachment.blendEnable = VK_FALSE; + + VkPipelineColorBlendStateCreateInfo color_blending = {}; + color_blending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + color_blending.logicOpEnable = VK_FALSE; + color_blending.logicOp = VK_LOGIC_OP_COPY; + color_blending.attachmentCount = 1; + color_blending.pAttachments = &color_blend_attachment; + color_blending.blendConstants[0] = 0.0f; + color_blending.blendConstants[1] = 0.0f; + color_blending.blendConstants[2] = 0.0f; + color_blending.blendConstants[3] = 0.0f; + + std::array dynamic_state = + {{ + VK_DYNAMIC_STATE_SCISSOR, + VK_DYNAMIC_STATE_VIEWPORT + }}; + + VkPipelineDynamicStateCreateInfo dynamic_state_info = {}; + dynamic_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + dynamic_state_info.dynamicStateCount = dynamic_state.size(), + dynamic_state_info.pDynamicStates = dynamic_state.data(); + + VkGraphicsPipelineCreateInfo pipeline_info = {}; + pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipeline_info.stageCount = shader_stages.size(); + pipeline_info.pStages = shader_stages.data(); + pipeline_info.pVertexInputState = &vertex_input_info; + pipeline_info.pInputAssemblyState = &input_assembly; + pipeline_info.pViewportState = &viewport_state; + pipeline_info.pRasterizationState = &rasterizer; + pipeline_info.pMultisampleState = &multisampling; + pipeline_info.pDepthStencilState = &depth_stencil; + pipeline_info.pColorBlendState = &color_blending; + pipeline_info.pDynamicState = &dynamic_state_info; + pipeline_info.layout = g_pipeline_layout; + pipeline_info.renderPass = vk->getRTTTexture() ? + vk->getRTTTexture()->getRTTRenderPass() : vk->getRenderPass(); + pipeline_info.subpass = 0; + pipeline_info.basePipelineHandle = VK_NULL_HANDLE; + + if (vkCreateGraphicsPipelines(vk->getDevice(), VK_NULL_HANDLE, + 1, &pipeline_info, NULL, &g_graphics_pipeline) != VK_SUCCESS) + { + throw std::runtime_error("vkCreateGraphicsPipelines failed for " + "addSkyBox"); + } + +} // addSkyBox + +} diff --git a/lib/graphics_engine/src/ge_vulkan_skybox_renderer.hpp b/lib/graphics_engine/src/ge_vulkan_skybox_renderer.hpp new file mode 100644 index 000000000..beccf3f5a --- /dev/null +++ b/lib/graphics_engine/src/ge_vulkan_skybox_renderer.hpp @@ -0,0 +1,29 @@ +#ifndef HEADER_GE_VULKAN_SKYBOX_RENDERER_HPP +#define HEADER_GE_VULKAN_SKYBOX_RENDERER_HPP + +#include "vulkan_wrapper.h" + +namespace irr +{ + namespace scene { class ISceneNode; } +} + +namespace GE +{ +class GEVulkanCameraSceneNode; +class GEVulkanDriver; +namespace GEVulkanSkyBoxRenderer +{ +// ---------------------------------------------------------------------------- +void init(); +// ---------------------------------------------------------------------------- +void destroy(); +// ---------------------------------------------------------------------------- +void render(VkCommandBuffer, GEVulkanCameraSceneNode*); +// ---------------------------------------------------------------------------- +void addSkyBox(GEVulkanCameraSceneNode*, irr::scene::ISceneNode*); +}; // GEVulkanSkyBoxRenderer + +} + +#endif diff --git a/lib/irrlicht/include/IImage.h b/lib/irrlicht/include/IImage.h index 7918759b5..bcdaabfa7 100644 --- a/lib/irrlicht/include/IImage.h +++ b/lib/irrlicht/include/IImage.h @@ -100,6 +100,8 @@ public: virtual void setDeleteMemory(bool val) = 0; + virtual void setMemory(u8* memory) = 0; + //! get the amount of Bits per Pixel of the given color format static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format) { diff --git a/lib/irrlicht/source/Irrlicht/CImage.cpp b/lib/irrlicht/source/Irrlicht/CImage.cpp index 60ff3702a..18804e329 100644 --- a/lib/irrlicht/source/Irrlicht/CImage.cpp +++ b/lib/irrlicht/source/Irrlicht/CImage.cpp @@ -462,5 +462,10 @@ void CImage::setDeleteMemory(bool val) DeleteMemory = val; } +void CImage::setMemory(u8* memory) +{ + Data = memory; +} + } // end namespace video } // end namespace irr diff --git a/lib/irrlicht/source/Irrlicht/CImage.h b/lib/irrlicht/source/Irrlicht/CImage.h index 8eb8459bc..e9c5aed83 100644 --- a/lib/irrlicht/source/Irrlicht/CImage.h +++ b/lib/irrlicht/source/Irrlicht/CImage.h @@ -105,6 +105,8 @@ public: virtual void setDeleteMemory(bool val); + virtual void setMemory(u8* memory); + private: //! assumes format and size has been set and creates the rest