commits
tags
#pragma once
//==========================================================================
//
// One wall segment in the draw list
//
//==========================================================================
#include "r_defs.h"
#include "renderstyle.h"
#include "textures.h"
#include "r_data/colormaps.h"
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
bool CheckFog(FLevelLocals* Level, sector_t* frontsector, sector_t* backsector, ELightMode lightmode);
struct HWHorizonInfo;
struct HWSkyInfo;
struct F3DFloor;
class FMaterial;
struct FTexCoordInfo;
struct FSectorPortalGroup;
struct FFlatVertex;
struct FLinePortalSpan;
struct FDynLightData;
class VSMatrix;
struct FSpriteModelFrame;
struct particle_t;
class FRenderState;
struct HWDecal;
struct FSection;
enum area_t : int;
enum HWRenderStyle
{
STYLEHW_Normal, // default
STYLEHW_Solid, // drawn solid (needs special treatment for sprites)
STYLEHW_NoAlphaTest, // disable alpha test
};
enum WallTypes
{
RENDERWALL_NONE,
RENDERWALL_TOP,
RENDERWALL_M1S,
RENDERWALL_M2S,
RENDERWALL_BOTTOM,
RENDERWALL_FOGBOUNDARY,
RENDERWALL_MIRRORSURFACE,
RENDERWALL_M2SNF,
RENDERWALL_COLOR,
RENDERWALL_FFBLOCK,
// Insert new types at the end!
};
enum PortalTypes
{
PORTALTYPE_SKY,
PORTALTYPE_HORIZON,
PORTALTYPE_SKYBOX,
PORTALTYPE_SECTORSTACK,
PORTALTYPE_PLANEMIRROR,
PORTALTYPE_MIRROR,
PORTALTYPE_LINETOLINE,
};
//==========================================================================
//
// One sector plane, still in fixed point
//
//==========================================================================
struct HWSectorPlane
{
FTextureID texture;
secplane_t plane;
float Texheight;
float Angle;
FVector2 Offs;
FVector2 Scale;
void GetFromSector(sector_t * sec, int ceiling)
{
Offs.X = (float)sec->GetXOffset(ceiling);
Offs.Y = (float)sec->GetYOffset(ceiling);
Scale.X = (float)sec->GetXScale(ceiling);
Scale.Y = (float)sec->GetYScale(ceiling);
Angle = (float)sec->GetAngle(ceiling).Degrees();
texture = sec->GetTexture(ceiling);
plane = sec->GetSecPlane(ceiling);
Texheight = (float)((ceiling == sector_t::ceiling)? plane.fD() : -plane.fD());
}
};
struct HWSeg
{
float x1,x2;
float y1,y2;
float fracleft, fracright; // fractional offset of the 2 vertices on the linedef
FVector3 Normal() const
{
// we do not use the vector math inlines here because they are not optimized for speed but accuracy in the playsim and this is called quite frequently.
float x = y2 - y1;
float y = x1 - x2;
float ilength = 1.f / sqrtf(x*x + y*y);
return FVector3(x * ilength, 0, y * ilength);
}
};
struct texcoord
{
float u,v;
};
struct HWDrawInfo;
class HWWall;
// this only exists to keep HWWallDispatcher trivial
struct HWWallDispatcher;
class HWWall
{
public:
static const char passflag[];
enum
{
HWF_CLAMPX = 1,
HWF_CLAMPY = 2,
HWF_SKYHACK = 4,
HWF_GLOW = 8, // illuminated by glowing flats
HWF_NOSPLITUPPER = 16,
HWF_NOSPLITLOWER = 32,
HWF_NOSPLIT = 64,
HWF_TRANSLUCENT = 128,
HWF_NOSLICE = 256
};
enum
{
RWF_BLANK = 0,
RWF_TEXTURED = 1, // actually not being used anymore because with buffers it's even less efficient not writing the texture coordinates - but leave it here
RWF_NOSPLIT = 4,
RWF_NORENDER = 8,
};
enum
{
LOLFT,
UPLFT,
UPRGT,
LORGT,
};
friend struct HWDrawList;
friend class HWPortal;
vertex_t* vertexes[2]; // required for polygon splitting
FGameTexture* texture;
TArray<lightlist_t>* lightlist;
LightmapSurface* lightmap;
HWSeg glseg;
float ztop[2], zbottom[2];
texcoord tcs[4];
texcoord lightuv[4];
float lindex;
float alpha;
FColormap Colormap;
ERenderStyle RenderStyle;
float ViewDistance;
short lightlevel;
uint16_t flags;
uint8_t type;
short rellight;
float topglowcolor[4];
float bottomglowcolor[4];
int dynlightindex;
union
{
// it's either one of them but never more!
FSectorPortal* secportal; // sector portal (formerly skybox)
HWSkyInfo* sky; // for normal sky
HWHorizonInfo* horizon; // for horizon information
FSectorPortalGroup* portal; // stacked sector portals
secplane_t* planemirror; // for plane mirrors
FLinePortalSpan* lineportal; // line-to-line portals
struct
{
int portaltype; // for the mesh builder. Real portals can only be assigned when being rendered.
int portalplane;
};
};
// these are not the same as ytop and ybottom!!!
float zceil[2];
float zfloor[2];
unsigned int vertindex;
unsigned int vertcount;
public:
seg_t* seg; // this gives the easiest access to all other structs involved
subsector_t* sub; // For polyobjects
sector_t* frontsector, * backsector;
//private:
void PutWall(HWWallDispatcher* di, bool translucent);
void PutPortal(HWWallDispatcher* di, int ptype, int plane);
void CheckTexturePosition(FTexCoordInfo* tci);
void Put3DWall(HWWallDispatcher* di, lightlist_t* lightlist, bool translucent);
bool SplitWallComplex(HWWallDispatcher* di, sector_t* frontsector, bool translucent, float& maplightbottomleft, float& maplightbottomright);
void SplitWall(HWWallDispatcher* di, sector_t* frontsector, bool translucent);
void SetupLights(HWDrawInfo* di, FDynLightData& lightdata);
void MakeVertices(bool nosplit);
void SkyPlane(HWWallDispatcher* di, sector_t* sector, int plane, bool allowmirror);
void SkyLine(HWWallDispatcher* di, sector_t* sec, line_t* line);
void SkyNormal(HWWallDispatcher* di, sector_t* fs, vertex_t* v1, vertex_t* v2);
void SkyTop(HWWallDispatcher* di, seg_t* seg, sector_t* fs, sector_t* bs, vertex_t* v1, vertex_t* v2);
void SkyBottom(HWWallDispatcher* di, seg_t* seg, sector_t* fs, sector_t* bs, vertex_t* v1, vertex_t* v2);
bool DoHorizon(HWWallDispatcher* di, seg_t* seg, sector_t* fs, vertex_t* v1, vertex_t* v2);
bool SetWallCoordinates(seg_t* seg, FTexCoordInfo* tci, float ceilingrefheight,
float topleft, float topright, float bottomleft, float bottomright, float t_ofs, float skew);
void DoTexture(HWWallDispatcher* di, int type, seg_t* seg, int peg,
float ceilingrefheight, float floorrefheight,
float CeilingHeightstart, float CeilingHeightend,
float FloorHeightstart, float FloorHeightend,
float v_offset, float skew);
void DoMidTexture(HWWallDispatcher* di, seg_t* seg, bool drawfogboundary,
sector_t* front, sector_t* back,
sector_t* realfront, sector_t* realback,
float fch1, float fch2, float ffh1, float ffh2,
float bch1, float bch2, float bfh1, float bfh2, float zalign, float skew);
void GetPlanePos(F3DFloor::planeref* planeref, float& left, float& right);
void BuildFFBlock(HWWallDispatcher* di, seg_t* seg, F3DFloor* rover, int roverIndex,
float ff_topleft, float ff_topright,
float ff_bottomleft, float ff_bottomright);
void InverseFloors(HWWallDispatcher* di, seg_t* seg, sector_t* frontsector,
float topleft, float topright,
float bottomleft, float bottomright);
void ClipFFloors(HWWallDispatcher* di, seg_t* seg, F3DFloor* ffloor, int ffloorIndex, sector_t* frontsector,
float topleft, float topright,
float bottomleft, float bottomright);
void DoFFloorBlocks(HWWallDispatcher* di, seg_t* seg, sector_t* frontsector, sector_t* backsector,
float fch1, float fch2, float ffh1, float ffh2,
float bch1, float bch2, float bfh1, float bfh2);
void ProcessDecal(HWDrawInfo* di, DBaseDecal* decal, const FVector3& normal);
void ProcessDecals(HWDrawInfo* di);
int CreateVertices(FFlatVertex*& ptr, bool nosplit);
void SplitLeftEdge(FFlatVertex*& ptr);
void SplitRightEdge(FFlatVertex*& ptr);
void SplitUpperEdge(FFlatVertex*& ptr);
void SplitLowerEdge(FFlatVertex*& ptr);
void CountLeftEdge(unsigned& ptr);
void CountRightEdge(unsigned& ptr);
int CountVertices();
void RenderWall(FRenderState& state, int textured);
void RenderFogBoundary(HWWallDispatcher* di, FRenderState& state);
void RenderMirrorSurface(HWWallDispatcher* di, FRenderState& state);
void RenderTexturedWall(HWWallDispatcher* di, FRenderState& state, int rflags);
void RenderTranslucentWall(HWWallDispatcher* di, FRenderState& state);
void DrawDecalsForMirror(HWDrawInfo* di, FRenderState& state, TArray<HWDecal*>& decals);
public:
void Process(HWWallDispatcher* di, seg_t* seg, sector_t* frontsector, sector_t* backsector, bool isculled = false);
void ProcessLowerMiniseg(HWWallDispatcher* di, seg_t* seg, sector_t* frontsector, sector_t* backsector);
float PointOnSide(float x, float y)
{
return -((y - glseg.y1) * (glseg.x2 - glseg.x1) - (x - glseg.x1) * (glseg.y2 - glseg.y1));
}
void DrawWall(HWWallDispatcher* di, FRenderState& state, bool translucent);
};
//==========================================================================
//
// One flat plane in the draw list
//
//==========================================================================
class HWFlat
{
public:
sector_t * sector;
FSection *section;
FGameTexture *texture;
TextureManipulation* TextureFx;
float z; // the z position of the flat (only valid for non-sloped planes)
FColormap Colormap; // light and fog
PalEntry FlatColor;
PalEntry AddColor;
ERenderStyle renderstyle;
float alpha;
HWSectorPlane plane;
int lightlevel;
bool stack;
bool ceiling;
uint8_t renderflags;
uint8_t hacktype;
int iboindex;
//int vboheight;
int dynlightindex;
void CreateSkyboxVertices(FFlatVertex *buffer);
void SetupLights(HWDrawInfo *di, FLightNode *head, FDynLightData &lightdata, int portalgroup);
void PutFlat(HWDrawInfo *di, bool fog = false);
void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture);
void SetFrom3DFloor(F3DFloor *rover, bool top, bool underside);
void ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which = 7 /*SSRF_RENDERALL*/); // cannot use constant due to circular dependencies.
void DrawSubsectors(HWDrawInfo *di, FRenderState &state);
void DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent);
void DrawOtherPlanes(HWDrawInfo *di, FRenderState &state);
void DrawFloodPlanes(HWDrawInfo *di, FRenderState &state);
};
//==========================================================================
//
// One sprite in the draw list
//
//==========================================================================
class HWSprite
{
public:
int lightlevel;
uint8_t foglevel;
uint8_t hw_styleflags;
bool fullbright;
bool polyoffset;
PalEntry ThingColor; // thing's own color
FColormap Colormap;
FSpriteModelFrame * modelframe;
int modelframeflags;
FRenderStyle RenderStyle;
int OverrideShader;
FTranslationID translation;
int index;
float depth;
int vertexindex;
float topclip;
float bottomclip;
float x,y,z; // needed for sorting!
float ul,ur;
float vt,vb;
float x1,y1,z1;
float x2,y2,z2;
float offx, offy;
float trans;
int dynlightindex;
FGameTexture *texture;
AActor * actor;
particle_t * particle;
TArray<lightlist_t> *lightlist;
DRotator Angles;
void SplitSprite(HWDrawInfo *di, sector_t * frontsector, bool translucent);
void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight);
bool CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp);
public:
void CreateVertices(HWDrawInfo *di);
void PutSprite(HWDrawInfo *di, bool translucent);
void Process(HWDrawInfo *di, AActor* thing,sector_t * sector, area_t in_area, int thruportal = false, bool isSpriteShadow = false);
void ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *sector, class DVisualThinker *spr);//, int shade, int fakeside)
void AdjustVisualThinker(HWDrawInfo *di, DVisualThinker *spr, sector_t *sector);
void DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent);
};
struct DecalVertex
{
float x, y, z;
float u, v;
};
struct HWDecal
{
FGameTexture *texture;
TArray<lightlist_t> *lightlist;
DBaseDecal *decal;
DecalVertex dv[4];
float zcenter;
unsigned int vertindex;
FRenderStyle renderstyle;
int lightlevel;
int rellight;
float alpha;
FColormap Colormap;
int dynlightindex;
sector_t *frontsector;
FVector3 Normal;
void DrawDecal(HWDrawInfo *di, FRenderState &state);
};
inline float Dist2(float x1,float y1,float x2,float y2)
{
return sqrtf((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
bool hw_SetPlaneTextureRotation(const HWSectorPlane * secplane, FGameTexture * gltexture, VSMatrix &mat);
void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata);
LightProbe* FindLightProbe(FLevelLocals* level, float x, float y, float z);
extern const float LARGE_VALUE;
struct FDynLightData;
struct FDynamicLight;
bool GetLight(FDynLightData& dld, int group, Plane& p, FDynamicLight* light, bool checkside);
void AddLightToList(FDynLightData &dld, int group, FDynamicLight* light, bool forceAttenuate);
void SetSplitPlanes(FRenderState& state, const secplane_t& top, const secplane_t& bottom);