From 49ec7beb8f1211cf76191e117f49e63fb70e9b66 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Aug 2014 13:04:41 +0200 Subject: [PATCH] - separate draw lists for walls and flats. This makes the sorting much more efficient because draw types no longer need to be checked in the compare function. This is a lot more important than having perfect texture order. --- src/gl/scene/gl_drawinfo.cpp | 101 ++++++++++++++++++++--------------- src/gl/scene/gl_drawinfo.h | 13 +++-- src/gl/scene/gl_flats.cpp | 2 +- src/gl/scene/gl_scene.cpp | 26 +++++---- src/gl/scene/gl_walls.cpp | 4 +- 5 files changed, 87 insertions(+), 59 deletions(-) diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index 050860a48..c468b2a7a 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -644,7 +644,6 @@ SortNode * GLDrawList::DoSort(SortNode * head) case GLDIT_SPRITE: SortSpriteIntoPlane(head,node); break; - case GLDIT_POLY: break; } node=next; } @@ -670,7 +669,7 @@ SortNode * GLDrawList::DoSort(SortNode * head) case GLDIT_SPRITE: SortSpriteIntoWall(head,node); break; - case GLDIT_POLY: break; + case GLDIT_FLAT: break; } node=next; @@ -722,7 +721,6 @@ void GLDrawList::DoDraw(int pass, int i, bool trans) RenderSprite.Unclock(); } break; - case GLDIT_POLY: break; } } @@ -783,6 +781,36 @@ void GLDrawList::Draw(int pass) } } +//========================================================================== +// +// +// +//========================================================================== +void GLDrawList::DrawWalls(int pass) +{ + RenderWall.Clock(); + for(unsigned i=0;iwalls[di1->index]; - for(int i=0;i<2;i++) - { - switch(di[i]->rendertype) - { - case GLDIT_FLAT: - { - GLFlat * f=&sortinfo->flats[di[i]->index]; - tx[i]=f->gltexture; - clamp[i] = 0; - } - break; + const GLDrawItem * di2 = (const GLDrawItem *)b; + GLWall * w2=&sortinfo->walls[di2->index]; - case GLDIT_WALL: - { - GLWall * w=&sortinfo->walls[di[i]->index]; - tx[i]=w->gltexture; - clamp[i] = w->flags & 3; - } - break; + if (w1->gltexture != w2->gltexture) return w1->gltexture - w2->gltexture; + return ((w1->flags & 3) - (w2->flags & 3)); +} - case GLDIT_SPRITE: - { - GLSprite * s=&sortinfo->sprites[di[i]->index]; - tx[i]=s->gltexture; - clamp[i] = 3; - } - break; - case GLDIT_POLY: break; - } - } - if (tx[0]!=tx[1]) return tx[0]-tx[1]; - return clamp[0]-clamp[1]; // clamping forces different textures. +static int __cdecl difcmp (const void *a, const void *b) +{ + const GLDrawItem * di1 = (const GLDrawItem *)a; + GLFlat * w1=&sortinfo->flats[di1->index]; + + const GLDrawItem * di2 = (const GLDrawItem *)b; + GLFlat* w2=&sortinfo->flats[di2->index]; + + return w1->gltexture - w2->gltexture; } -void GLDrawList::Sort() +void GLDrawList::SortWalls() { if (drawitems.Size()!=0 && gl_sort_textures) { sortinfo=this; - qsort(&drawitems[0], drawitems.Size(), sizeof(drawitems[0]), dicmp); + qsort(&drawitems[0], drawitems.Size(), sizeof(drawitems[0]), diwcmp); + } +} + +void GLDrawList::SortFlats() +{ + if (drawitems.Size()!=0 && gl_sort_textures) + { + sortinfo=this; + qsort(&drawitems[0], drawitems.Size(), sizeof(drawitems[0]), difcmp); } } diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 9f8b2c383..b0a139108 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -13,9 +13,11 @@ enum GLDrawItemType enum DrawListType { - GLDL_PLAIN, - GLDL_MASKED, - GLDL_MASKEDOFS, + GLDL_PLAINWALLS, + GLDL_PLAINFLATS, + GLDL_MASKEDWALLS, + GLDL_MASKEDFLATS, + GLDL_MASKEDWALLSOFS, GLDL_MODELS, GLDL_TRANSLUCENT, @@ -106,7 +108,8 @@ public: void AddFlat(GLFlat * flat); void AddSprite(GLSprite * sprite); void Reset(); - void Sort(); + void SortWalls(); + void SortFlats(); void MakeSortList(); @@ -125,6 +128,8 @@ public: void DoDrawSorted(SortNode * node); void DrawSorted(); void Draw(int pass); + void DrawWalls(int pass); + void DrawFlats(int pass); GLDrawList * next; } ; diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 0df465caf..0bd4d9eb5 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -402,7 +402,7 @@ inline void GLFlat::PutFlat(bool fog) else { bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack); - list = masked ? GLDL_MASKED : GLDL_PLAIN; + list = masked ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS; } gl_drawinfo->drawlists[list].AddFlat (this); } diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index fb4de22ea..89d505168 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -340,18 +340,22 @@ void FGLRenderer::RenderScene(int recursion) gl_RenderState.EnableFog(true); gl_RenderState.BlendFunc(GL_ONE,GL_ZERO); - gl_drawinfo->drawlists[GLDL_PLAIN].Sort(); - gl_drawinfo->drawlists[GLDL_MASKED].Sort(); - gl_drawinfo->drawlists[GLDL_MASKEDOFS].Sort(); + gl_drawinfo->drawlists[GLDL_PLAINWALLS].SortWalls(); + gl_drawinfo->drawlists[GLDL_PLAINFLATS].SortFlats(); + gl_drawinfo->drawlists[GLDL_MASKEDWALLS].SortWalls(); + gl_drawinfo->drawlists[GLDL_MASKEDFLATS].SortFlats(); + gl_drawinfo->drawlists[GLDL_MASKEDWALLSOFS].SortWalls(); // if we don't have a persistently mapped buffer, we have to process all the dynamic lights up front, // so that we don't have to do repeated map/unmap calls on the buffer. if (mLightCount > 0 && gl_fixedcolormap == CM_DEFAULT && gl_lights && !(gl.flags & RFL_BUFFER_STORAGE)) { GLRenderer->mLights->Begin(); - gl_drawinfo->drawlists[GLDL_PLAIN].Draw(GLPASS_LIGHTSONLY); - gl_drawinfo->drawlists[GLDL_MASKED].Draw(GLPASS_LIGHTSONLY); - gl_drawinfo->drawlists[GLDL_MASKEDOFS].Draw(GLPASS_LIGHTSONLY); + gl_drawinfo->drawlists[GLDL_PLAINWALLS].Draw(GLPASS_LIGHTSONLY); + gl_drawinfo->drawlists[GLDL_PLAINFLATS].Draw(GLPASS_LIGHTSONLY); + gl_drawinfo->drawlists[GLDL_MASKEDWALLS].Draw(GLPASS_LIGHTSONLY); + gl_drawinfo->drawlists[GLDL_MASKEDFLATS].Draw(GLPASS_LIGHTSONLY); + gl_drawinfo->drawlists[GLDL_MASKEDWALLSOFS].Draw(GLPASS_LIGHTSONLY); gl_drawinfo->drawlists[GLDL_TRANSLUCENTBORDER].Draw(GLPASS_LIGHTSONLY); gl_drawinfo->drawlists[GLDL_TRANSLUCENT].Draw(GLPASS_LIGHTSONLY); GLRenderer->mLights->Finish(); @@ -375,7 +379,8 @@ void FGLRenderer::RenderScene(int recursion) gl_RenderState.EnableTexture(gl_texture); gl_RenderState.EnableBrightmap(true); - gl_drawinfo->drawlists[GLDL_PLAIN].Draw(pass); + gl_drawinfo->drawlists[GLDL_PLAINWALLS].Draw(pass); + gl_drawinfo->drawlists[GLDL_PLAINFLATS].Draw(pass); // Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show @@ -385,14 +390,15 @@ void FGLRenderer::RenderScene(int recursion) gl_RenderState.SetTextureMode(TM_MASK); } gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); - gl_drawinfo->drawlists[GLDL_MASKED].Draw(pass); + gl_drawinfo->drawlists[GLDL_MASKEDWALLS].Draw(pass); + gl_drawinfo->drawlists[GLDL_MASKEDFLATS].Draw(pass); // Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use. - if (gl_drawinfo->drawlists[GLDL_MASKEDOFS].Size() > 0) + if (gl_drawinfo->drawlists[GLDL_MASKEDWALLSOFS].Size() > 0) { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -128.0f); - gl_drawinfo->drawlists[GLDL_MASKEDOFS].Draw(pass); + gl_drawinfo->drawlists[GLDL_MASKEDWALLSOFS].Draw(pass); glDisable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0, 0); } diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index 1a9e30a72..bb160a790 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -151,11 +151,11 @@ void GLWall::PutWall(bool translucent) if ((flags&GLWF_SKYHACK && type == RENDERWALL_M2S)) { - list = GLDL_MASKEDOFS; + list = GLDL_MASKEDWALLSOFS; } else { - list = masked ? GLDL_MASKED : GLDL_PLAIN; + list = masked ? GLDL_MASKEDWALLS : GLDL_PLAINWALLS; } gl_drawinfo->drawlists[list].AddWall(this);