mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Implement render ordering
This commit is contained in:
parent
5ddcb90ad2
commit
7c8b11e28a
@ -66,6 +66,13 @@ enum class Primitive {
|
|||||||
kTriangleStrip,
|
kTriangleStrip,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class CullMode {
|
||||||
|
kCullNone,
|
||||||
|
kCullFront,
|
||||||
|
kCullBack,
|
||||||
|
kCullFrontAndBack
|
||||||
|
};
|
||||||
|
|
||||||
enum class VertexAttribFormat { kFloat2, kFloat3, kFloat4 };
|
enum class VertexAttribFormat { kFloat2, kFloat3, kFloat4 };
|
||||||
|
|
||||||
enum class Filter : int {
|
enum class Filter : int {
|
||||||
@ -106,6 +113,7 @@ struct PipelineInfo {
|
|||||||
VertexFormat vertex_format;
|
VertexFormat vertex_format;
|
||||||
bool alpha_blending;
|
bool alpha_blending;
|
||||||
bool backface_culling;
|
bool backface_culling;
|
||||||
|
bool write_z;
|
||||||
std::vector<const DescriptorSetLayout*> descriptor_set_layouts;
|
std::vector<const DescriptorSetLayout*> descriptor_set_layouts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,18 +18,29 @@ class Shader {
|
|||||||
bool has_uv0; // vec2
|
bool has_uv0; // vec2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ShaderSettings {
|
||||||
|
VertexParams vertexParams;
|
||||||
|
bool alpha_blending;
|
||||||
|
bool cull_backface;
|
||||||
|
bool write_z;
|
||||||
|
int render_order;
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr int kHighestRenderOrder = 1;
|
||||||
|
|
||||||
Shader(RenderData* render_data, const char* vert_path, const char* frag_path,
|
Shader(RenderData* render_data, const char* vert_path, const char* frag_path,
|
||||||
const VertexParams& vertex_params, bool alpha_blending,
|
const ShaderSettings& settings);
|
||||||
bool cull_backface);
|
|
||||||
~Shader();
|
~Shader();
|
||||||
Shader(const Shader&) = delete;
|
Shader(const Shader&) = delete;
|
||||||
Shader& operator=(const Shader&) = delete;
|
Shader& operator=(const Shader&) = delete;
|
||||||
|
|
||||||
const gfx::Pipeline* GetPipeline();
|
const gfx::Pipeline* GetPipeline();
|
||||||
|
int GetRenderOrder() { return render_order_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GFXDevice* const gfx_;
|
GFXDevice* const gfx_;
|
||||||
const gfx::Pipeline* pipeline_;
|
const gfx::Pipeline* pipeline_;
|
||||||
|
const int render_order_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace resources
|
} // namespace resources
|
||||||
|
@ -139,10 +139,16 @@ Application::Application(const char* appName, const char* appVersion,
|
|||||||
resources::Shader::VertexParams vertParams{};
|
resources::Shader::VertexParams vertParams{};
|
||||||
vertParams.has_normal = true;
|
vertParams.has_normal = true;
|
||||||
vertParams.has_uv0 = true;
|
vertParams.has_uv0 = true;
|
||||||
|
resources::Shader::ShaderSettings shaderSettings{};
|
||||||
|
shaderSettings.vertexParams = vertParams;
|
||||||
|
shaderSettings.alpha_blending = false;
|
||||||
|
shaderSettings.cull_backface = true;
|
||||||
|
shaderSettings.write_z = true;
|
||||||
|
shaderSettings.render_order = 0;
|
||||||
auto texturedShader = std::make_unique<resources::Shader>(
|
auto texturedShader = std::make_unique<resources::Shader>(
|
||||||
&render_data_, GetResourcePath("engine/shaders/standard.vert").c_str(),
|
&render_data_, GetResourcePath("engine/shaders/standard.vert").c_str(),
|
||||||
GetResourcePath("engine/shaders/standard.frag").c_str(), vertParams,
|
GetResourcePath("engine/shaders/standard.frag").c_str(),
|
||||||
false, true);
|
shaderSettings);
|
||||||
GetResourceManager<resources::Shader>()->AddPersistent(
|
GetResourceManager<resources::Shader>()->AddPersistent(
|
||||||
"builtin.standard", std::move(texturedShader));
|
"builtin.standard", std::move(texturedShader));
|
||||||
}
|
}
|
||||||
@ -150,10 +156,15 @@ Application::Application(const char* appName, const char* appVersion,
|
|||||||
resources::Shader::VertexParams vertParams{};
|
resources::Shader::VertexParams vertParams{};
|
||||||
vertParams.has_normal = true;
|
vertParams.has_normal = true;
|
||||||
vertParams.has_uv0 = true;
|
vertParams.has_uv0 = true;
|
||||||
|
resources::Shader::ShaderSettings shaderSettings{};
|
||||||
|
shaderSettings.vertexParams = vertParams;
|
||||||
|
shaderSettings.alpha_blending = false;
|
||||||
|
shaderSettings.cull_backface = true;
|
||||||
|
shaderSettings.write_z = true;
|
||||||
|
shaderSettings.render_order = 0;
|
||||||
auto skyboxShader = std::make_unique<resources::Shader>(
|
auto skyboxShader = std::make_unique<resources::Shader>(
|
||||||
&render_data_, GetResourcePath("engine/shaders/skybox.vert").c_str(),
|
&render_data_, GetResourcePath("engine/shaders/skybox.vert").c_str(),
|
||||||
GetResourcePath("engine/shaders/skybox.frag").c_str(), vertParams,
|
GetResourcePath("engine/shaders/skybox.frag").c_str(), shaderSettings);
|
||||||
false, true);
|
|
||||||
GetResourceManager<resources::Shader>()->AddPersistent(
|
GetResourceManager<resources::Shader>()->AddPersistent(
|
||||||
"builtin.skybox", std::move(skyboxShader));
|
"builtin.skybox", std::move(skyboxShader));
|
||||||
}
|
}
|
||||||
@ -161,15 +172,19 @@ Application::Application(const char* appName, const char* appVersion,
|
|||||||
resources::Shader::VertexParams vertParams{};
|
resources::Shader::VertexParams vertParams{};
|
||||||
vertParams.has_normal = true;
|
vertParams.has_normal = true;
|
||||||
vertParams.has_uv0 = true;
|
vertParams.has_uv0 = true;
|
||||||
|
resources::Shader::ShaderSettings shaderSettings{};
|
||||||
|
shaderSettings.vertexParams = vertParams;
|
||||||
|
shaderSettings.alpha_blending = true;
|
||||||
|
shaderSettings.cull_backface = true;
|
||||||
|
shaderSettings.write_z = false;
|
||||||
|
shaderSettings.render_order = 1;
|
||||||
auto quadShader = std::make_unique<resources::Shader>(
|
auto quadShader = std::make_unique<resources::Shader>(
|
||||||
&render_data_, GetResourcePath("engine/shaders/quad.vert").c_str(),
|
&render_data_, GetResourcePath("engine/shaders/quad.vert").c_str(),
|
||||||
GetResourcePath("engine/shaders/quad.frag").c_str(), vertParams,
|
GetResourcePath("engine/shaders/quad.frag").c_str(), shaderSettings);
|
||||||
true, true);
|
|
||||||
GetResourceManager<resources::Shader>()->AddPersistent(
|
GetResourceManager<resources::Shader>()->AddPersistent(
|
||||||
"builtin.quad", std::move(quadShader));
|
"builtin.quad", std::move(quadShader));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* default textures */
|
/* default textures */
|
||||||
{
|
{
|
||||||
auto whiteTexture = std::make_unique<resources::Texture>(
|
auto whiteTexture = std::make_unique<resources::Texture>(
|
||||||
|
@ -214,6 +214,19 @@ namespace engine {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static VkCullModeFlags getCullModeFlags(gfx::CullMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case gfx::CullMode::kCullNone:
|
||||||
|
return VK_CULL_MODE_NONE;
|
||||||
|
case gfx::CullMode::kCullFront:
|
||||||
|
return VK_CULL_MODE_FRONT_BIT;
|
||||||
|
case gfx::CullMode::kCullBack:
|
||||||
|
return VK_CULL_MODE_BACK_BIT;
|
||||||
|
case gfx::CullMode::kCullFrontAndBack:
|
||||||
|
return VK_CULL_MODE_FRONT_AND_BACK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
@ -974,7 +987,7 @@ namespace engine {
|
|||||||
VkPipelineDepthStencilStateCreateInfo depthStencil{};
|
VkPipelineDepthStencilStateCreateInfo depthStencil{};
|
||||||
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||||
depthStencil.depthTestEnable = VK_TRUE;
|
depthStencil.depthTestEnable = VK_TRUE;
|
||||||
depthStencil.depthWriteEnable = VK_TRUE;
|
depthStencil.depthWriteEnable = info.write_z ? VK_TRUE : VK_FALSE;
|
||||||
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
|
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||||
depthStencil.depthBoundsTestEnable = VK_FALSE;
|
depthStencil.depthBoundsTestEnable = VK_FALSE;
|
||||||
depthStencil.minDepthBounds = 0.0f;
|
depthStencil.minDepthBounds = 0.0f;
|
||||||
|
@ -102,7 +102,7 @@ std::unique_ptr<std::vector<uint8_t>> Font::GetTextBitmap(
|
|||||||
(*bitmap)[out_index + 0] = pixel;
|
(*bitmap)[out_index + 0] = pixel;
|
||||||
(*bitmap)[out_index + 1] = pixel;
|
(*bitmap)[out_index + 1] = pixel;
|
||||||
(*bitmap)[out_index + 2] = pixel;
|
(*bitmap)[out_index + 2] = pixel;
|
||||||
(*bitmap)[out_index + 3] = 0xFF;
|
(*bitmap)[out_index + 3] = (pixel == 0x00) ? 0x00 : 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,32 +8,36 @@
|
|||||||
|
|
||||||
namespace engine::resources {
|
namespace engine::resources {
|
||||||
|
|
||||||
|
Shader::Shader(RenderData* renderData, const char* vertPath,
|
||||||
Shader::Shader(RenderData* renderData, const char* vertPath, const char* fragPath, const VertexParams& vertexParams, bool alphaBlending, bool cullBackFace)
|
const char* fragPath, const ShaderSettings& settings)
|
||||||
: gfx_(renderData->gfxdev.get())
|
: gfx_(renderData->gfxdev.get()), render_order_(settings.render_order) {
|
||||||
{
|
assert(settings.render_order <= kHighestRenderOrder && settings.render_order >= 0);
|
||||||
|
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
uint32_t stride = 0;
|
uint32_t stride = 0;
|
||||||
gfx::VertexFormat vertFormat{};
|
gfx::VertexFormat vertFormat{};
|
||||||
|
|
||||||
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat3, stride);
|
vertFormat.attribute_descriptions.emplace_back(
|
||||||
|
index++, gfx::VertexAttribFormat::kFloat3, stride);
|
||||||
stride += 3 * sizeof(float);
|
stride += 3 * sizeof(float);
|
||||||
|
|
||||||
if (vertexParams.has_normal) {
|
if (settings.vertexParams.has_normal) {
|
||||||
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat3, stride);
|
vertFormat.attribute_descriptions.emplace_back(
|
||||||
|
index++, gfx::VertexAttribFormat::kFloat3, stride);
|
||||||
stride += 3 * sizeof(float);
|
stride += 3 * sizeof(float);
|
||||||
}
|
}
|
||||||
if (vertexParams.has_tangent) {
|
if (settings.vertexParams.has_tangent) {
|
||||||
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat4, stride);
|
vertFormat.attribute_descriptions.emplace_back(
|
||||||
|
index++, gfx::VertexAttribFormat::kFloat4, stride);
|
||||||
stride += 4 * sizeof(float);
|
stride += 4 * sizeof(float);
|
||||||
}
|
}
|
||||||
if (vertexParams.has_color) {
|
if (settings.vertexParams.has_color) {
|
||||||
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat4, stride);
|
vertFormat.attribute_descriptions.emplace_back(
|
||||||
|
index++, gfx::VertexAttribFormat::kFloat4, stride);
|
||||||
stride += 4 * sizeof(float);
|
stride += 4 * sizeof(float);
|
||||||
}
|
}
|
||||||
if (vertexParams.has_uv0) {
|
if (settings.vertexParams.has_uv0) {
|
||||||
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat2, stride);
|
vertFormat.attribute_descriptions.emplace_back(
|
||||||
|
index++, gfx::VertexAttribFormat::kFloat2, stride);
|
||||||
stride += 2 * sizeof(float);
|
stride += 2 * sizeof(float);
|
||||||
}
|
}
|
||||||
vertFormat.stride = stride;
|
vertFormat.stride = stride;
|
||||||
@ -42,26 +46,21 @@ namespace engine::resources {
|
|||||||
info.vert_shader_path = vertPath;
|
info.vert_shader_path = vertPath;
|
||||||
info.frag_shader_path = fragPath;
|
info.frag_shader_path = fragPath;
|
||||||
info.vertex_format = vertFormat;
|
info.vertex_format = vertFormat;
|
||||||
info.alpha_blending = alphaBlending;
|
info.alpha_blending = settings.alpha_blending;
|
||||||
info.backface_culling = cullBackFace;
|
info.backface_culling = settings.cull_backface;
|
||||||
|
info.write_z = settings.write_z;
|
||||||
info.descriptor_set_layouts.push_back(renderData->global_set_layout);
|
info.descriptor_set_layouts.push_back(renderData->global_set_layout);
|
||||||
info.descriptor_set_layouts.push_back(renderData->frame_set_layout);
|
info.descriptor_set_layouts.push_back(renderData->frame_set_layout);
|
||||||
info.descriptor_set_layouts.push_back(renderData->material_set_layout);
|
info.descriptor_set_layouts.push_back(renderData->material_set_layout);
|
||||||
|
|
||||||
pipeline_ = gfx_->CreatePipeline(info);
|
pipeline_ = gfx_->CreatePipeline(info);
|
||||||
|
|
||||||
LOG_INFO("Loaded shader: {}, vertex attribs: {}", vertPath, vertFormat.attribute_descriptions.size());
|
LOG_INFO("Loaded shader: {}, vertex attribs: {}", vertPath,
|
||||||
|
vertFormat.attribute_descriptions.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader::~Shader()
|
Shader::~Shader() { gfx_->DestroyPipeline(pipeline_); }
|
||||||
{
|
|
||||||
gfx_->DestroyPipeline(pipeline_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const gfx::Pipeline* Shader::GetPipeline()
|
const gfx::Pipeline* Shader::GetPipeline() { return pipeline_; }
|
||||||
{
|
|
||||||
return pipeline_;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
} // namespace engine::resources
|
||||||
|
@ -71,8 +71,8 @@ void RenderSystem::OnUpdate(float ts) {
|
|||||||
uint32_t index_count;
|
uint32_t index_count;
|
||||||
PushConstants push_constants;
|
PushConstants push_constants;
|
||||||
};
|
};
|
||||||
std::unordered_map<const gfx::Pipeline*, std::vector<DrawCallData>>
|
std::vector<std::tuple<int, const gfx::Pipeline*, DrawCallData>>
|
||||||
pipeline_draw_calls{};
|
unsorted_draw_calls{};
|
||||||
|
|
||||||
for (uint32_t entity : entities_) {
|
for (uint32_t entity : entities_) {
|
||||||
auto r = scene_->GetComponent<RenderableComponent>(entity);
|
auto r = scene_->GetComponent<RenderableComponent>(entity);
|
||||||
@ -85,7 +85,10 @@ void RenderSystem::OnUpdate(float ts) {
|
|||||||
auto t = scene_->GetComponent<TransformComponent>(entity);
|
auto t = scene_->GetComponent<TransformComponent>(entity);
|
||||||
assert(t != nullptr);
|
assert(t != nullptr);
|
||||||
|
|
||||||
|
int render_order = r->material->GetShader()->GetRenderOrder();
|
||||||
|
|
||||||
const gfx::Pipeline* pipeline = r->material->GetShader()->GetPipeline();
|
const gfx::Pipeline* pipeline = r->material->GetShader()->GetPipeline();
|
||||||
|
|
||||||
DrawCallData data{};
|
DrawCallData data{};
|
||||||
data.vb = r->mesh->GetVB();
|
data.vb = r->mesh->GetVB();
|
||||||
data.ib = r->mesh->GetIB();
|
data.ib = r->mesh->GetIB();
|
||||||
@ -93,22 +96,40 @@ void RenderSystem::OnUpdate(float ts) {
|
|||||||
data.index_count = r->mesh->GetCount();
|
data.index_count = r->mesh->GetCount();
|
||||||
data.push_constants.model = t->world_matrix;
|
data.push_constants.model = t->world_matrix;
|
||||||
|
|
||||||
pipeline_draw_calls[pipeline].push_back(data);
|
unsorted_draw_calls.emplace_back(
|
||||||
|
std::make_tuple(render_order, pipeline, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<const gfx::Pipeline*, DrawCallData>> draw_calls{};
|
||||||
|
draw_calls.reserve(unsorted_draw_calls.size());
|
||||||
|
|
||||||
|
/* sort the draw calls */
|
||||||
|
for (int i = 0; i <= resources::Shader::kHighestRenderOrder; i++) {
|
||||||
|
for (const auto& [render_order, pipeline, data] : unsorted_draw_calls) {
|
||||||
|
if (render_order == i) {
|
||||||
|
draw_calls.emplace_back(std::make_pair(pipeline, data));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* begin rendering */
|
/* begin rendering */
|
||||||
render_data.draw_buffer = gfx_->BeginRender();
|
render_data.draw_buffer = gfx_->BeginRender();
|
||||||
|
|
||||||
/* these descriptor set bindings should persist across pipeline changes */
|
/* these descriptor set bindings should persist across pipeline changes */
|
||||||
const gfx::Pipeline* first_pipeline = pipeline_draw_calls.begin()->first;
|
const gfx::Pipeline* const first_pipeline = draw_calls.begin()->first;
|
||||||
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, first_pipeline,
|
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, first_pipeline,
|
||||||
render_data.global_set, 0);
|
render_data.global_set, 0);
|
||||||
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, first_pipeline,
|
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, first_pipeline,
|
||||||
render_data.frame_set, 1);
|
render_data.frame_set, 1);
|
||||||
|
|
||||||
for (const auto& [pipeline, draw_calls] : pipeline_draw_calls) {
|
gfx_->CmdBindPipeline(render_data.draw_buffer, first_pipeline);
|
||||||
|
const gfx::Pipeline* last_bound_pipeline = first_pipeline;
|
||||||
|
|
||||||
|
for (const auto& [pipeline, draw_call] : draw_calls) {
|
||||||
|
if (pipeline != last_bound_pipeline) {
|
||||||
gfx_->CmdBindPipeline(render_data.draw_buffer, pipeline);
|
gfx_->CmdBindPipeline(render_data.draw_buffer, pipeline);
|
||||||
for (const auto& draw_call : draw_calls) {
|
last_bound_pipeline = pipeline;
|
||||||
|
}
|
||||||
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, pipeline,
|
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, pipeline,
|
||||||
draw_call.material_set, 2);
|
draw_call.material_set, 2);
|
||||||
gfx_->CmdPushConstants(render_data.draw_buffer, pipeline, 0,
|
gfx_->CmdPushConstants(render_data.draw_buffer, pipeline, 0,
|
||||||
@ -118,7 +139,6 @@ void RenderSystem::OnUpdate(float ts) {
|
|||||||
gfx_->CmdDrawIndexed(render_data.draw_buffer, draw_call.index_count, 1, 0,
|
gfx_->CmdDrawIndexed(render_data.draw_buffer, draw_call.index_count, 1, 0,
|
||||||
0, 0);
|
0, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* draw */
|
/* draw */
|
||||||
gfx_->FinishRender(render_data.draw_buffer);
|
gfx_->FinishRender(render_data.draw_buffer);
|
||||||
|
Loading…
Reference in New Issue
Block a user