From 638f19172ac649073058efbe51fe5910ee36a605 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Apr 2021 18:20:07 +0200 Subject: [PATCH] - voxel rendering. The stock voxels of Blood and SW seem to work so far, but not all edge cases have been tested. --- source/CMakeLists.txt | 2 +- source/build/src/voxmodel.cpp | 2 +- source/common/utility/matrix.h | 4 +- .../rendering/hw_models.cpp} | 4 +- .../rendering/hw_models.h} | 2 +- source/core/rendering/scene/hw_drawinfo.cpp | 8 +- source/core/rendering/scene/hw_drawstructs.h | 20 ++- source/core/rendering/scene/hw_sprites.cpp | 133 +++++++++++++++++- source/glbackend/glbackend.cpp | 4 +- 9 files changed, 153 insertions(+), 26 deletions(-) rename source/{glbackend/gl_models.cpp => core/rendering/hw_models.cpp} (97%) rename source/{glbackend/gl_models.h => core/rendering/hw_models.h} (97%) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index de6c438ee..99b5d0e26 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1023,7 +1023,6 @@ set (PCH_SOURCES glbackend/glbackend.cpp glbackend/gl_palmanager.cpp glbackend/gl_texture.cpp - glbackend/gl_models.cpp thirdparty/src/md4.cpp @@ -1073,6 +1072,7 @@ set (PCH_SOURCES core/gi.cpp core/rendering/hw_entrypoint.cpp + core/rendering/hw_models.cpp core/rendering/scene/hw_clipper.cpp core/rendering/scene/hw_walls.cpp core/rendering/scene/hw_flats.cpp diff --git a/source/build/src/voxmodel.cpp b/source/build/src/voxmodel.cpp index 6f47281e9..9f8fd0117 100644 --- a/source/build/src/voxmodel.cpp +++ b/source/build/src/voxmodel.cpp @@ -12,7 +12,7 @@ #include "hw_renderstate.h" #include "texturemanager.h" #include "voxels.h" -#include "glbackend/gl_models.h" +#include "hw_models.h" #include "printf.h" #include "palette.h" diff --git a/source/common/utility/matrix.h b/source/common/utility/matrix.h index 1c46c2397..81d7be6f2 100644 --- a/source/common/utility/matrix.h +++ b/source/common/utility/matrix.h @@ -33,9 +33,7 @@ class VSMatrix { public: - VSMatrix() - { - } + VSMatrix() = default; VSMatrix(int) { diff --git a/source/glbackend/gl_models.cpp b/source/core/rendering/hw_models.cpp similarity index 97% rename from source/glbackend/gl_models.cpp rename to source/core/rendering/hw_models.cpp index 318ed7d3f..3472d6215 100644 --- a/source/glbackend/gl_models.cpp +++ b/source/core/rendering/hw_models.cpp @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, @@ -33,7 +33,7 @@ #include "hwrenderer/data/buffers.h" #include "flatvertices.h" #include "hw_renderstate.h" -#include "gl_models.h" +#include "hw_models.h" //CVAR(Bool, gl_light_models, true, CVAR_ARCHIVE) diff --git a/source/glbackend/gl_models.h b/source/core/rendering/hw_models.h similarity index 97% rename from source/glbackend/gl_models.h rename to source/core/rendering/hw_models.h index c13fc7800..b533aa428 100644 --- a/source/glbackend/gl_models.h +++ b/source/core/rendering/hw_models.h @@ -6,7 +6,7 @@ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or +// the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, diff --git a/source/core/rendering/scene/hw_drawinfo.cpp b/source/core/rendering/scene/hw_drawinfo.cpp index f5e7daf70..3a892a4e7 100644 --- a/source/core/rendering/scene/hw_drawinfo.cpp +++ b/source/core/rendering/scene/hw_drawinfo.cpp @@ -303,14 +303,14 @@ void HWDrawInfo::DispatchSprites() { if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT) != CSTAT_SPRITE_ALIGNMENT_SLAB && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) { - //HWSprite hwsprite; - //if (hwsprite.ProcessVoxel(voxmodels[tiletovox[tspr->picnum]], tspr)) return; + HWSprite hwsprite; + if (hwsprite.ProcessVoxel(this, voxmodels[tiletovox[tspr->picnum]], tspr, §or[tspr->sectnum])) return; break; } else if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB && tspr->picnum < MAXVOXELS && voxmodels[tspr->picnum]) { - //HWSprite hwsprite; - //hwsprite.ProcessVoxel(voxmodels[tspr->picnum], tspr); + HWSprite hwsprite; + hwsprite.ProcessVoxel(this, voxmodels[tspr->picnum], tspr, §or[tspr->sectnum]); break; } } diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index 4364b98e0..e1723b8e1 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -10,6 +10,7 @@ #include "build.h" #include "gamefuncs.h" #include "render.h" +#include "matrix.h" #ifdef _MSC_VER #pragma warning(disable:4244) @@ -292,7 +293,8 @@ public: int shade, palette, visibility; float alpha; FRenderStyle RenderStyle; - int modelframe; // : sprite, 1: model, <0:voxel index + int modelframe; // : sprite, 1: model, -1:voxel + voxmodel_t* voxel; int index; float depth; @@ -300,10 +302,17 @@ public: float x,y,z; // needed for sorting! - float ul,ur; - float vt,vb; - float x1,y1,z1; - float x2,y2,z2; + union + { + struct + { + float ul, ur; + float vt, vb; + float x1, y1, z1; + float x2, y2, z2; + }; + VSMatrix rotmat; + }; int dynlightindex; FGameTexture *texture; @@ -317,6 +326,7 @@ public: void CreateVertices(HWDrawInfo* di); void PutSprite(HWDrawInfo *di, bool translucent); void Process(HWDrawInfo *di, spritetype* thing,sectortype * sector, int thruportal = false); + bool ProcessVoxel(HWDrawInfo* di, voxmodel_t* voxel, spritetype* tspr, sectortype* sector); void DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent); }; diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index a38e34c61..a2b307220 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -42,6 +42,8 @@ #include "hw_dynlightdata.h" #include "hw_lightbuffer.h" #include "hw_renderstate.h" +#include "hw_models.h" +#include "hw_viewpointbuffer.h" extern PalEntry GlobalMapFog; extern float GlobalFogDensity; @@ -142,11 +144,9 @@ void HWSprite::DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent) // The shade rgb from the tint is ignored here. state.SetColorAlpha(color, alpha); - state.SetMaterial(texture, UF_Texture, 0, CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); - - - if (!modelframe) + if (modelframe == 0) { + state.SetMaterial(texture, UF_Texture, 0, CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); state.SetNormal(0, 0, 0); @@ -170,9 +170,27 @@ void HWSprite::DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent) } else { - //FHWModelRenderer renderer(di, state, dynlightindex); - //RenderModel(&renderer, x, y, z, modelframe, actor, di->Viewpoint.TicFrac); - //state.SetVertexBuffer(screen->mVertexData); + state.EnableModelMatrix(true); + state.mModelMatrix = rotmat; + FHWModelRenderer mr(state, dynlightindex); + if (modelframe < 0) + { + auto model = voxel->model; + state.SetDepthFunc(DF_LEqual); + state.EnableTexture(true); + model->BuildVertexBuffer(&mr); + mr.SetupFrame(model, 0, 0, 0); + model->RenderFrame(&mr, TexMan.GetGameTexture(model->GetPaletteTexture()), 0, 0, 0.f, TRANSLATION(Translation_Remap + curbasepal, palette)); + state.SetDepthFunc(DF_Less); + state.SetVertexBuffer(screen->mVertexData); + + } + else + { + //RenderModel(&renderer, x, y, z, modelframe, actor, di->Viewpoint.TicFrac); + } + state.SetVertexBuffer(screen->mVertexData); + state.EnableModelMatrix(false); } if (translucent) @@ -443,3 +461,104 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int rendered_sprites++; } + +//========================================================================== +// +// +// +//========================================================================== + +bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, spritetype* spr, sectortype* sector) +{ + sprite = spr; + + texture = nullptr; + modelframe = -1; + dynlightindex = -1; + shade = spr->shade; + palette = spr->pal; + fade = lookups.getFade(sector->floorpal); // fog is per sector. + visibility = sectorVisibility(sector); + voxel = vox; + + if (!vox || (spr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_FLOOR) return false; + + bool trans = (spr->cstat & CSTAT_SPRITE_TRANSLUCENT); + if (trans) + { + RenderStyle = GetRenderStyle(0, !!(spr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); + alpha = GetAlphaFromBlend((spr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0); + } + else + { + RenderStyle = LegacyRenderStyles[STYLE_Translucent]; + alpha = 1.f; + } + + auto sprext = &spriteext[spr->owner]; + + FVector3 scalevec = { voxel->scale, voxel->scale, voxel->scale }; + FVector3 translatevec = { 0, 0, voxel->zadd * voxel->scale }; + + float basescale = voxel->bscale / 64.f; + float sprxscale = (float)spr->xrepeat * (256.f / 320.f) * basescale; + if ((::sprite[spr->owner].cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_WALL) + { + sprxscale *= 1.25f; + translatevec.Y -= spr->xoffset * bcosf(sprext->angoff, -20); + translatevec.X += spr->xoffset * bsinf(sprext->angoff, -20); + } + + if (spr->cstat & CSTAT_SPRITE_YFLIP) + { + scalevec.Z = -scalevec.Z; + translatevec.Z = -translatevec.Z; + } + if (spr->cstat & CSTAT_SPRITE_XFLIP) + { + scalevec.X = -scalevec.X; + translatevec.X = -translatevec.X; + translatevec.Y = -translatevec.Y; + } + + scalevec.X *= sprxscale; + translatevec.X *= sprxscale; + scalevec.Y *= sprxscale; + translatevec.Y *= sprxscale; + float sprzscale = (float)spr->yrepeat * basescale; + scalevec.Z *= sprzscale; + translatevec.Z *= sprzscale; + + float zpos = (float)(spr->z + sprext->position_offset.z); + float zscale = ((spr->cstat & CSTAT_SPRITE_YFLIP) && (::sprite[spr->owner].cstat & CSTAT_SPRITE_ALIGNMENT) != 0) ? -4.f : 4.f; + zpos -= (spr->yoffset * spr->yrepeat) * zscale * voxel->bscale; + + x = (spr->x + sprext->position_offset.x) * (1 / 16.f); + z = zpos * (1 / -256.f); + y = (spr->y + sprext->position_offset.y) * (1 / -16.f); + + float zoff = voxel->siz.z * .5f; + if (!(spr->cstat & CSTAT_SPRITE_YCENTER)) + zoff += voxel->piv.z; + else if ((spr->cstat & CSTAT_SPRITE_ALIGNMENT) != CSTAT_SPRITE_ALIGNMENT_SLAB) + { + zoff += voxel->piv.z; + zoff -= voxel->siz.z * .5f; + } + if (spr->cstat & CSTAT_SPRITE_YFLIP) zoff = voxel->siz.z - zoff; + + rotmat.loadIdentity(); + rotmat.translate(x + translatevec.X, z - translatevec.Z, y - translatevec.Y); + rotmat.rotate(buildang(spr->ang).asdeg() - 90.f, 0, 1, 0); + rotmat.scale(scalevec.X, scalevec.Z, scalevec.Y); + // Apply pivot last + rotmat.translate(-voxel->piv.x, zoff, voxel->piv.y); + + + + auto vp = di->Viewpoint; + depth = (float)((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin); + PutSprite(di, alpha < 1.f - FLT_EPSILON); + rendered_sprites++; + return true; +} diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index 23686eaa2..dc44c5e37 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -49,7 +49,7 @@ #include "hw_renderstate.h" #include "hw_cvars.h" #include "gamestruct.h" -#include "gl_models.h" +#include "hw_models.h" #include "gamefuncs.h" CVARD(Bool, hw_hightile, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "enable/disable hightile texture rendering") @@ -136,7 +136,7 @@ void GLInstance::DoDraw() state.SetDepthFunc(DF_LEqual); state.EnableTexture(true); rs.model->BuildVertexBuffer(&mr); - mr.SetupFrame(rs.model, rs.mframes[0], rs.mframes[1], rs.mfactor); + mr.SetupFrame(rs.model, rs.mframes[0], rs.mframes[1], 0); rs.model->RenderFrame(&mr, rs.mMaterial.mTexture, rs.mframes[0], rs.mframes[1], 0.f, rs.mMaterial.mTranslation); state.SetDepthFunc(DF_Less); state.SetVertexBuffer(screen->mVertexData);