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,
|
||||
};
|
||||
|
||||
enum class CullMode {
|
||||
kCullNone,
|
||||
kCullFront,
|
||||
kCullBack,
|
||||
kCullFrontAndBack
|
||||
};
|
||||
|
||||
enum class VertexAttribFormat { kFloat2, kFloat3, kFloat4 };
|
||||
|
||||
enum class Filter : int {
|
||||
@ -106,6 +113,7 @@ struct PipelineInfo {
|
||||
VertexFormat vertex_format;
|
||||
bool alpha_blending;
|
||||
bool backface_culling;
|
||||
bool write_z;
|
||||
std::vector<const DescriptorSetLayout*> descriptor_set_layouts;
|
||||
};
|
||||
|
||||
|
@ -18,18 +18,29 @@ class Shader {
|
||||
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,
|
||||
const VertexParams& vertex_params, bool alpha_blending,
|
||||
bool cull_backface);
|
||||
const ShaderSettings& settings);
|
||||
~Shader();
|
||||
Shader(const Shader&) = delete;
|
||||
Shader& operator=(const Shader&) = delete;
|
||||
|
||||
const gfx::Pipeline* GetPipeline();
|
||||
int GetRenderOrder() { return render_order_; }
|
||||
|
||||
private:
|
||||
GFXDevice* const gfx_;
|
||||
const gfx::Pipeline* pipeline_;
|
||||
const int render_order_;
|
||||
};
|
||||
|
||||
} // namespace resources
|
||||
|
@ -139,10 +139,16 @@ Application::Application(const char* appName, const char* appVersion,
|
||||
resources::Shader::VertexParams vertParams{};
|
||||
vertParams.has_normal = 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>(
|
||||
&render_data_, GetResourcePath("engine/shaders/standard.vert").c_str(),
|
||||
GetResourcePath("engine/shaders/standard.frag").c_str(), vertParams,
|
||||
false, true);
|
||||
GetResourcePath("engine/shaders/standard.frag").c_str(),
|
||||
shaderSettings);
|
||||
GetResourceManager<resources::Shader>()->AddPersistent(
|
||||
"builtin.standard", std::move(texturedShader));
|
||||
}
|
||||
@ -150,10 +156,15 @@ Application::Application(const char* appName, const char* appVersion,
|
||||
resources::Shader::VertexParams vertParams{};
|
||||
vertParams.has_normal = 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>(
|
||||
&render_data_, GetResourcePath("engine/shaders/skybox.vert").c_str(),
|
||||
GetResourcePath("engine/shaders/skybox.frag").c_str(), vertParams,
|
||||
false, true);
|
||||
GetResourcePath("engine/shaders/skybox.frag").c_str(), shaderSettings);
|
||||
GetResourceManager<resources::Shader>()->AddPersistent(
|
||||
"builtin.skybox", std::move(skyboxShader));
|
||||
}
|
||||
@ -161,15 +172,19 @@ Application::Application(const char* appName, const char* appVersion,
|
||||
resources::Shader::VertexParams vertParams{};
|
||||
vertParams.has_normal = 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>(
|
||||
&render_data_, GetResourcePath("engine/shaders/quad.vert").c_str(),
|
||||
GetResourcePath("engine/shaders/quad.frag").c_str(), vertParams,
|
||||
true, true);
|
||||
GetResourcePath("engine/shaders/quad.frag").c_str(), shaderSettings);
|
||||
GetResourceManager<resources::Shader>()->AddPersistent(
|
||||
"builtin.quad", std::move(quadShader));
|
||||
}
|
||||
|
||||
|
||||
/* default textures */
|
||||
{
|
||||
auto whiteTexture = std::make_unique<resources::Texture>(
|
||||
|
@ -214,6 +214,19 @@ namespace engine {
|
||||
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
|
||||
@ -974,7 +987,7 @@ namespace engine {
|
||||
VkPipelineDepthStencilStateCreateInfo depthStencil{};
|
||||
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||
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.depthBoundsTestEnable = VK_FALSE;
|
||||
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 + 1] = 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 {
|
||||
|
||||
|
||||
Shader::Shader(RenderData* renderData, const char* vertPath, const char* fragPath, const VertexParams& vertexParams, bool alphaBlending, bool cullBackFace)
|
||||
: gfx_(renderData->gfxdev.get())
|
||||
{
|
||||
|
||||
Shader::Shader(RenderData* renderData, const char* vertPath,
|
||||
const char* fragPath, const ShaderSettings& settings)
|
||||
: gfx_(renderData->gfxdev.get()), render_order_(settings.render_order) {
|
||||
assert(settings.render_order <= kHighestRenderOrder && settings.render_order >= 0);
|
||||
uint32_t index = 0;
|
||||
uint32_t stride = 0;
|
||||
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);
|
||||
|
||||
if (vertexParams.has_normal) {
|
||||
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat3, stride);
|
||||
if (settings.vertexParams.has_normal) {
|
||||
vertFormat.attribute_descriptions.emplace_back(
|
||||
index++, gfx::VertexAttribFormat::kFloat3, stride);
|
||||
stride += 3 * sizeof(float);
|
||||
}
|
||||
if (vertexParams.has_tangent) {
|
||||
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat4, stride);
|
||||
if (settings.vertexParams.has_tangent) {
|
||||
vertFormat.attribute_descriptions.emplace_back(
|
||||
index++, gfx::VertexAttribFormat::kFloat4, stride);
|
||||
stride += 4 * sizeof(float);
|
||||
}
|
||||
if (vertexParams.has_color) {
|
||||
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat4, stride);
|
||||
if (settings.vertexParams.has_color) {
|
||||
vertFormat.attribute_descriptions.emplace_back(
|
||||
index++, gfx::VertexAttribFormat::kFloat4, stride);
|
||||
stride += 4 * sizeof(float);
|
||||
}
|
||||
if (vertexParams.has_uv0) {
|
||||
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat2, stride);
|
||||
if (settings.vertexParams.has_uv0) {
|
||||
vertFormat.attribute_descriptions.emplace_back(
|
||||
index++, gfx::VertexAttribFormat::kFloat2, stride);
|
||||
stride += 2 * sizeof(float);
|
||||
}
|
||||
vertFormat.stride = stride;
|
||||
@ -42,26 +46,21 @@ namespace engine::resources {
|
||||
info.vert_shader_path = vertPath;
|
||||
info.frag_shader_path = fragPath;
|
||||
info.vertex_format = vertFormat;
|
||||
info.alpha_blending = alphaBlending;
|
||||
info.backface_culling = cullBackFace;
|
||||
info.alpha_blending = settings.alpha_blending;
|
||||
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->frame_set_layout);
|
||||
info.descriptor_set_layouts.push_back(renderData->material_set_layout);
|
||||
|
||||
pipeline_ = gfx_->CreatePipeline(info);
|
||||
|
||||
LOG_INFO("Loaded shader: {}, vertex attribs: {}", vertPath, vertFormat.attribute_descriptions.size());
|
||||
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
gfx_->DestroyPipeline(pipeline_);
|
||||
}
|
||||
|
||||
const gfx::Pipeline* Shader::GetPipeline()
|
||||
{
|
||||
return pipeline_;
|
||||
}
|
||||
|
||||
LOG_INFO("Loaded shader: {}, vertex attribs: {}", vertPath,
|
||||
vertFormat.attribute_descriptions.size());
|
||||
}
|
||||
|
||||
Shader::~Shader() { gfx_->DestroyPipeline(pipeline_); }
|
||||
|
||||
const gfx::Pipeline* Shader::GetPipeline() { return pipeline_; }
|
||||
|
||||
} // namespace engine::resources
|
||||
|
@ -71,8 +71,8 @@ void RenderSystem::OnUpdate(float ts) {
|
||||
uint32_t index_count;
|
||||
PushConstants push_constants;
|
||||
};
|
||||
std::unordered_map<const gfx::Pipeline*, std::vector<DrawCallData>>
|
||||
pipeline_draw_calls{};
|
||||
std::vector<std::tuple<int, const gfx::Pipeline*, DrawCallData>>
|
||||
unsorted_draw_calls{};
|
||||
|
||||
for (uint32_t entity : entities_) {
|
||||
auto r = scene_->GetComponent<RenderableComponent>(entity);
|
||||
@ -85,7 +85,10 @@ void RenderSystem::OnUpdate(float ts) {
|
||||
auto t = scene_->GetComponent<TransformComponent>(entity);
|
||||
assert(t != nullptr);
|
||||
|
||||
int render_order = r->material->GetShader()->GetRenderOrder();
|
||||
|
||||
const gfx::Pipeline* pipeline = r->material->GetShader()->GetPipeline();
|
||||
|
||||
DrawCallData data{};
|
||||
data.vb = r->mesh->GetVB();
|
||||
data.ib = r->mesh->GetIB();
|
||||
@ -93,22 +96,40 @@ void RenderSystem::OnUpdate(float ts) {
|
||||
data.index_count = r->mesh->GetCount();
|
||||
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 */
|
||||
render_data.draw_buffer = gfx_->BeginRender();
|
||||
|
||||
/* 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,
|
||||
render_data.global_set, 0);
|
||||
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, first_pipeline,
|
||||
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);
|
||||
for (const auto& draw_call : draw_calls) {
|
||||
last_bound_pipeline = pipeline;
|
||||
}
|
||||
gfx_->CmdBindDescriptorSet(render_data.draw_buffer, pipeline,
|
||||
draw_call.material_set, 2);
|
||||
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,
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw */
|
||||
gfx_->FinishRender(render_data.draw_buffer);
|
||||
|
Loading…
Reference in New Issue
Block a user