diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2022-08-30 14:06:22 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-08-30 14:06:22 +0300 |
commit | fce7e485787c7ef7435873352fa0ccc678926386 (patch) | |
tree | 06c1914583cab9bc32d18b98f9ea948d7c3ee38a | |
parent | 2f6463517e6e8d0e789884f14ecd43d39a48939f (diff) |
DRW: Add new pass type for transparent objects (PassSortable)
-rw-r--r-- | source/blender/draw/intern/draw_pass.hh | 59 | ||||
-rw-r--r-- | source/blender/draw/tests/draw_pass_test.cc | 26 |
2 files changed, 85 insertions, 0 deletions
diff --git a/source/blender/draw/intern/draw_pass.hh b/source/blender/draw/intern/draw_pass.hh index 513e7580742..650fa30010c 100644 --- a/source/blender/draw/intern/draw_pass.hh +++ b/source/blender/draw/intern/draw_pass.hh @@ -364,6 +364,65 @@ template<typename DrawCommandBufType> class Pass : public detail::PassBase<DrawC */ // using PassMain = detail::Pass<DrawMultiBuf>; +/** + * Special pass type for rendering transparent objects. + * The base level can only be composed of sub passes that will be ordered by a special value. + */ +class PassSortable : public PassMain { + private: + /** Sorting value associated with each sub pass. */ + Vector<float> sorting_values_; + + bool sorted_ = false; + + public: + PassSortable(const char *name_) : PassMain(name_){}; + + void init() + { + sorting_values_.clear(); + sorted_ = false; + PassMain::init(); + } + + PassMain::Sub &sub(const char *name, float sorting_value) + { + int64_t index = sub_passes_.append_and_get_index( + PassBase(name, draw_commands_buf_, sub_passes_, shader_)); + headers_.append({Type::SubPass, static_cast<uint>(index)}); + sorting_values_.append(sorting_value); + return sub_passes_[index]; + } + + std::string serialize(std::string line_prefix = "") const + { + if (sorted_ == false) { + const_cast<PassSortable *>(this)->sort(); + } + return PassMain::serialize(line_prefix); + } + + protected: + void sort() + { + std::sort(headers_.begin(), headers_.end(), [&](Header &a, Header &b) { + BLI_assert(a.type == Type::SubPass && b.type == Type::SubPass); + float a_val = sorting_values_[a.index]; + float b_val = sorting_values_[b.index]; + return a_val < b_val || (a_val == b_val && a.index < b.index); + }); + sorted_ = true; + } + + void submit(command::RecordingState &state) const + { + if (sorted_ == false) { + const_cast<PassSortable *>(this)->sort(); + } + PassMain::submit(state); + } +}; + /** \} */ namespace detail { diff --git a/source/blender/draw/tests/draw_pass_test.cc b/source/blender/draw/tests/draw_pass_test.cc index ca32c4f1f29..5a8adaa866a 100644 --- a/source/blender/draw/tests/draw_pass_test.cc +++ b/source/blender/draw/tests/draw_pass_test.cc @@ -203,6 +203,32 @@ static void test_draw_pass_multi_draw() } DRAW_TEST(draw_pass_multi_draw) +static void test_draw_pass_sortable() +{ + PassSortable pass = {"test.sortable"}; + pass.init(); + + pass.sub("Sub3", 3.0f); + pass.sub("Sub2", 2.0f); + pass.sub("Sub5", 4.0f); + pass.sub("Sub4", 3.0f); + pass.sub("Sub1", 1.0f); + + std::string result = pass.serialize(); + std::stringstream expected; + expected << ".test.sortable" << std::endl; + expected << " .Sub1" << std::endl; + expected << " .Sub2" << std::endl; + expected << " .Sub3" << std::endl; + expected << " .Sub4" << std::endl; + expected << " .Sub5" << std::endl; + + EXPECT_EQ(result, expected.str()); + + DRW_shape_cache_free(); +} +DRAW_TEST(draw_pass_sortable) + static void test_draw_resource_id_gen() { float4x4 win_mat; |