From e26f0b569809f746bfe0536593a5f1e6c30ca257 Mon Sep 17 00:00:00 2001 From: hyzboy Date: Tue, 15 Jun 2021 15:04:48 +0800 Subject: [PATCH] first finished SceneTreeToRenderList. --- inc/hgl/graph/SceneTreeToRenderList.h | 26 ++-- src/SceneGraph/SceneTreeToRenderList.cpp | 180 ++++++++++++++--------- 2 files changed, 128 insertions(+), 78 deletions(-) diff --git a/inc/hgl/graph/SceneTreeToRenderList.h b/inc/hgl/graph/SceneTreeToRenderList.h index 9677f7a8..4b1bb446 100644 --- a/inc/hgl/graph/SceneTreeToRenderList.h +++ b/inc/hgl/graph/SceneTreeToRenderList.h @@ -5,10 +5,17 @@ #include #include #include + +using RenderNodePointer=hgl::graph::RenderNode *; + +using RenderNodeComparator=Comparator; + namespace hgl { namespace graph { + using MVPArrayBuffer=GPUArrayBuffer; + class SceneTreeToRenderList { using PipelineSets =Sets; @@ -25,24 +32,25 @@ namespace hgl Frustum frustum; protected: + + RenderNodeComparator render_node_comparator; - RenderNodeList *render_node_list; ///<场景节点列表 + RenderNodeList render_node_list; ///<场景节点列表 - PipelineSets pipeline_sets; ///<管线合集 - MaterialSets material_sets; ///<材质合集 - MatInstSets mat_inst_sets; ///<材质实例合集 + //PipelineSets pipeline_sets; ///<管线合集 + //MaterialSets material_sets; ///<材质合集 + //MatInstSets mat_inst_sets; ///<材质实例合集 + + MVPArrayBuffer *mvp_array; + List ri_list; RenderList * render_list; protected: - virtual int Comp(RenderNode *,RenderNode *); ///<摄像机距离比较函数 - -// virtual bool InFrustum(const SceneNode *,void *); ///<平截头截剪函数 - virtual bool Begin(); virtual bool Expend(SceneNode *); - virtual bool End(); + virtual void End(); public: diff --git a/src/SceneGraph/SceneTreeToRenderList.cpp b/src/SceneGraph/SceneTreeToRenderList.cpp index 043f3320..14cf961c 100644 --- a/src/SceneGraph/SceneTreeToRenderList.cpp +++ b/src/SceneGraph/SceneTreeToRenderList.cpp @@ -1,96 +1,136 @@ #include #include +#include + +/** +* 理论上讲,我们需要按以下顺序排序 +* +* for(material) +* for(pipeline) +* for(material_instance) +* for(vbo) +* for(distance) +*/ + +template<> +int Comparator::compare(const RenderNodePointer &obj_one,const RenderNodePointer &obj_two) const +{ + int off; + + //比较材质 + hgl::graph::MaterialInstance *mi1=obj_one->ri->GetMaterialInstance(); + hgl::graph::MaterialInstance *mi2=obj_two->ri->GetMaterialInstance(); + + off=mi1->GetMaterial()-mi2->GetMaterial(); + + if(off) + return off; + + //比较管线 + hgl::graph::Pipeline *p1=obj_one->ri->GetPipeline(); + hgl::graph::Pipeline *p2=obj_two->ri->GetPipeline(); + + off=p1-p2; + + if(off) + return off; + + //比较材质实例 + off=mi1-mi2; + + if(off) + return off; + + //比较vbo+ebo + off=obj_one->ri->GetBufferHash() + -obj_two->ri->GetBufferHash(); + + if(off) + return off; + + //比较距离 + { + const double dist=obj_one->distance_to_camera_square- + obj_two->distance_to_camera_square; + + //由于距离差距可能会小于1,但又返回int,所以需要做如此处理 + + if(dist>0)return 1;else + if(dist<0)return -1; + } + + return 0; +} namespace hgl { namespace graph - { + { SceneTreeToRenderList::SceneTreeToRenderList(GPUDevice *d) { device=d; hgl_zero(camera_info); - - render_node_list=nullptr; - render_list=nullptr; + + mvp_array =new MVPArrayBuffer(device,VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + render_list =nullptr; } SceneTreeToRenderList::~SceneTreeToRenderList() { - SAFE_CLEAR(render_node_list); + delete mvp_array; } - - /** - * 理论上讲,我们需要按以下顺序排序 - * - * for(material) - * for(pipeline) - * for(material_instance) - * for(vbo) - * for(distance) - */ - - int SceneTreeToRenderList::Comp(RenderNode *obj_one,RenderNode *obj_two) - { - int off; - - //比较材质 - MaterialInstance *mi1=obj_one->ri->GetMaterialInstance(); - MaterialInstance *mi2=obj_two->ri->GetMaterialInstance(); - - off=mi1->GetMaterial()-mi2->GetMaterial(); - - if(off) - return off; - - //比较管线 - Pipeline *p1=obj_one->ri->GetPipeline(); - Pipeline *p2=obj_two->ri->GetPipeline(); - - off=p1-p2; - - if(off) - return off; - - //比较材质实例 - off=mi1-mi2; - - if(off) - return off; - - //比较vbo+ebo - off=obj_one->ri->GetBufferHash() - -obj_two->ri->GetBufferHash(); - - if(off) - return off; - - //比较距离 - return( obj_one->distance_to_camera_square- - obj_two->distance_to_camera_square); - } - - //bool SceneTreeToRenderList::InFrustum(const SceneNode *,void *) - //{ - // return(true); - //} bool SceneTreeToRenderList::Begin() { - if(!render_node_list) - render_node_list=new RenderNodeList; + render_node_list.ClearData(); + mvp_array->Clear(); + ri_list.ClearData(); - render_node_list->ClearData(); - - pipeline_sets.ClearData(); - material_sets.ClearData(); - mat_inst_sets.ClearData(); + //pipeline_sets.ClearData(); + //material_sets.ClearData(); + //mat_inst_sets.ClearData(); return(true); } - bool SceneTreeToRenderList::End() + void SceneTreeToRenderList::End() { + if(render_node_list.GetCount()<=0)return; + //排序 + Sort(render_node_list,&render_node_comparator); + + //产生MVP矩阵UBO数据 + { + const uint32_t count=render_node_list.GetCount(); + + { + //按当前总节点数量分配UBO + mvp_array->Alloc(count); + mvp_array->Clear(); + + ri_list.SetCount(count); + } + + { + const uint32_t unit_offset=mvp_array->GetUnitSize(); + + char *mp=(char *)(mvp_array->Map(0,count)); + RenderableInstance **ri=ri_list.GetData(); + + for(RenderNode *node:render_node_list) //未来可能要在Expend处考虑做去重 + { + memcpy(mp,&(node->matrix),sizeof(MVPMatrix)); + mp+=unit_offset; + + (*ri)=node->ri; + ++ri; + } + } + } + + //写入RenderList + render_list->Set(mvp_array->GetBuffer(),&ri_list); } bool SceneTreeToRenderList::Expend(SceneNode *sn) @@ -101,6 +141,8 @@ namespace hgl { RenderNode *rn=new RenderNode; + rn->matrix.Set(sn->GetLocalToWorldMatrix(),camera_info.vp); + rn->WorldCenter=sn->GetWorldCenter(); rn->distance_to_camera_square=length_squared(rn->WorldCenter,camera_info.pos); @@ -108,7 +150,7 @@ namespace hgl rn->ri=sn->render_obj; - render_node_list->Add(rn); + render_node_list.Add(rn); } for(SceneNode *sub:sn->SubNode)