Add more shaders

This commit is contained in:
Benau 2022-07-28 13:37:09 +08:00
parent 3f99e63a3c
commit e9d3152c1a
11 changed files with 190 additions and 39 deletions

View File

@ -0,0 +1,15 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.h"
void main()
{
vec4 mixed_color = sampleMeshTexture0(f_material_id, f_uv)* f_vertex_color;
if (mixed_color.a < 0.5)
discard;
o_color = vec4(mixed_color.xyz, 1.0);
}

View File

@ -0,0 +1,16 @@
layout(location = 1) in vec2 f_uv;
layout(location = 2) in vec2 f_uv_two;
layout(location = 3) flat in int f_material_id;
layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.h"
void main()
{
vec4 color = sampleMeshTexture0(f_material_id, f_uv);
vec4 layer_two_tex = sampleMeshTexture1(f_material_id, f_uv_two);
layer_two_tex.rgb = layer_two_tex.a * layer_two_tex.rgb;
vec3 final_color = layer_two_tex.rgb + color.rgb * (1.0 - layer_two_tex.a);
o_color = vec4(final_color, 1.0);
}

View File

@ -1,6 +1,6 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 2) flat in int f_material_id;
layout(location = 3) flat in int f_material_id;
layout(location = 0) out vec4 o_color;

View File

@ -7,5 +7,6 @@ void main()
vec4(v_position, 1.0);
f_vertex_color = v_color.zyxw;
f_uv = v_uv;
f_uv_two = v_uv_two;
f_material_id = u_object_buffer.m_objects[gl_InstanceIndex].m_material_id;
}

View File

@ -13,5 +13,6 @@ void main()
joint_matrix * vec4(v_position, 1.0);
f_vertex_color = v_color.zyxw;
f_uv = v_uv;
f_uv_two = v_uv_two;
f_material_id = u_object_buffer.m_objects[gl_InstanceIndex].m_material_id;
}

View File

@ -0,0 +1,13 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.h"
void main()
{
vec4 mixed_color = sampleMeshTexture0(f_material_id, f_uv) * f_vertex_color;
o_color = vec4(mixed_color.rgb * mixed_color.a, mixed_color.a);
}

View File

@ -36,4 +36,5 @@ layout(location = 7) in vec4 v_weight;
layout(location = 0) out vec4 f_vertex_color;
layout(location = 1) out vec2 f_uv;
layout(location = 2) flat out int f_material_id;
layout(location = 2) out vec2 f_uv_two;
layout(location = 3) flat out int f_material_id;

View File

