mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-15 00:41:55 +00:00
- flat sprite rendering!
This commit is contained in:
parent
fd0e9824b6
commit
1dfb2672a8
14 changed files with 574 additions and 72 deletions
|
@ -1076,6 +1076,7 @@ set (PCH_SOURCES
|
|||
core/rendering/scene/hw_clipper.cpp
|
||||
core/rendering/scene/hw_walls.cpp
|
||||
core/rendering/scene/hw_flats.cpp
|
||||
core/rendering/scene/hw_sprites.cpp
|
||||
core/rendering/scene/hw_drawlistadd.cpp
|
||||
core/rendering/scene/hw_drawlist.cpp
|
||||
core/rendering/scene/hw_drawinfo.cpp
|
||||
|
|
|
@ -3329,6 +3329,7 @@ EXTERN_CVAR(Int, gl_fogmode)
|
|||
int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz,
|
||||
fixed_t daang, fixed_t dahoriz, int16_t dacursectnum)
|
||||
{
|
||||
spritesortcnt = 0;
|
||||
checkRotatedWalls();
|
||||
|
||||
if (gl_fogmode == 1) gl_fogmode = 2; // only radial fog works with Build's screwed up coordinate system.
|
||||
|
|
|
@ -618,7 +618,7 @@ void renderDrawMapView(int cposx, int cposy, int czoom, int cang)
|
|||
{
|
||||
auto spr = &sprite[sn];
|
||||
vec2_t pp[4];
|
||||
GetFlatSpritePosition(spr, spr->pos.vec2, pp);
|
||||
GetFlatSpritePosition(spr, spr->pos.vec2, pp, true);
|
||||
|
||||
for (unsigned j = 0; j < 4; j++)
|
||||
{
|
||||
|
|
|
@ -231,11 +231,21 @@ void GetWallSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void GetFlatSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out)
|
||||
void GetFlatSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool render)
|
||||
{
|
||||
auto tex = tileGetTexture(spr->picnum);
|
||||
int width = tex->GetTexelWidth() * spr->xrepeat;
|
||||
int height = tex->GetTexelHeight() * spr->yrepeat;
|
||||
|
||||
int width, height;
|
||||
if (render && hw_hightile && TileFiles.tiledata[spr->picnum].h_xsize)
|
||||
{
|
||||
width = TileFiles.tiledata[spr->picnum].h_xsize * spr->xrepeat;
|
||||
height = TileFiles.tiledata[spr->picnum].h_ysize * spr->yrepeat;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = tex->GetTexelWidth() * spr->xrepeat;
|
||||
height = tex->GetTexelHeight() * spr->yrepeat;
|
||||
}
|
||||
int leftofs = (tex->GetTexelLeftOffset() + spr->xoffset) * spr->xrepeat;
|
||||
int topofs = (tex->GetTexelTopOffset() + spr->yoffset) * spr->yrepeat;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ bool spriteIsModelOrVoxel(const spritetype* tspr);
|
|||
void PlanesAtPoint(const sectortype* sec, float dax, float day, float* ceilz, float* florz);
|
||||
void setWallSectors();
|
||||
void GetWallSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out);
|
||||
void GetFlatSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out);
|
||||
void GetFlatSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out, bool render = false);
|
||||
void checkRotatedWalls();
|
||||
|
||||
// y is negated so that the orientation is the same as in GZDoom, in order to use its utilities.
|
||||
|
|
|
@ -283,6 +283,84 @@ HWDecal* HWDrawInfo::AddDecal(bool onmirror)
|
|||
#endif
|
||||
}
|
||||
|
||||
void HWDrawInfo::DispatchSprites()
|
||||
{
|
||||
for (int i = 0; i < spritesortcnt; i++)
|
||||
{
|
||||
auto tspr = &tsprite[i];
|
||||
int tilenum = tspr->picnum;
|
||||
int spritenum = tspr->owner;
|
||||
|
||||
if (spritenum < 0 || (unsigned)tilenum >= MAXTILES)
|
||||
continue;
|
||||
|
||||
setgotpic(tilenum);
|
||||
|
||||
if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT) != CSTAT_SPRITE_ALIGNMENT_SLAB)
|
||||
tileUpdatePicnum(&tilenum, spritenum + 32768, 0);
|
||||
|
||||
|
||||
while (!(spriteext[spritenum].flags & SPREXT_NOTMD))
|
||||
{
|
||||
int pt = Ptile2tile(tspr->picnum, tspr->pal);
|
||||
if (hw_models && tile2model[pt].modelid >= 0 && tile2model[pt].framenum >= 0)
|
||||
{
|
||||
//HWSprite hwsprite;
|
||||
//if (hwsprite.ProcessModel(pt, tspr)) return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r_voxels)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (spriteext[spritenum].flags & SPREXT_AWAY1)
|
||||
{
|
||||
tspr->pos.x += bcos(tspr->ang, -13);
|
||||
tspr->pos.y += bsin(tspr->ang, -13);
|
||||
}
|
||||
else if (spriteext[spritenum].flags & SPREXT_AWAY2)
|
||||
{
|
||||
tspr->pos.x -= bcos(tspr->ang, -13);
|
||||
tspr->pos.y -= bsin(tspr->ang, -13);
|
||||
}
|
||||
|
||||
switch (tspr->cstat & CSTAT_SPRITE_ALIGNMENT)
|
||||
{
|
||||
case CSTAT_SPRITE_ALIGNMENT_FACING:
|
||||
// face sprite
|
||||
break;
|
||||
|
||||
case CSTAT_SPRITE_ALIGNMENT_WALL:
|
||||
// wall sprite
|
||||
break;
|
||||
|
||||
case CSTAT_SPRITE_ALIGNMENT_FLOOR:
|
||||
{
|
||||
HWFlat flat;
|
||||
flat.ProcessFlatSprite(this, tspr, §or[tspr->sectnum]);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// CreateScene
|
||||
|
@ -318,6 +396,7 @@ void HWDrawInfo::CreateScene()
|
|||
|
||||
SetupSprite.Clock();
|
||||
gi->processSprites(view.x, view.y, vp.Pos.Z * -256, bamang(vp.RotAngle), vp.TicFrac * 65536);
|
||||
DispatchSprites();
|
||||
SetupSprite.Unclock();
|
||||
|
||||
screen->mLights->Unmap();
|
||||
|
@ -345,14 +424,6 @@ void HWDrawInfo::RenderScene(FRenderState &state)
|
|||
state.EnableFog(true);
|
||||
state.SetRenderStyle(STYLE_Source);
|
||||
|
||||
if (gl_sort_textures)
|
||||
{
|
||||
drawlists[GLDL_PLAINWALLS].SortWalls();
|
||||
drawlists[GLDL_PLAINFLATS].SortFlats();
|
||||
drawlists[GLDL_MASKEDWALLS].SortWalls();
|
||||
drawlists[GLDL_MASKEDFLATS].SortFlats();
|
||||
drawlists[GLDL_MASKEDWALLSOFS].SortWalls();
|
||||
}
|
||||
|
||||
// Part 1: solid geometry. This is set up so that there are no transparent parts
|
||||
state.SetDepthFunc(DF_Less);
|
||||
|
@ -362,21 +433,35 @@ void HWDrawInfo::RenderScene(FRenderState &state)
|
|||
state.EnableTexture(gl_texture);
|
||||
state.EnableBrightmap(true);
|
||||
drawlists[GLDL_PLAINWALLS].DrawWalls(this, state, false);
|
||||
|
||||
drawlists[GLDL_PLAINFLATS].DrawFlats(this, state, false);
|
||||
|
||||
|
||||
// Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show
|
||||
state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
|
||||
drawlists[GLDL_MASKEDWALLS].DrawWalls(this, state, false);
|
||||
drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false);
|
||||
|
||||
// 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 (drawlists[GLDL_MASKEDWALLSOFS].Size() > 0)
|
||||
{
|
||||
state.SetDepthBias(-1, -128);
|
||||
drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(this, state, false);
|
||||
state.ClearDepthBias();
|
||||
}
|
||||
// This list is masked, non-translucent walls.
|
||||
drawlists[GLDL_MASKEDWALLS].DrawWalls(this, state, false);
|
||||
|
||||
// These lists must be drawn in two passes for color and depth to avoid depth fighting with overlapping entries
|
||||
drawlists[GLDL_MASKEDFLATS].SortFlats(this);
|
||||
//drawlists[GLDL_MASKEDWALLSV].SortWalls(this);
|
||||
//drawlists[GLDL_MASKEDWALLSH].SortWalls(this);
|
||||
|
||||
// these lists are only wall and floor sprites - often attached to walls and floors - so they need to be offset from the plane they may be attached to.
|
||||
drawlists[GLDL_MASKEDWALLSS].DrawWalls(this, state, false);
|
||||
state.SetDepthBias(-1, -128);
|
||||
state.SetDepthMask(false);
|
||||
drawlists[GLDL_MASKEDWALLSV].DrawWalls(this, state, false);
|
||||
drawlists[GLDL_MASKEDWALLSH].DrawWalls(this, state, false);
|
||||
drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false);
|
||||
state.SetDepthMask(true);
|
||||
state.SetColorMask(false);
|
||||
drawlists[GLDL_MASKEDWALLSV].DrawWalls(this, state, false);
|
||||
drawlists[GLDL_MASKEDWALLSH].DrawWalls(this, state, false);
|
||||
drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false);
|
||||
state.SetColorMask(true);
|
||||
state.ClearDepthBias();
|
||||
|
||||
drawlists[GLDL_MODELS].Draw(this, state, false);
|
||||
|
||||
|
|
|
@ -72,6 +72,9 @@ enum DrawListType
|
|||
GLDL_PLAINWALLS,
|
||||
GLDL_PLAINFLATS,
|
||||
GLDL_MASKEDWALLS,
|
||||
GLDL_MASKEDWALLSS, // arbitrary wall sprites.
|
||||
GLDL_MASKEDWALLSV, // vertical wall sprites
|
||||
GLDL_MASKEDWALLSH, // horizontal wall sprites. These two lists merely exist for easier sorting.
|
||||
GLDL_MASKEDFLATS,
|
||||
GLDL_MASKEDWALLSOFS,
|
||||
GLDL_MODELS,
|
||||
|
@ -154,6 +157,7 @@ public:
|
|||
|
||||
void DrawScene(int drawmode);
|
||||
void CreateScene();
|
||||
void DispatchSprites();
|
||||
void RenderScene(FRenderState &state);
|
||||
void RenderTranslucent(FRenderState &state);
|
||||
void RenderPortal(HWPortal *p, FRenderState &state, bool usestencil);
|
||||
|
|
|
@ -330,7 +330,7 @@ void HWDrawList::SortSpriteIntoPlane(SortNode * head, SortNode * sort)
|
|||
auto hiz = ss->z1 > ss->z2 ? ss->z1 : ss->z2;
|
||||
auto loz = ss->z1 < ss->z2 ? ss->z1 : ss->z2;
|
||||
|
||||
if ((hiz > fh->z && loz < fh->z) || ss->modelframe)
|
||||
if ((hiz > fh->z && loz < fh->z))// || ss->modelframe)
|
||||
{
|
||||
// We have to split this sprite
|
||||
HWSprite *s = NewSprite();
|
||||
|
@ -723,16 +723,44 @@ void HWDrawList::SortWalls()
|
|||
}
|
||||
}
|
||||
|
||||
void HWDrawList::SortFlats()
|
||||
void HWDrawList::SortFlats(HWDrawInfo* di)
|
||||
{
|
||||
auto viewz = di->Viewpoint.Pos.Z;
|
||||
if (drawitems.Size() > 1)
|
||||
{
|
||||
std::sort(drawitems.begin(), drawitems.end(), [=](const HWDrawItem &a, const HWDrawItem &b)
|
||||
TArray<HWDrawItem> list1(drawitems.Size(), false);
|
||||
TArray<HWDrawItem> list2(drawitems.Size(), false);
|
||||
|
||||
for (auto& item : drawitems)
|
||||
{
|
||||
HWFlat * w1 = flats[a.index];
|
||||
HWFlat* w1 = flats[item.index];
|
||||
if (w1->z < viewz) list1.Push(item);
|
||||
else list2.Push(item);
|
||||
}
|
||||
|
||||
std::sort(list1.begin(), list1.end(), [=](const HWDrawItem &a, const HWDrawItem &b)
|
||||
{
|
||||
HWFlat* w1 = flats[a.index];
|
||||
HWFlat* w2 = flats[b.index];
|
||||
return w1->texture < w2->texture;
|
||||
if (w1->z != w2->z) return w1->z < w2->z;
|
||||
int time1 = w1->sprite ? w1->sprite->time : -1;
|
||||
int time2 = w2->sprite ? w2->sprite->time : -1;
|
||||
return time1 < time2;
|
||||
});
|
||||
|
||||
std::sort(list2.begin(), list2.end(), [=](const HWDrawItem& a, const HWDrawItem& b)
|
||||
{
|
||||
HWFlat* w1 = flats[a.index];
|
||||
HWFlat* w2 = flats[b.index];
|
||||
if (w1->z != w2->z) return w2->z < w1->z;
|
||||
int time1 = w1->sprite ? w1->sprite->time : -1;
|
||||
int time2 = w2->sprite ? w2->sprite->time : -1;
|
||||
return time1 < time2;
|
||||
});
|
||||
|
||||
drawitems.Clear();
|
||||
drawitems.Append(list1);
|
||||
drawitems.Append(list2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ struct HWDrawItem
|
|||
HWDrawItemType rendertype;
|
||||
int index;
|
||||
|
||||
HWDrawItem() = default; // we need this for dynamic arrays.
|
||||
HWDrawItem(HWDrawItemType _rendertype,int _index) : rendertype(_rendertype),index(_index) {}
|
||||
};
|
||||
|
||||
|
@ -92,7 +93,7 @@ public:
|
|||
HWSprite *NewSprite();
|
||||
void Reset();
|
||||
void SortWalls();
|
||||
void SortFlats();
|
||||
void SortFlats(HWDrawInfo* di);
|
||||
|
||||
|
||||
void MakeSortList();
|
||||
|
|
|
@ -106,33 +106,17 @@ void HWDrawInfo::AddMirrorSurface(HWWall *w)
|
|||
|
||||
void HWDrawInfo::AddFlat(HWFlat *flat)
|
||||
{
|
||||
int list = GLDL_PLAINFLATS;
|
||||
int list;;
|
||||
|
||||
#if 0
|
||||
if (flat->renderstyle != STYLE_Translucent || flat->alpha < 1.f - FLT_EPSILON)
|
||||
if (flat->RenderStyle != LegacyRenderStyles[STYLE_Translucent] || flat->alpha < 1.f - FLT_EPSILON) // flat->texture->GetTranslucency() - fixme
|
||||
{
|
||||
// translucent portals go into the translucent border list.
|
||||
list = GLDL_TRANSLUCENTBORDER;
|
||||
list = flat->sprite? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER;
|
||||
}
|
||||
else if (flat->texture->GetTranslucency())
|
||||
else
|
||||
{
|
||||
/*
|
||||
if (flat->stack)
|
||||
{
|
||||
list = GLDL_TRANSLUCENTBORDER;
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
list = GLDL_PLAINFLATS;
|
||||
}
|
||||
list = flat->sprite ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS;
|
||||
}
|
||||
else //if (flat->hacktype != SSRF_FLOODHACK) // The flood hack may later need different treatment but with the current setup can go into the existing render list.
|
||||
{
|
||||
bool masked = flat->texture->isMasked() && flat->stack;
|
||||
list = masked ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS;
|
||||
}
|
||||
#endif
|
||||
auto newflat = drawlists[list].NewFlat();
|
||||
*newflat = *flat;
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ public:
|
|||
texcoord tcs[4];
|
||||
float alpha;
|
||||
|
||||
ERenderStyle RenderStyle;
|
||||
FRenderStyle RenderStyle;
|
||||
|
||||
float ViewDistance;
|
||||
float visibility;
|
||||
|
@ -181,8 +181,9 @@ public:
|
|||
unsigned int vertcount;
|
||||
|
||||
public:
|
||||
walltype * seg;
|
||||
sectortype *frontsector, *backsector;
|
||||
walltype* seg;
|
||||
spritetype* sprite;
|
||||
sectortype* frontsector, * backsector;
|
||||
//private:
|
||||
|
||||
void PutWall(HWDrawInfo *di, bool translucent);
|
||||
|
@ -229,6 +230,7 @@ public:
|
|||
|
||||
public:
|
||||
void Process(HWDrawInfo* di, walltype* seg, sectortype* frontsector, sectortype* backsector);
|
||||
void ProcessWallSprite(HWDrawInfo* di, walltype* seg, sectortype* frontsector, sectortype* backsector);
|
||||
|
||||
float PointOnSide(float x,float y)
|
||||
{
|
||||
|
@ -249,15 +251,16 @@ class HWFlat
|
|||
{
|
||||
public:
|
||||
sectortype * sec;
|
||||
spritetype* sprite; // for flat sprites.
|
||||
FGameTexture *texture;
|
||||
|
||||
float z; // the z position of the flat (only valid for non-sloped planes)
|
||||
FColormap Colormap; // light and fog
|
||||
ERenderStyle renderstyle;
|
||||
|
||||
PalEntry fade;
|
||||
int shade, palette, visibility;
|
||||
float alpha;
|
||||
FRenderStyle RenderStyle;
|
||||
int iboindex;
|
||||
//int vboheight;
|
||||
|
||||
|
@ -272,6 +275,7 @@ public:
|
|||
|
||||
void PutFlat(HWDrawInfo* di, int whichplane);
|
||||
void ProcessSector(HWDrawInfo *di, sectortype * frontsector, int which = 7 /*SSRF_RENDERALL*/); // cannot use constant due to circular dependencies.
|
||||
void ProcessFlatSprite(HWDrawInfo* di, spritetype* sprite, sectortype* sector);
|
||||
|
||||
void DrawSubsectors(HWDrawInfo *di, FRenderState &state);
|
||||
void DrawFlat(HWDrawInfo* di, FRenderState& state, bool translucent);
|
||||
|
@ -293,7 +297,7 @@ public:
|
|||
bool fullbright;
|
||||
bool polyoffset;
|
||||
FColormap Colormap;
|
||||
FSpriteModelFrame * modelframe;
|
||||
int modeltype;
|
||||
FRenderStyle RenderStyle;
|
||||
int OverrideShader;
|
||||
|
||||
|
|
|
@ -97,20 +97,44 @@ void HWFlat::SetupLights(HWDrawInfo *di, FLightNode * node, FDynLightData &light
|
|||
|
||||
void HWFlat::MakeVertices()
|
||||
{
|
||||
auto mesh = sectorGeometry.get(sec - sector, plane);
|
||||
if (!mesh) return;
|
||||
auto ret = screen->mVertexData->AllocVertices(mesh->vertices.Size());
|
||||
auto vp = ret.first;
|
||||
for (unsigned i = 0; i < mesh->vertices.Size(); i++)
|
||||
if (vertcount > 0) return;
|
||||
if (sprite == nullptr)
|
||||
{
|
||||
auto& pt = mesh->vertices[i];
|
||||
auto& uv = mesh->texcoords[i];
|
||||
vp->SetVertex(pt.X, pt.Z, pt.Y);
|
||||
vp->SetTexCoord(uv.X, uv.Y);
|
||||
vp++;
|
||||
auto mesh = sectorGeometry.get(sec - sector, plane);
|
||||
if (!mesh) return;
|
||||
auto ret = screen->mVertexData->AllocVertices(mesh->vertices.Size());
|
||||
auto vp = ret.first;
|
||||
for (unsigned i = 0; i < mesh->vertices.Size(); i++)
|
||||
{
|
||||
auto& pt = mesh->vertices[i];
|
||||
auto& uv = mesh->texcoords[i];
|
||||
vp->SetVertex(pt.X, pt.Z, pt.Y);
|
||||
vp->SetTexCoord(uv.X, uv.Y);
|
||||
vp++;
|
||||
}
|
||||
vertindex = ret.second;
|
||||
vertcount = mesh->vertices.Size();
|
||||
}
|
||||
else
|
||||
{
|
||||
vec2_t pos[4];
|
||||
GetFlatSpritePosition(sprite, sprite->pos.vec2, pos, true);
|
||||
|
||||
auto ret = screen->mVertexData->AllocVertices(6);
|
||||
auto vp = ret.first;
|
||||
float x = !(sprite->cstat & CSTAT_SECTOR_XFLIP) ? 0.f : 1.f;
|
||||
float y = !(sprite->cstat & CSTAT_SECTOR_YFLIP) ? 0.f : 1.f;
|
||||
for (unsigned i = 0; i < 6; i++)
|
||||
{
|
||||
const static unsigned indices[] = { 0, 1, 2, 0, 2, 3 };
|
||||
int j = indices[i];
|
||||
vp->SetVertex(pos[j].x * (1 / 16.f), z, pos[j].y * (1 / -16.f));
|
||||
vp->SetTexCoord(j == 1 || j == 2 ? 1.f - x : x, j == 2 || j == 3 ? 1.f - x : x);
|
||||
vp++;
|
||||
}
|
||||
vertindex = ret.second;
|
||||
vertcount = 6;
|
||||
}
|
||||
vertindex = ret.second;
|
||||
vertcount = mesh->vertices.Size();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -132,8 +156,16 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent)
|
|||
}
|
||||
#endif
|
||||
|
||||
auto mesh = sectorGeometry.get(sec - sector, plane);
|
||||
state.SetNormal(mesh->normal);
|
||||
if (!sprite)
|
||||
{
|
||||
auto mesh = sectorGeometry.get(sec - sector, plane);
|
||||
state.SetNormal(mesh->normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (z < di->Viewpoint.Pos.Z) state.SetNormal({ 0,1,0 });
|
||||
else state.SetNormal({ 0, -1, 0 });
|
||||
}
|
||||
|
||||
// Fog must be done before the texture so that the texture selector can override it.
|
||||
bool foggy = (GlobalMapFog || (fade & 0xffffff));
|
||||
|
@ -160,7 +192,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent)
|
|||
|
||||
if (translucent)
|
||||
{
|
||||
state.SetRenderStyle(renderstyle);
|
||||
state.SetRenderStyle(RenderStyle);
|
||||
if (!texture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
|
||||
else state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
}
|
||||
|
@ -186,6 +218,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent)
|
|||
|
||||
void HWFlat::PutFlat(HWDrawInfo *di, int whichplane)
|
||||
{
|
||||
vertcount = 0;
|
||||
plane = whichplane;
|
||||
if (!screen->BuffersArePersistent()) // should be made static buffer content later (when the logic is working)
|
||||
{
|
||||
|
@ -228,6 +261,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sectortype * frontsector, int which)
|
|||
fade = lookups.getFade(frontsector->floorpal); // fog is per sector.
|
||||
visibility = sectorVisibility(frontsector);
|
||||
sec = frontsector;
|
||||
sprite = nullptr;
|
||||
|
||||
//
|
||||
//
|
||||
|
@ -262,7 +296,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sectortype * frontsector, int which)
|
|||
if (texture && texture->isValid())
|
||||
{
|
||||
//iboindex = frontsector->iboindex[sector_t::floor];
|
||||
renderstyle = STYLE_Translucent;
|
||||
RenderStyle = STYLE_Translucent;
|
||||
PutFlat(di, 0);
|
||||
}
|
||||
}
|
||||
|
@ -303,10 +337,45 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sectortype * frontsector, int which)
|
|||
if (texture && texture->isValid())
|
||||
{
|
||||
//iboindex = frontsector->iboindex[sector_t::floor];
|
||||
renderstyle = STYLE_Translucent;
|
||||
RenderStyle = STYLE_Translucent;
|
||||
PutFlat(di, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HWFlat::ProcessFlatSprite(HWDrawInfo* di, spritetype* sprite, sectortype* sector)
|
||||
{
|
||||
int tilenum = sprite->picnum;
|
||||
texture = tileGetTexture(tilenum);
|
||||
z = sprite->z * (1 / -256.f);
|
||||
if (z == di->Viewpoint.Pos.Z) return; // looking right at the edge.
|
||||
|
||||
visibility = sectorVisibility(§or[sprite->sectnum]);// *(4.f / 5.f); // The factor comes directly from Polymost. No idea why this uses a different visibility setting. Bad projection math?
|
||||
|
||||
// Weird Build logic that really makes no sense.
|
||||
if ((sprite->cstat & CSTAT_SPRITE_ONE_SIDED) != 0 && (di->Viewpoint.Pos.Z < z) == ((sprite->cstat & CSTAT_SPRITE_YFLIP) == 0))
|
||||
return;
|
||||
|
||||
if (texture && texture->isValid())
|
||||
{
|
||||
this->sprite = sprite;
|
||||
sec = sector;
|
||||
shade = sprite->shade;
|
||||
palette = sprite->pal;
|
||||
fade = lookups.getFade(sector[sprite->sectnum].floorpal); // fog is per sector.
|
||||
|
||||
bool trans = (sprite->cstat & CSTAT_SPRITE_TRANSLUCENT);
|
||||
if (trans)
|
||||
{
|
||||
RenderStyle = GetRenderStyle(0, !!(sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT));
|
||||
alpha = GetAlphaFromBlend((sprite->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||
alpha = 1.f;
|
||||
}
|
||||
PutFlat(di, 0);
|
||||
}
|
||||
}
|
||||
|
|
315
source/core/rendering/scene/hw_sprites.cpp
Normal file
315
source/core/rendering/scene/hw_sprites.cpp
Normal file
|
@ -0,0 +1,315 @@
|
|||
|
||||
#if 0
|
||||
void polymost_drawsprite(int32_t snum)
|
||||
{
|
||||
|
||||
vec2_t off = { 0, 0 };
|
||||
|
||||
if ((globalorientation & 48) != 48) // only non-voxel sprites should do this
|
||||
{
|
||||
int const flag = hw_hightile && TileFiles.tiledata[globalpicnum].h_xsize;
|
||||
off = { (int32_t)tspr->xoffset + (flag ? TileFiles.tiledata[globalpicnum].h_xoffs : tileLeftOffset(globalpicnum)),
|
||||
(int32_t)tspr->yoffset + (flag ? TileFiles.tiledata[globalpicnum].h_yoffs : tileTopOffset(globalpicnum)) };
|
||||
}
|
||||
|
||||
int32_t method = DAMETH_MASK | DAMETH_CLAMPED;
|
||||
|
||||
if (tspr->cstat & 2)
|
||||
method = DAMETH_CLAMPED | ((tspr->cstat & 512) ? DAMETH_TRANS2 : DAMETH_TRANS1);
|
||||
|
||||
SetRenderStyleFromBlend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512));
|
||||
|
||||
drawpoly_alpha = spriteext[spritenum].alpha;
|
||||
drawpoly_blend = tspr->blend;
|
||||
|
||||
sec = (usectorptr_t)§or[tspr->sectnum];
|
||||
|
||||
|
||||
vec3_t pos = tspr->pos;
|
||||
|
||||
|
||||
vec2_t tsiz;
|
||||
|
||||
if (hw_hightile && TileFiles.tiledata[globalpicnum].h_xsize)
|
||||
tsiz = { TileFiles.tiledata[globalpicnum].h_xsize, TileFiles.tiledata[globalpicnum].h_ysize };
|
||||
else
|
||||
tsiz = { tileWidth(globalpicnum), tileHeight(globalpicnum) };
|
||||
|
||||
if (tsiz.x <= 0 || tsiz.y <= 0)
|
||||
return;
|
||||
|
||||
vec2f_t const ftsiz = { (float) tsiz.x, (float) tsiz.y };
|
||||
|
||||
switch ((globalorientation >> 4) & 3)
|
||||
{
|
||||
case 0: // Face sprite
|
||||
{
|
||||
// Project 3D to 2D
|
||||
if (globalorientation & 4)
|
||||
off.x = -off.x;
|
||||
// NOTE: yoff not negated not for y flipping, unlike wall and floor
|
||||
// aligned sprites.
|
||||
|
||||
int const ang = (getangle(tspr->x - globalposx, tspr->y - globalposy) + 1024) & 2047;
|
||||
|
||||
float foffs = TSPR_OFFSET(tspr);
|
||||
float foffs2 = TSPR_OFFSET(tspr);
|
||||
if (fabs(foffs2) < fabs(foffs)) foffs = foffs2;
|
||||
|
||||
vec2f_t const offs = { float(bcosf(ang, -6) * foffs), float(bsinf(ang, -6) * foffs) };
|
||||
|
||||
vec2f_t s0 = { (float)(tspr->x - globalposx) + offs.x,
|
||||
(float)(tspr->y - globalposy) + offs.y};
|
||||
|
||||
vec2f_t p0 = { s0.y * gcosang - s0.x * gsinang, s0.x * gcosang2 + s0.y * gsinang2 };
|
||||
|
||||
if (p0.y <= SCISDIST)
|
||||
goto _drawsprite_return;
|
||||
|
||||
float const ryp0 = 1.f / p0.y;
|
||||
s0 = { ghalfx * p0.x * ryp0 + ghalfx, ((float)(pos.z - globalposz)) * gyxscale * ryp0 + ghoriz };
|
||||
|
||||
float const f = ryp0 * fxdimen * (1.0f / 160.f);
|
||||
|
||||
vec2f_t ff = { ((float)tspr->xrepeat) * f,
|
||||
((float)tspr->yrepeat) * f * ((float)yxaspect * (1.0f / 65536.f)) };
|
||||
|
||||
if (tsiz.x & 1)
|
||||
s0.x += ff.x * 0.5f;
|
||||
if (globalorientation & 128 && tsiz.y & 1)
|
||||
s0.y += ff.y * 0.5f;
|
||||
|
||||
s0.x -= ff.x * (float) off.x;
|
||||
s0.y -= ff.y * (float) off.y;
|
||||
|
||||
ff.x *= ftsiz.x;
|
||||
ff.y *= ftsiz.y;
|
||||
|
||||
vec2f_t pxy[4];
|
||||
|
||||
pxy[0].x = pxy[3].x = s0.x - ff.x * 0.5f;
|
||||
pxy[1].x = pxy[2].x = s0.x + ff.x * 0.5f;
|
||||
if (!(globalorientation & 128))
|
||||
{
|
||||
pxy[0].y = pxy[1].y = s0.y - ff.y;
|
||||
pxy[2].y = pxy[3].y = s0.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxy[0].y = pxy[1].y = s0.y - ff.y * 0.5f;
|
||||
pxy[2].y = pxy[3].y = s0.y + ff.y * 0.5f;
|
||||
}
|
||||
|
||||
xtex.d = ytex.d = ytex.u = xtex.v = 0;
|
||||
otex.d = ryp0 * gviewxrange;
|
||||
|
||||
if (!(globalorientation & 4))
|
||||
{
|
||||
xtex.u = ftsiz.x * otex.d / (pxy[1].x - pxy[0].x + .002f);
|
||||
otex.u = -xtex.u * (pxy[0].x - .001f);
|
||||
}
|
||||
else
|
||||
{
|
||||
xtex.u = ftsiz.x * otex.d / (pxy[0].x - pxy[1].x - .002f);
|
||||
otex.u = -xtex.u * (pxy[1].x + .001f);
|
||||
}
|
||||
|
||||
if (!(globalorientation & 8))
|
||||
{
|
||||
ytex.v = ftsiz.y * otex.d / (pxy[3].y - pxy[0].y + .002f);
|
||||
otex.v = -ytex.v * (pxy[0].y - .001f);
|
||||
}
|
||||
else
|
||||
{
|
||||
ytex.v = ftsiz.y * otex.d / (pxy[0].y - pxy[3].y - .002f);
|
||||
otex.v = -ytex.v * (pxy[3].y + .001f);
|
||||
}
|
||||
|
||||
// Clip sprites to ceilings/floors when no parallaxing and not sloped
|
||||
if (!(sector[tspr->sectnum].ceilingstat & 3))
|
||||
{
|
||||
s0.y = ((float) (sector[tspr->sectnum].ceilingz - globalposz)) * gyxscale * ryp0 + ghoriz;
|
||||
if (pxy[0].y < s0.y)
|
||||
pxy[0].y = pxy[1].y = s0.y;
|
||||
}
|
||||
|
||||
if (!(sector[tspr->sectnum].floorstat & 3))
|
||||
{
|
||||
s0.y = ((float) (sector[tspr->sectnum].floorz - globalposz)) * gyxscale * ryp0 + ghoriz;
|
||||
if (pxy[2].y > s0.y)
|
||||
pxy[2].y = pxy[3].y = s0.y;
|
||||
}
|
||||
|
||||
vec2_16_t tempsiz = { (int16_t)tsiz.x, (int16_t)tsiz.y };
|
||||
pow2xsplit = 0;
|
||||
polymost_drawpoly(pxy, 4, method, tempsiz);
|
||||
|
||||
drawpoly_srepeat = 0;
|
||||
drawpoly_trepeat = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // Wall sprite
|
||||
{
|
||||
// Project 3D to 2D
|
||||
if (globalorientation & 4)
|
||||
off.x = -off.x;
|
||||
|
||||
if (globalorientation & 8)
|
||||
off.y = -off.y;
|
||||
|
||||
vec2f_t const extent = { float(tspr->xrepeat * bsinf(tspr->ang, -16)),
|
||||
float(tspr->xrepeat * -bcosf(tspr->ang, -16)) };
|
||||
|
||||
float f = (float)(tsiz.x >> 1) + (float)off.x;
|
||||
|
||||
vec2f_t const vf = { extent.x * f, extent.y * f };
|
||||
|
||||
vec2f_t vec0 = { (float)(pos.x - globalposx) - vf.x,
|
||||
(float)(pos.y - globalposy) - vf.y };
|
||||
|
||||
int32_t const s = tspr->owner;
|
||||
int32_t walldist = 1;
|
||||
int32_t w = (s == -1) ? -1 : wsprinfo[s].wall;
|
||||
|
||||
vec2f_t p0 = { vec0.y * gcosang - vec0.x * gsinang,
|
||||
vec0.x * gcosang2 + vec0.y * gsinang2 };
|
||||
|
||||
vec2f_t const pp = { extent.x * ftsiz.x + vec0.x,
|
||||
extent.y * ftsiz.x + vec0.y };
|
||||
|
||||
vec2f_t p1 = { pp.y * gcosang - pp.x * gsinang,
|
||||
pp.x * gcosang2 + pp.y * gsinang2 };
|
||||
|
||||
if ((p0.y <= SCISDIST) && (p1.y <= SCISDIST))
|
||||
goto _drawsprite_return;
|
||||
|
||||
// Clip to close parallel-screen plane
|
||||
vec2f_t const op0 = p0;
|
||||
|
||||
float t0 = 0.f, t1 = 1.f;
|
||||
|
||||
if (p0.y < SCISDIST)
|
||||
{
|
||||
t0 = (SCISDIST - p0.y) / (p1.y - p0.y);
|
||||
p0 = { (p1.x - p0.x) * t0 + p0.x, SCISDIST };
|
||||
}
|
||||
|
||||
if (p1.y < SCISDIST)
|
||||
{
|
||||
t1 = (SCISDIST - op0.y) / (p1.y - op0.y);
|
||||
p1 = { (p1.x - op0.x) * t1 + op0.x, SCISDIST };
|
||||
}
|
||||
|
||||
f = 1.f / p0.y;
|
||||
const float ryp0 = f * gyxscale;
|
||||
float sx0 = ghalfx * p0.x * f + ghalfx;
|
||||
|
||||
f = 1.f / p1.y;
|
||||
const float ryp1 = f * gyxscale;
|
||||
float sx1 = ghalfx * p1.x * f + ghalfx;
|
||||
|
||||
pos.z -= ((off.y * tspr->yrepeat) << 2);
|
||||
|
||||
if (globalorientation & 128)
|
||||
{
|
||||
pos.z += ((tsiz.y * tspr->yrepeat) << 1);
|
||||
|
||||
if (tsiz.y & 1)
|
||||
pos.z += (tspr->yrepeat << 1); // Odd yspans
|
||||
}
|
||||
|
||||
xtex.d = (ryp0 - ryp1) * gxyaspect / (sx0 - sx1);
|
||||
ytex.d = 0;
|
||||
otex.d = ryp0 * gxyaspect - xtex.d * sx0;
|
||||
|
||||
if (globalorientation & 4)
|
||||
{
|
||||
t0 = 1.f - t0;
|
||||
t1 = 1.f - t1;
|
||||
}
|
||||
|
||||
xtex.u = (t0 * ryp0 - t1 * ryp1) * gxyaspect * ftsiz.x / (sx0 - sx1);
|
||||
ytex.u = 0;
|
||||
otex.u = t0 * ryp0 * gxyaspect * ftsiz.x - xtex.u * sx0;
|
||||
|
||||
f = ((float) tspr->yrepeat) * ftsiz.y * 4;
|
||||
|
||||
float sc0 = ((float) (pos.z - globalposz - f)) * ryp0 + ghoriz;
|
||||
float sc1 = ((float) (pos.z - globalposz - f)) * ryp1 + ghoriz;
|
||||
float sf0 = ((float) (pos.z - globalposz)) * ryp0 + ghoriz;
|
||||
float sf1 = ((float) (pos.z - globalposz)) * ryp1 + ghoriz;
|
||||
|
||||
// gvx*sx0 + gvy*sc0 + gvo = 0
|
||||
// gvx*sx1 + gvy*sc1 + gvo = 0
|
||||
// gvx*sx0 + gvy*sf0 + gvo = tsizy*(gdx*sx0 + gdo)
|
||||
f = ftsiz.y * (xtex.d * sx0 + otex.d) / ((sx0 - sx1) * (sc0 - sf0));
|
||||
|
||||
if (!(globalorientation & 8))
|
||||
{
|
||||
xtex.v = (sc0 - sc1) * f;
|
||||
ytex.v = (sx1 - sx0) * f;
|
||||
otex.v = -xtex.v * sx0 - ytex.v * sc0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xtex.v = (sf1 - sf0) * f;
|
||||
ytex.v = (sx0 - sx1) * f;
|
||||
otex.v = -xtex.v * sx0 - ytex.v * sf0;
|
||||
}
|
||||
|
||||
// Clip sprites to ceilings/floors when no parallaxing
|
||||
if (!(sector[tspr->sectnum].ceilingstat & 1))
|
||||
{
|
||||
if (sector[tspr->sectnum].ceilingz > pos.z - (float)((tspr->yrepeat * tsiz.y) << 2))
|
||||
{
|
||||
sc0 = (float)(sector[tspr->sectnum].ceilingz - globalposz) * ryp0 + ghoriz;
|
||||
sc1 = (float)(sector[tspr->sectnum].ceilingz - globalposz) * ryp1 + ghoriz;
|
||||
}
|
||||
}
|
||||
if (!(sector[tspr->sectnum].floorstat & 1))
|
||||
{
|
||||
if (sector[tspr->sectnum].floorz < pos.z)
|
||||
{
|
||||
sf0 = (float)(sector[tspr->sectnum].floorz - globalposz) * ryp0 + ghoriz;
|
||||
sf1 = (float)(sector[tspr->sectnum].floorz - globalposz) * ryp1 + ghoriz;
|
||||
}
|
||||
}
|
||||
|
||||
if (sx0 > sx1)
|
||||
{
|
||||
if (globalorientation & 64)
|
||||
goto _drawsprite_return; // 1-sided sprite
|
||||
|
||||
std::swap(sx0, sx1);
|
||||
std::swap(sc0, sc1);
|
||||
std::swap(sf0, sf1);
|
||||
}
|
||||
|
||||
vec2f_t const pxy[4] = { { sx0, sc0 }, { sx1, sc1 }, { sx1, sf1 }, { sx0, sf0 } };
|
||||
|
||||
vec2_16_t tempsiz = { (int16_t)tsiz.x, (int16_t)tsiz.y };
|
||||
pow2xsplit = 0;
|
||||
polymost_drawpoly(pxy, 4, method, tempsiz);
|
||||
|
||||
drawpoly_srepeat = 0;
|
||||
drawpoly_trepeat = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Floor sprite
|
||||
else
|
||||
|
||||
break;
|
||||
|
||||
case 3: // Voxel sprite
|
||||
break;
|
||||
}
|
||||
|
||||
if (automapping == 1 && (unsigned)spritenum < MAXSPRITES)
|
||||
show2dsprite.Set(spritenum);
|
||||
|
||||
_drawsprite_return:
|
||||
;
|
||||
}
|
||||
#endif
|
|
@ -766,7 +766,7 @@ void HWWall::DoTexture(HWDrawInfo* di, walltype* wal, walltype* refwall, float r
|
|||
bool trans = type == RENDERWALL_M2S && (wal->cstat & CSTAT_WALL_TRANSLUCENT);
|
||||
if (trans)
|
||||
{
|
||||
SetRenderStyleFromBlend(!!(wal->cstat & CSTAT_WALL_TRANSLUCENT), 0, !!(wal->cstat & CSTAT_WALL_TRANS_FLIP));
|
||||
RenderStyle = GetRenderStyle(0, !!(wal->cstat & CSTAT_WALL_TRANS_FLIP));
|
||||
alpha = GetAlphaFromBlend((wal->cstat & CSTAT_WALL_TRANS_FLIP) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0);
|
||||
}
|
||||
PutWall(di, trans);
|
||||
|
|
Loading…
Reference in a new issue