From 1a953b8a6c3aa88f3fa411f1c599e878ad596a65 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 29 Jul 2022 10:51:14 +0800 Subject: [PATCH] Add grass shader --- data/shaders/ge_shaders/grass.vert | 21 ++++++++++ .../src/ge_vulkan_draw_call.cpp | 39 +++++++++++++++---- .../src/ge_vulkan_draw_call.hpp | 16 ++++++++ 3 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 data/shaders/ge_shaders/grass.vert diff --git a/data/shaders/ge_shaders/grass.vert b/data/shaders/ge_shaders/grass.vert new file mode 100644 index 000000000..0b4d10ed8 --- /dev/null +++ b/data/shaders/ge_shaders/grass.vert @@ -0,0 +1,21 @@ +#include "utils/spm_layout.h" + +layout(push_constant) uniform Constants +{ + vec3 m_wind_direction; +} u_push_constants; + +void main() +{ + vec3 offset = sin(u_push_constants.m_wind_direction * (v_position.y * 0.1)); + offset += vec3(cos(u_push_constants.m_wind_direction) * 0.7); + vec3 position = v_position + offset * v_color.r; + + mat4 model_matrix = u_object_buffer.m_objects[gl_InstanceIndex].m_model; + gl_Position = u_camera.m_projection_view_matrix * model_matrix * + vec4(position, 1.0); + f_vertex_color = vec4(1.0); + f_uv = v_uv; + f_uv_two = v_uv_two; + f_material_id = u_object_buffer.m_objects[gl_InstanceIndex].m_material_id; +} diff --git a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp index a8051a543..070a6a916 100644 --- a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp +++ b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp @@ -256,6 +256,7 @@ std::string GEVulkanDrawCall::getShader(irr::scene::ISceneNode* node, case irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF: return "alphatest"; case irr::video::EMT_ONETEXTURE_BLEND: return "alphablend"; case irr::video::EMT_SOLID_2_LAYER: return "decal"; + case irr::video::EMT_STK_GRASS: return "grass"; default: return "solid"; } } // getShader @@ -290,6 +291,23 @@ void GEVulkanDrawCall::createAllPipelines(GEVulkanDriver* vk) settings.m_drawing_priority = (char)5; createPipeline(vk, settings); + settings.m_vertex_shader = "grass.vert"; + settings.m_skinning_vertex_shader = ""; + settings.m_shader_name = "grass"; + settings.m_drawing_priority = (char)5; + settings.m_push_constants_func = [](uint32_t* size, void** data) + { + static irr::core::vector3df wind_direction; + wind_direction = irr::core::vector3df(1.0f, 0.0f, 0.0f) * + (getMonoTimeMs() / 1000.0f) * 1.5f; + *size = sizeof(irr::core::vector3df); + *data = &wind_direction; + }; + createPipeline(vk, settings); + + settings.m_vertex_shader = "spm.vert"; + settings.m_skinning_vertex_shader = "spm_skinning.vert"; + settings.m_push_constants_func = nullptr; settings.m_depth_write = false; settings.m_backface_culling = false; settings.m_alphablend = true; @@ -615,6 +633,15 @@ void GEVulkanDrawCall::createVulkanData() pipeline_layout_info.setLayoutCount = all_layouts.size(); pipeline_layout_info.pSetLayouts = all_layouts.data(); + VkPushConstantRange push_constant; + push_constant.offset = 0; + const VkPhysicalDeviceLimits& limit = + vk->getPhysicalDeviceProperties().limits; + push_constant.size = std::min(limit.maxPushConstantsSize, 128u); + push_constant.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; + pipeline_layout_info.pPushConstantRanges = &push_constant; + pipeline_layout_info.pushConstantRangeCount = 1; + result = vkCreatePipelineLayout(vk->getDevice(), &pipeline_layout_info, NULL, &m_pipeline_layout); @@ -818,8 +845,7 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam, { if (m_cmds[i].m_shader != cur_pipeline) { - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - m_graphics_pipelines[cur_pipeline].first); + bindPipeline(cmd, cur_pipeline); vkCmdDrawIndexedIndirect(cmd, m_dynamic_data->getCurrentBuffer(), indirect_offset, draw_count, indirect_size); @@ -830,8 +856,7 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam, } draw_count++; } - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - m_graphics_pipelines[m_cmds.back().m_shader].first); + bindPipeline(cmd, m_cmds.back().m_shader); vkCmdDrawIndexedIndirect(cmd, m_dynamic_data->getCurrentBuffer(), indirect_offset, draw_count, indirect_size); @@ -839,8 +864,7 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam, else { int cur_mid = m_materials[m_cmds[0].m_cmd.vertexOffset]; - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - m_graphics_pipelines[cur_pipeline].first); + bindPipeline(cmd, cur_pipeline); if (!GEVulkanFeatures::supportsBindMeshTexturesAtOnce()) { vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, @@ -863,8 +887,7 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam, if (m_cmds[i].m_shader != cur_pipeline) { cur_pipeline = m_cmds[i].m_shader; - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - m_graphics_pipelines[cur_pipeline].first); + bindPipeline(cmd, cur_pipeline); } vkCmdDrawIndexed(cmd, cur_cmd.indexCount, cur_cmd.instanceCount, cur_cmd.firstIndex, cur_cmd.vertexOffset, cur_cmd.firstInstance); diff --git a/lib/graphics_engine/src/ge_vulkan_draw_call.hpp b/lib/graphics_engine/src/ge_vulkan_draw_call.hpp index f12f33fec..9bcba069d 100644 --- a/lib/graphics_engine/src/ge_vulkan_draw_call.hpp +++ b/lib/graphics_engine/src/ge_vulkan_draw_call.hpp @@ -1,6 +1,7 @@ #ifndef HEADER_GE_VULKAN_DRAW_CALL_HPP #define HEADER_GE_VULKAN_DRAW_CALL_HPP +#include #include #include #include @@ -51,6 +52,7 @@ struct PipelineSettings bool m_depth_test; bool m_depth_write; char m_drawing_priority; + std::function m_push_constants_func; bool isTransparent() const { return m_alphablend || m_additive; } }; @@ -110,6 +112,20 @@ private: void createVulkanData(); // ------------------------------------------------------------------------ std::string getShader(irr::scene::ISceneNode* node, int material_id); + // ------------------------------------------------------------------------ + void bindPipeline(VkCommandBuffer cmd, const std::string& name) const + { + auto& ret = m_graphics_pipelines.at(name); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ret.first); + if (ret.second.m_push_constants_func) + { + uint32_t size; + void* data; + ret.second.m_push_constants_func(&size, &data); + vkCmdPushConstants(cmd, m_pipeline_layout, + VK_SHADER_STAGE_ALL_GRAPHICS, 0, size, data); + } + } public: // ------------------------------------------------------------------------ GEVulkanDrawCall();