@ -103,7 +103,8 @@ void GEVulkanDrawCall::addNode(irr::scene::ISceneNode* node)
mesh->getMeshBuffer(i));
if (m_culling_tool->isCulled(buffer, node))
continue;
m_visible_nodes[buffer].push_back(node);
const std::string& shader = getShader(node, i);
m_visible_nodes[buffer][shader].emplace_back(node, i);
if (anode && !added_skinning &&
!anode->getSkinningMatrices().empty() &&
m_skinning_nodes.find(anode) == m_skinning_nodes.end())
@ -117,6 +118,9 @@ void GEVulkanDrawCall::addNode(irr::scene::ISceneNode* node)
// ----------------------------------------------------------------------------
void GEVulkanDrawCall::generate()
{
if (!m_visible_nodes.empty() && m_data_layout == VK_NULL_HANDLE)
createVulkanData();
std::unordered_map<irr::scene::ISceneNode*, int> skinning_offets;
int added_joint = 1;
m_skinning_data_padded_size = sizeof(irr::core::matrix4);
@ -152,12 +156,22 @@ void GEVulkanDrawCall::generate()
const int material_id = m_texture_descriptor->getTextureID(list);
if (!GEVulkanFeatures::supportsBindMeshTexturesAtOnce())
m_materials[p.first->getVBOOffset()] = material_id;
unsigned visible_count = p.second.size();
if (visible_count != 0)
const bool skinning = p.first->hasSkinning();
for (auto& q : p.second)
{
bool skinning = p.first->hasSkinning();
for (auto* node : p.second)
unsigned visible_count = q.second.size();
if (visible_count == 0)
continue;
std::string cur_shader = q.first;
if (skinning)
cur_shader += "_skinning";
if (m_graphics_pipelines.find(cur_shader) ==
m_graphics_pipelines.end())
continue;
for (auto& r : q.second)
{
irr::scene::ISceneNode* node = r.first;
int skinning_offset = -1000;
auto it = skinning_offets.find(node);
if (it != skinning_offets.end())
@ -172,32 +186,45 @@ void GEVulkanDrawCall::generate()
cmd.vertexOffset = p.first->getVBOOffset();
cmd.firstInstance = accumulated_instance;
accumulated_instance += visible_count;
m_cmds.emplace_back(cmd, skinning ? "solid_skinning" : "solid");
const PipelineSettings& settings =
m_graphics_pipelines[cur_shader].second;
std::string sorting_key =
std::string(1, settings.m_drawing_priority) + cur_shader;
m_cmds.push_back({ cmd, cur_shader, sorting_key });
}
}
if (!GEVulkanFeatures::supportsBindMeshTexturesAtOnce())
{
std::stable_sort(m_cmds.begin(), m_cmds.end(),
[this](
const std::pair<VkDrawIndexedIndirectCommand, std::string>& a,
const std::pair<VkDrawIndexedIndirectCommand, std::string>& b)
[this](const DrawCallData& a, const DrawCallData& b)
{
return m_materials[a.first.vertexOffset] <
m_materials[b.first.vertexOffset];
return m_materials[a.m_cmd.vertexOffset] <
m_materials[b.m_cmd.vertexOffset];
});
}
std::stable_sort(m_cmds.begin(), m_cmds.end(),
[](const std::pair<VkDrawIndexedIndirectCommand, std::string>& a,
const std::pair<VkDrawIndexedIndirectCommand, std::string>& b)
[](const DrawCallData& a, const DrawCallData& b)
{
return a.second < b.second;
return a.m_sorting_key < b.m_sorting_key;
});
if (!m_cmds.empty() && m_data_layout == VK_NULL_HANDLE)
createVulkanData();
} // generate
// ----------------------------------------------------------------------------
std::string GEVulkanDrawCall::getShader(irr::scene::ISceneNode* node,
int material_id)
{
irr::video::SMaterial& m = node->getMaterial(material_id);
switch (m.MaterialType)
{
case irr::video::EMT_TRANSPARENT_ADD_COLOR: return "additive";
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";
default: return "solid";
}
} // getShader
// ----------------------------------------------------------------------------
void GEVulkanDrawCall::prepare(GEVulkanCameraSceneNode* cam)
{
@ -208,13 +235,40 @@ void GEVulkanDrawCall::prepare(GEVulkanCameraSceneNode* cam)
// ----------------------------------------------------------------------------
void GEVulkanDrawCall::createAllPipelines(GEVulkanDriver* vk)
{
PipelineSettings settings;
PipelineSettings settings = {};
settings.m_depth_test = true;
settings.m_depth_write = true;
settings.m_backface_culling = true;
settings.m_vertex_shader = "spm.vert";
settings.m_skinning_vertex_shader = "spm_skinning.vert";
settings.m_fragment_shader = "solid.frag";
settings.m_shader_name = "solid";
createPipeline(vk, settings);
settings.m_fragment_shader = "decal.frag";
settings.m_shader_name = "decal";
createPipeline(vk, settings);
settings.m_fragment_shader = "alphatest.frag";
settings.m_shader_name = "alphatest";
settings.m_drawing_priority = (char)5;
createPipeline(vk, settings);
settings.m_depth_write = false;
settings.m_backface_culling = false;
settings.m_alphablend = true;
settings.m_drawing_priority = (char)10;
settings.m_fragment_shader = "transparent.frag";
settings.m_shader_name = "alphablend";
createPipeline(vk, settings);
settings.m_alphablend = false;
settings.m_additive = true;
settings.m_fragment_shader = "transparent.frag";
settings.m_shader_name = "additive";
createPipeline(vk, settings);
} // createAllPipelines
// ----------------------------------------------------------------------------
@ -326,7 +380,8 @@ start:
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.cullMode = settings.m_backface_culling ?
VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_NONE;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
@ -337,8 +392,8 @@ start:
VkPipelineDepthStencilStateCreateInfo depth_stencil = {};
depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depth_stencil.depthTestEnable = VK_TRUE;
depth_stencil.depthWriteEnable = VK_TRUE;
depth_stencil.depthTestEnable = settings.m_depth_test;
depth_stencil.depthWriteEnable = settings.m_depth_write;
depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS;
depth_stencil.depthBoundsTestEnable = VK_FALSE;
depth_stencil.stencilTestEnable = VK_FALSE;
@ -347,8 +402,25 @@ start:
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;
color_blend_attachment.blendEnable = settings.isTransparent();
if (settings.m_alphablend)
{
color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
color_blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
color_blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
color_blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD;
}
if (settings.m_additive)
{
color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
color_blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
color_blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
color_blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD;
}
VkPipelineColorBlendStateCreateInfo color_blending = {};
color_blending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
color_blending.logicOpEnable = VK_FALSE;
@ -578,7 +650,7 @@ void GEVulkanDrawCall::uploadDynamicData(GEVulkanDriver* vk,
for (auto& cmd : m_cmds)
{
m_data_uploading.emplace_back(
(void*)&cmd.first, sizeof(VkDrawIndexedIndirectCommand));
(void*)&cmd.m_cmd, sizeof(VkDrawIndexedIndirectCommand));
}
dst_stage |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
}
@ -700,7 +772,7 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
const bool use_multidraw = GEVulkanFeatures::supportsMultiDrawIndirect() &&
GEVulkanFeatures::supportsBindMeshTexturesAtOnce();
std::string cur_pipeline = m_cmds[0].second;
std::string cur_pipeline = m_cmds[0].m_shader;
if (use_multidraw)
{
size_t indirect_offset = m_skinning_data_padded_size +
@ -709,7 +781,7 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
unsigned draw_count = 0;
for (unsigned i = 0; i < m_cmds.size(); i++)
{
if (m_cmds[i].second != cur_pipeline)
if (m_cmds[i].m_shader != cur_pipeline)
{
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_graphics_pipelines[cur_pipeline].first);
@ -718,20 +790,20 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
draw_count, indirect_size);
indirect_offset += draw_count * indirect_size;
draw_count = 1;
cur_pipeline = m_cmds[i].second;
cur_pipeline = m_cmds[i].m_shader;
continue;
}
draw_count++;
}
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_graphics_pipelines[m_cmds.back().second].first);
m_graphics_pipelines[m_cmds.back().m_shader].first);
vkCmdDrawIndexedIndirect(cmd,
m_dynamic_data->getCurrentBuffer(), indirect_offset,
draw_count, indirect_size);
}
else
{
int cur_mid = m_materials[m_cmds[0].first.vertexOffset];
int cur_mid = m_materials[m_cmds[0].m_cmd.vertexOffset];
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_graphics_pipelines[cur_pipeline].first);
if (!GEVulkanFeatures::supportsBindMeshTexturesAtOnce())
@ -742,7 +814,7 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
}
for (unsigned i = 0; i < m_cmds.size(); i++)
{
const VkDrawIndexedIndirectCommand& cur_cmd = m_cmds[i].first;
const VkDrawIndexedIndirectCommand& cur_cmd = m_cmds[i].m_cmd;
int mid = m_materials[cur_cmd.vertexOffset];
if (!GEVulkanFeatures::supportsBindMeshTexturesAtOnce() &&
cur_mid != mid)
@ -753,9 +825,9 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
&m_texture_descriptor->getDescriptorSet()[cur_mid], 0,
NULL);
}
if (m_cmds[i].second != cur_pipeline)
if (m_cmds[i].m_shader != cur_pipeline)
{
cur_pipeline = m_cmds[i].second;
cur_pipeline = m_cmds[i].m_shader;
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_graphics_pipelines[cur_pipeline].first);
}

