From fe9836f2d8d7abb0480582c544611a5b248310cc Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 18 Aug 2021 00:39:41 +0300 Subject: [PATCH] Refactor winding-based culling --- source/core/cullface.cpp | 32 +++++++++++++++++ source/core/cullface.h | 29 ++++++++++++++++ source/core/mesh.cpp | 18 +++------- source/core/mesh.h | 7 ++-- source/core/pipelinestate.cpp | 29 +++++++++++----- source/core/pipelinestate.h | 12 ++++--- source/core/windingtest.cpp | 61 --------------------------------- source/core/windingtest.h | 47 ------------------------- source/materials/renderpass.cpp | 10 +++--- source/materials/renderpass.h | 7 ++-- source/render/renderer.cpp | 16 ++++----- source/render/renderer.h | 8 ++--- 12 files changed, 118 insertions(+), 158 deletions(-) create mode 100644 source/core/cullface.cpp create mode 100644 source/core/cullface.h delete mode 100644 source/core/windingtest.cpp delete mode 100644 source/core/windingtest.h diff --git a/source/core/cullface.cpp b/source/core/cullface.cpp new file mode 100644 index 00000000..b1839504 --- /dev/null +++ b/source/core/cullface.cpp @@ -0,0 +1,32 @@ +#include +#include "cullface.h" + +namespace Msp { +namespace GL { + +void operator>>(const LexicalConverter &conv, FaceWinding &winding) +{ + if(conv.get()=="NON_MANIFOLD") + winding = NON_MANIFOLD; + else if(conv.get()=="CLOCKWISE") + winding = CLOCKWISE; + else if(conv.get()=="COUNTERCLOCKWISE") + winding = COUNTERCLOCKWISE; + else + throw lexical_error(format("conversion of '%s' to FaceWinding", conv.get())); +} + +void operator>>(const LexicalConverter &conv, CullMode &cull) +{ + if(conv.get()=="NO_CULL") + cull = NO_CULL; + else if(conv.get()=="CULL_FRONT") + cull = CULL_FRONT; + else if(conv.get()=="CULL_BACK") + cull = CULL_BACK; + else + throw lexical_error(format("conversion of '%s' to CullMode", conv.get())); +} + +} // namespace GL +} // namespace Msp diff --git a/source/core/cullface.h b/source/core/cullface.h new file mode 100644 index 00000000..fd90ef20 --- /dev/null +++ b/source/core/cullface.h @@ -0,0 +1,29 @@ +#ifndef MSP_GL_CULLFACE_H_ +#define MSP_GL_CULLFACE_H_ + +#include + +namespace Msp { +namespace GL { + +enum FaceWinding +{ + NON_MANIFOLD, + CLOCKWISE, + COUNTERCLOCKWISE +}; + +enum CullMode +{ + NO_CULL, + CULL_FRONT, + CULL_BACK +}; + +void operator>>(const LexicalConverter &, FaceWinding &); +void operator>>(const LexicalConverter &, CullMode &); + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/core/mesh.cpp b/source/core/mesh.cpp index 492f416d..4414a90e 100644 --- a/source/core/mesh.cpp +++ b/source/core/mesh.cpp @@ -31,7 +31,7 @@ void Mesh::init(ResourceManager *rm) ibuf = 0; dirty = 0; disallow_rendering = false; - winding = 0; + face_winding = NON_MANIFOLD; if(rm) set_manager(rm); @@ -149,9 +149,9 @@ void Mesh::add_batch(const Batch &b) check_buffers(INDEX_BUFFER); } -void Mesh::set_winding(const WindingTest *w) +void Mesh::set_winding(FaceWinding w) { - winding = w; + face_winding = w; } void Mesh::draw(Renderer &renderer) const @@ -183,7 +183,7 @@ void Mesh::draw(Renderer &renderer, const VertexSetup *vs, unsigned count) const resize_buffers(); renderer.set_vertex_setup(vs ? vs : &vtx_setup); - renderer.set_winding_test(winding); + renderer.set_front_face(face_winding); if(!count) { @@ -256,7 +256,7 @@ Mesh::Loader::Loader(Mesh &m, bool g): add("storage", &Loader::storage); add("vertices", &Loader::vertices); add("vertices", &Loader::vertices_with_format); - add("winding", &Loader::winding); + add("winding", &Mesh::face_winding); } void Mesh::Loader::storage(const vector &a) @@ -290,14 +290,6 @@ void Mesh::Loader::batch(PrimitiveType p) obj.add_batch(btc); } -void Mesh::Loader::winding(FaceWinding w) -{ - if(w==CLOCKWISE) - obj.winding = &WindingTest::clockwise(); - else if(w==COUNTERCLOCKWISE) - obj.winding = &WindingTest::counterclockwise(); -} - Mesh::AsyncLoader::AsyncLoader(Mesh &m, IO::Seekable &i): mesh(m), diff --git a/source/core/mesh.h b/source/core/mesh.h index 66516267..57ffce47 100644 --- a/source/core/mesh.h +++ b/source/core/mesh.h @@ -3,10 +3,10 @@ #include #include "batch.h" +#include "cullface.h" #include "resource.h" #include "vertexarray.h" #include "vertexsetup.h" -#include "windingtest.h" namespace Msp { namespace GL { @@ -36,7 +36,6 @@ public: void vertices(); void vertices_with_format(const std::vector &); void batch(PrimitiveType); - void winding(FaceWinding); }; private: @@ -70,7 +69,7 @@ private: VertexSetup vtx_setup; mutable unsigned short dirty; bool disallow_rendering; - const WindingTest *winding; + FaceWinding face_winding; std::string debug_name; public: @@ -97,7 +96,7 @@ public: void add_batch(const Batch &b); const std::vector &get_batches() const { return batches; } - void set_winding(const WindingTest *); + void set_winding(FaceWinding); void draw(Renderer &) const; void draw_instanced(Renderer &, const VertexSetup &, unsigned) const; diff --git a/source/core/pipelinestate.cpp b/source/core/pipelinestate.cpp index a3b9e640..cfeed9ab 100644 --- a/source/core/pipelinestate.cpp +++ b/source/core/pipelinestate.cpp @@ -12,7 +12,6 @@ #include "texture.h" #include "uniformblock.h" #include "vertexsetup.h" -#include "windingtest.h" using namespace std; @@ -25,7 +24,8 @@ vector PipelineState::bound_tex_targets; PipelineState::PipelineState(): shprog(0), vertex_setup(0), - winding_test(0), + front_face(COUNTERCLOCKWISE), + face_cull(NO_CULL), enabled_clip_planes(0), changes(0) { @@ -57,12 +57,21 @@ void PipelineState::set_vertex_setup(const VertexSetup *s) } } -void PipelineState::set_winding_test(const WindingTest *w) +void PipelineState::set_front_face(FaceWinding w) { - if(w!=winding_test) + if(w!=front_face) { - winding_test = w; - changes |= WINDING_TEST; + front_face = w; + changes |= FACE_CULL; + } +} + +void PipelineState::set_face_cull(CullMode c) +{ + if(c!=face_cull) + { + face_cull = c; + changes |= FACE_CULL; } } @@ -132,12 +141,14 @@ void PipelineState::apply(unsigned mask) const vertex_setup->refresh(); } - if(mask&WINDING_TEST) + if(mask&FACE_CULL) { - if(winding_test) + glFrontFace(front_face==CLOCKWISE ? GL_CW : GL_CCW); + + if(face_cull!=NO_CULL) { glEnable(GL_CULL_FACE); - glFrontFace(winding_test->get_winding()); + glCullFace(face_cull==CULL_FRONT ? GL_FRONT : GL_BACK); } else glDisable(GL_CULL_FACE); diff --git a/source/core/pipelinestate.h b/source/core/pipelinestate.h index 8d1d1aaa..55d96485 100644 --- a/source/core/pipelinestate.h +++ b/source/core/pipelinestate.h @@ -3,6 +3,7 @@ #include #include +#include "cullface.h" namespace Msp { namespace GL { @@ -42,7 +43,7 @@ private: { SHPROG = 1, VERTEX_SETUP = 2, - WINDING_TEST = 4, + FACE_CULL = 4, CLIP_PLANES = 8, TEXTURES = 16, UNIFORMS = 32 @@ -50,7 +51,8 @@ private: const Program *shprog; const VertexSetup *vertex_setup; - const WindingTest *winding_test; + FaceWinding front_face; + CullMode face_cull; unsigned enabled_clip_planes; std::vector textures; std::vector uniform_blocks; @@ -65,7 +67,8 @@ public: void set_shader_program(const Program *); void set_vertex_setup(const VertexSetup *); - void set_winding_test(const WindingTest *); + void set_front_face(FaceWinding); + void set_face_cull(CullMode); void set_enabled_clip_planes(unsigned); void set_texture(unsigned, const Texture *, const Sampler *); void set_uniforms(const DefaultUniformBlock *); @@ -76,7 +79,8 @@ public: const Program *get_shader_program() const { return shprog; } const VertexSetup *get_vertex_setup() const { return vertex_setup; } - const WindingTest *get_winding_test() const { return winding_test; } + FaceWinding get_front_face() const { return front_face; } + CullMode get_face_cull() const { return face_cull; } void apply() const; private: diff --git a/source/core/windingtest.cpp b/source/core/windingtest.cpp deleted file mode 100644 index 0b8218ad..00000000 --- a/source/core/windingtest.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include "windingtest.h" - -namespace Msp { -namespace GL { - -void operator>>(const LexicalConverter &conv, FaceWinding &winding) -{ - if(conv.get()=="CLOCKWISE") - winding = CLOCKWISE; - else if(conv.get()=="COUNTERCLOCKWISE") - winding = COUNTERCLOCKWISE; - else - throw lexical_error(format("conversion of '%s' to FaceWinding", conv.get())); -} - -WindingTest::WindingTest(): - winding(COUNTERCLOCKWISE) -{ } - -WindingTest::WindingTest(FaceWinding w): - winding(w) -{ } - -void WindingTest::bind() const -{ - if(set_current(this)) - { - glEnable(GL_CULL_FACE); - glFrontFace(winding); - } -} - -void WindingTest::unbind() -{ - if(set_current(0)) - glDisable(GL_CULL_FACE); -} - -const WindingTest &WindingTest::get_reverse() const -{ - if(winding==CLOCKWISE) - return counterclockwise(); - else - return clockwise(); -} - -const WindingTest &WindingTest::clockwise() -{ - static WindingTest test(CLOCKWISE); - return test; -} - -const WindingTest &WindingTest::counterclockwise() -{ - static WindingTest test(COUNTERCLOCKWISE); - return test; -} - -} // namespace GL -} // namespace Msp diff --git a/source/core/windingtest.h b/source/core/windingtest.h deleted file mode 100644 index ff5b417d..00000000 --- a/source/core/windingtest.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef MSP_GL_WINDINGTEST_H_ -#define MSP_GL_WINDINGTEST_H_ - -#include -#include "bindable.h" -#include "gl.h" - -namespace Msp { -namespace GL { - -enum FaceWinding -{ - CLOCKWISE = GL_CW, - COUNTERCLOCKWISE = GL_CCW -}; - -void operator>>(const LexicalConverter &, FaceWinding &); - -/** -Tests the winding of polygons. If the order of vertices on screen does not -match the winding, the polygon is not rendered. -*/ -class WindingTest: public Bindable -{ -private: - FaceWinding winding; - -public: - WindingTest(); - WindingTest(FaceWinding); - - FaceWinding get_winding() const { return winding; } - - void bind() const; - - static void unbind(); - - const WindingTest &get_reverse() const; - - static const WindingTest &clockwise(); - static const WindingTest &counterclockwise(); -}; - -} // namespace GL -} // namespace Msp - -#endif diff --git a/source/materials/renderpass.cpp b/source/materials/renderpass.cpp index 70143e96..9a7ceef7 100644 --- a/source/materials/renderpass.cpp +++ b/source/materials/renderpass.cpp @@ -21,7 +21,7 @@ RenderPass::RenderPass(): shprog_from_material(false), shdata(0), material(0), - back_faces(false), + face_cull(CULL_BACK), receive_shadows(false), image_based_lighting(false) { } @@ -124,9 +124,9 @@ int RenderPass::get_texture_index(const string &n) const return (shprog && i!=textures.end() ? shprog->get_uniform_binding(i->tag) : -1); } -void RenderPass::set_back_faces(bool bf) +void RenderPass::set_face_cull(CullMode fc) { - back_faces = bf; + face_cull = fc; } void RenderPass::set_receive_shadows(bool rs) @@ -141,7 +141,7 @@ void RenderPass::apply(Renderer &renderer) const renderer.set_shader_program(shprog, shdata.get()); if(material) renderer.add_shader_data(material->get_shader_data()); - renderer.set_reverse_winding(back_faces); + renderer.set_face_cull(face_cull); } void RenderPass::set_debug_name(const string &name) @@ -171,12 +171,12 @@ RenderPass::Loader::Loader(RenderPass &p, Collection &c): void RenderPass::Loader::init_actions() { + add("face_cull", &RenderPass::face_cull); add("shader", &Loader::shader); add("image_based_lighting", &RenderPass::image_based_lighting); add("material", &Loader::material_inline); add("material", &Loader::material); add("material_slot", &RenderPass::material_slot); - add("back_faces",&RenderPass::back_faces); add("receive_shadows", &RenderPass::receive_shadows); add("texture", &Loader::texture); add("uniforms", &Loader::uniforms); diff --git a/source/materials/renderpass.h b/source/materials/renderpass.h index d5587c25..94cc2ed9 100644 --- a/source/materials/renderpass.h +++ b/source/materials/renderpass.h @@ -3,6 +3,7 @@ #include #include +#include "cullface.h" #include "material.h" namespace Msp { @@ -83,7 +84,7 @@ private: const Material *material; std::string material_slot; std::vector textures; - bool back_faces; + CullMode face_cull; bool receive_shadows; bool image_based_lighting; @@ -106,8 +107,8 @@ public: Tag get_texture_tag(const std::string &) const; DEPRECATED void set_texture(unsigned, const Texture *, const Sampler * = 0); DEPRECATED int get_texture_index(const std::string &) const; - void set_back_faces(bool); - bool get_back_faces() const { return back_faces; } + void set_face_cull(CullMode); + CullMode get_face_cull() const { return face_cull; } void set_receive_shadows(bool); bool get_receive_shadows() const { return receive_shadows; } void set_image_based_lighting(bool); diff --git a/source/render/renderer.cpp b/source/render/renderer.cpp index 4acf3ded..29db9923 100644 --- a/source/render/renderer.cpp +++ b/source/render/renderer.cpp @@ -15,7 +15,6 @@ #include "texture.h" #include "vertexarray.h" #include "vertexsetup.h" -#include "windingtest.h" using namespace std; @@ -152,14 +151,14 @@ void Renderer::set_vertex_setup(const VertexSetup *vs) state->vertex_setup = vs; } -void Renderer::set_winding_test(const WindingTest *w) +void Renderer::set_front_face(FaceWinding winding) { - state->winding_test = w; + state->front_face = winding; } -void Renderer::set_reverse_winding(bool r) +void Renderer::set_face_cull(CullMode cull) { - state->reverse_winding = r; + state->face_cull = cull; } void Renderer::set_object_lod_bias(unsigned b) @@ -252,7 +251,8 @@ void Renderer::apply_state() } pipeline_state.set_vertex_setup(state->vertex_setup); - pipeline_state.set_winding_test((state->winding_test && state->reverse_winding) ? &state->winding_test->get_reverse() : state->winding_test); + pipeline_state.set_front_face(state->front_face); + pipeline_state.set_face_cull(state->face_cull); pipeline_state.set_enabled_clip_planes(state->clipping ? (1<clipping->get_n_planes())-1 : 0); if(state->texture_countobject_lod_bias; } -- 2.43.0