View File

@ -45,16 +45,33 @@ struct PipelineSettings
std::string m_skinning_vertex_shader;
std::string m_fragment_shader;
std::string m_shader_name;
bool m_alphablend;
bool m_additive;
bool m_backface_culling;
bool m_depth_test;
bool m_depth_write;
char m_drawing_priority;
bool isTransparent() const { return m_alphablend || m_additive; }
};
struct DrawCallData
{
VkDrawIndexedIndirectCommand m_cmd;
std::string m_shader;
std::string m_sorting_key;
};
class GEVulkanDrawCall
{
private:
std::unordered_map<GESPMBuffer*, std::vector<irr::scene::ISceneNode*> > m_visible_nodes;
std::unordered_map<GESPMBuffer*, std::unordered_map<std::string,
std::vector<std::pair<irr::scene::ISceneNode*, unsigned> > > >
m_visible_nodes;
GECullingTool* m_culling_tool;
std::vector<std::pair<VkDrawIndexedIndirectCommand, std::string> > m_cmds;
std::vector<DrawCallData> m_cmds;
std::vector<ObjectData> m_visible_objects;
@ -91,6 +108,8 @@ private:
void createPipeline(GEVulkanDriver* vk, const PipelineSettings& settings);
// ------------------------------------------------------------------------
void createVulkanData();
// ------------------------------------------------------------------------
std::string getShader(irr::scene::ISceneNode* node, int material_id);
public:
// ------------------------------------------------------------------------
GEVulkanDrawCall();
@ -113,7 +132,7 @@ public:
{
unsigned result = 0;
for (auto& cmd : m_cmds)
result += (cmd.first.indexCount / 3) * cmd.first.instanceCount;
result += (cmd.m_cmd.indexCount / 3) * cmd.m_cmd.instanceCount;
return result;
}
// ------------------------------------------------------------------------

View File

@ -37,6 +37,9 @@ extern "C" VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(
const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
void* user_data)
{
std::string msg = callback_data->pMessage;
if (msg.find("UNASSIGNED-CoreValidation-Shader-OutputNotConsumed") != std::string::npos)
return VK_FALSE;
#ifdef __ANDROID__
android_LogPriority alp;
switch (message_severity)
@ -47,9 +50,9 @@ extern "C" VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: alp = ANDROID_LOG_ERROR; break;
default: alp = ANDROID_LOG_INFO;
}
__android_log_print(alp, "VALIDATION:", "%s", callback_data->pMessage);
__android_log_print(alp, "VALIDATION:", "%s", msg.c_str());
#else
printf("%s\n", callback_data->pMessage);
printf("%s\n", msg.c_str());
#endif
return VK_FALSE;
};

View File

@ -779,6 +779,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
m_texname.c_str());
}
bool is_vk = irr_driver->getVideoDriver()->getDriverType() == EDT_VULKAN;
// Default solid
m->MaterialType = video::EMT_SOLID;
if (RaceManager::get()->getReverseTrack() &&
@ -834,6 +835,8 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
video::EMFN_MODULATE_1X,
video::EAS_TEXTURE |
video::EAS_VERTEX_COLOR);
if (is_vk)
m->MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
}
else if (m_shader_name == "grass")
{
@ -852,10 +855,17 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
m->EmissiveColor = video::SColor(255, 150, 150, 150);
m->SpecularColor = video::SColor(255, 150, 150, 150);
}
if (is_vk)
m->MaterialType = video::EMT_STK_GRASS;
#endif
#endif
}
else if (m_shader_name == "decal")
{
if (is_vk)
m->MaterialType = video::EMT_SOLID_2_LAYER;
}
if (isTransparent())
{