mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-24 21:21:04 +00:00
Add the experimental swrenderer2
This commit is contained in:
parent
2a9e97688d
commit
7ef5a9f117
4 changed files with 2236 additions and 4 deletions
|
@ -971,6 +971,7 @@ set( NOT_COMPILED_SOURCE_FILES
|
|||
|
||||
set( FASTMATH_PCH_SOURCES
|
||||
r_swrenderer.cpp
|
||||
r_swrenderer2.cpp
|
||||
r_3dfloors.cpp
|
||||
r_bsp.cpp
|
||||
r_draw.cpp
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
#include "r_data/colormaps.h"
|
||||
#include "farchive.h"
|
||||
#include "p_maputl.h"
|
||||
#include "r_swrenderer2.h"
|
||||
|
||||
CVAR(Bool, r_newrenderer, 0, 0);
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -897,7 +900,15 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
|
|||
// Link the polyobjects right before drawing the scene to reduce the amounts of calls to this function
|
||||
PO_LinkToSubsectors();
|
||||
InSubsector = NULL;
|
||||
R_RenderBSPNode (nodes + numnodes - 1); // The head node is the last node output.
|
||||
if (!r_newrenderer || !r_swtruecolor)
|
||||
{
|
||||
R_RenderBSPNode(nodes + numnodes - 1); // The head node is the last node output.
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderBsp bsp;
|
||||
bsp.Render();
|
||||
}
|
||||
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
||||
camera->renderflags = savedflags;
|
||||
WallCycles.Unclock();
|
||||
|
@ -907,8 +918,11 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
|
|||
if (viewactive)
|
||||
{
|
||||
PlaneCycles.Clock();
|
||||
R_DrawPlanes ();
|
||||
R_DrawPortals ();
|
||||
if (!r_newrenderer || !r_swtruecolor)
|
||||
{
|
||||
R_DrawPlanes();
|
||||
R_DrawPortals();
|
||||
}
|
||||
PlaneCycles.Unclock();
|
||||
|
||||
// [RH] Walk through mirrors
|
||||
|
@ -925,7 +939,8 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
|
|||
NetUpdate ();
|
||||
|
||||
MaskedCycles.Clock();
|
||||
R_DrawMasked ();
|
||||
if (!r_newrenderer || !r_swtruecolor)
|
||||
R_DrawMasked ();
|
||||
MaskedCycles.Unclock();
|
||||
|
||||
NetUpdate ();
|
||||
|
|
1871
src/r_swrenderer2.cpp
Normal file
1871
src/r_swrenderer2.cpp
Normal file
File diff suppressed because it is too large
Load diff
345
src/r_swrenderer2.h
Normal file
345
src/r_swrenderer2.h
Normal file
|
@ -0,0 +1,345 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include "doomdata.h"
|
||||
#include "r_utility.h"
|
||||
#include "r_main.h"
|
||||
|
||||
// Transform for a view position and its viewport
|
||||
//
|
||||
// World space uses map coordinates in the XY plane. Z is up.
|
||||
// Eye space means relative to viewer, Y is up and Z is into the screen.
|
||||
// Viewport means in normalized device coordinates (-1 to 1 range with perspective division). 0,0 is in the center of the viewport and Y is still up.
|
||||
// Screen means in final screen coordinates. 0,0 is the upper left corner and Y is down. Z is still 1/z.
|
||||
//
|
||||
class ViewPosTransform
|
||||
{
|
||||
public:
|
||||
DVector3 WorldToEye(const DVector3 &worldPoint) const;
|
||||
DVector3 WorldToViewport(const DVector3 &worldPoint) const { return EyeToViewport(WorldToEye(worldPoint)); }
|
||||
DVector3 WorldToScreen(const DVector3 &worldPoint) const { return EyeToScreen(WorldToEye(worldPoint)); }
|
||||
|
||||
DVector3 EyeToViewport(const DVector3 &eyePoint) const;
|
||||
DVector3 EyeToScreen(const DVector3 &eyePoint) const { return ViewportToScreen(EyeToViewport(eyePoint)); }
|
||||
|
||||
DVector3 ViewportToScreen(const DVector3 &viewportPoint) const;
|
||||
|
||||
double ScreenXToEye(int x, double z) const;
|
||||
double ScreenYToEye(int y, double z) const;
|
||||
|
||||
double NearZ() const { return 0.0078125; };
|
||||
};
|
||||
|
||||
// Screen space coordinates for a wall
|
||||
class WallCoords
|
||||
{
|
||||
public:
|
||||
WallCoords() = default;
|
||||
WallCoords(const ViewPosTransform &transform, const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2);
|
||||
|
||||
// True if transform and clip culled the wall
|
||||
bool Culled = true;
|
||||
|
||||
// Plane for wall in eye space
|
||||
DVector3 PlaneNormal;
|
||||
double PlaneD = 0.0;
|
||||
|
||||
// Z range of the wall in eye space
|
||||
double NearZ = 0.0;
|
||||
double FarZ = 0.0;
|
||||
|
||||
// Screen space bounding box of the wall
|
||||
int ScreenX1 = 0;
|
||||
int ScreenX2 = 0;
|
||||
int ScreenY1 = 0;
|
||||
int ScreenY2 = 0;
|
||||
|
||||
// Get the Y positions for the given column
|
||||
short Y1(int x) const;
|
||||
short Y2(int x) const;
|
||||
|
||||
// Get the depth for a column
|
||||
double Z(int x) const;
|
||||
|
||||
// Perspective correct interpolation from start to end (used to calculate texture coordinates)
|
||||
double VaryingX(int x, double start, double end) const;
|
||||
double VaryingY(int x, int y, double start, double end) const;
|
||||
|
||||
private:
|
||||
static DVector3 Mix(const DVector3 &a, const DVector3 &b, double t);
|
||||
static double Mix(double a, double b, double t);
|
||||
|
||||
ViewPosTransform Transform;
|
||||
DVector3 ScreenTopLeft;
|
||||
DVector3 ScreenTopRight;
|
||||
DVector3 ScreenBottomLeft;
|
||||
DVector3 ScreenBottomRight;
|
||||
double RcpDeltaScreenX = 0.0;
|
||||
double VaryingXScale = 1.0;
|
||||
double VaryingXOffset = 0.0;
|
||||
};
|
||||
|
||||
// Texture coordinates for a wall
|
||||
class WallTextureCoords
|
||||
{
|
||||
public:
|
||||
WallTextureCoords(FTexture *tex, const seg_t *line, side_t::ETexpart texpart, double topz, double bottomz, double unpeggedceil);
|
||||
|
||||
double u1, u2;
|
||||
double v1, v2;
|
||||
|
||||
private:
|
||||
void CalcU(FTexture *tex, const seg_t *line, side_t::ETexpart texpart);
|
||||
void CalcV(FTexture *tex, const seg_t *line, side_t::ETexpart texpart, double topz, double bottomz, double unpeggedceil);
|
||||
void CalcVTopPart(FTexture *tex, const seg_t *line, double topz, double bottomz, double vscale, double yoffset);
|
||||
void CalcVMidPart(FTexture *tex, const seg_t *line, double topz, double bottomz, double vscale, double yoffset);
|
||||
void CalcVBottomPart(FTexture *tex, const seg_t *line, double topz, double bottomz, double unpeggedceil, double vscale, double yoffset);
|
||||
};
|
||||
|
||||
// Clipping buffers used during rendering
|
||||
class RenderClipBuffer
|
||||
{
|
||||
public:
|
||||
void Clear(short left, short right);
|
||||
void MarkSegmentCulled(const WallCoords &wallCoords, int drawIndex);
|
||||
void ClipVertical(const WallCoords &wallCoords, int drawIndex);
|
||||
void ClipTop(const WallCoords &wallCoords, int drawIndex);
|
||||
void ClipBottom(const WallCoords &wallCoords, int drawIndex);
|
||||
bool IsSegmentCulled(short x1, short x2) const;
|
||||
|
||||
void SetupSpriteClip(short x1, short x2, const DVector3 &pos, bool wallSprite);
|
||||
void RenderMaskedWalls();
|
||||
|
||||
short Top[MAXWIDTH];
|
||||
short Bottom[MAXWIDTH];
|
||||
|
||||
std::function<void(short x1, short x2, int drawIndex, const short *clipTop, const short *clipBottom)> DrawMaskedWall;
|
||||
|
||||
private:
|
||||
void AddDrawSegment(short x1, short x2, const WallCoords &wall, bool clipTop, bool clipBottom, int drawIndex);
|
||||
|
||||
struct SolidSegment
|
||||
{
|
||||
SolidSegment(short x1, short x2) : X1(x1), X2(x2) { }
|
||||
short X1, X2;
|
||||
};
|
||||
|
||||
struct DrawSegment
|
||||
{
|
||||
short X1;
|
||||
short X2;
|
||||
int ClipOffset;
|
||||
bool ClipTop;
|
||||
bool ClipBottom;
|
||||
DVector3 PlaneNormal;
|
||||
double PlaneD;
|
||||
double NearZ;
|
||||
double FarZ;
|
||||
int DrawIndex;
|
||||
};
|
||||
|
||||
std::vector<SolidSegment> SolidSegments;
|
||||
std::vector<DrawSegment> DrawSegments;
|
||||
std::vector<short> ClipValues;
|
||||
|
||||
friend class VisibleSegmentsIterator;
|
||||
};
|
||||
|
||||
// Walks the visible segments in a range
|
||||
class VisibleSegmentsIterator
|
||||
{
|
||||
public:
|
||||
VisibleSegmentsIterator(const RenderClipBuffer &buffer, short startx, short endx);
|
||||
bool Step();
|
||||
|
||||
short X1;
|
||||
short X2;
|
||||
|
||||
private:
|
||||
const std::vector<RenderClipBuffer::SolidSegment> &SolidSegments;
|
||||
short endx;
|
||||
int next = 0;
|
||||
};
|
||||
|
||||
// Class used to group sector ceilings/floors sharing common properties
|
||||
class VisiblePlaneKey
|
||||
{
|
||||
public:
|
||||
VisiblePlaneKey() { }
|
||||
VisiblePlaneKey(FTextureID picnum, FSWColormap *colormap, int lightlevel, secplane_t plane, const FTransform &xform) : Picnum(picnum), ColorMap(colormap), LightLevel(lightlevel), Plane(plane), Transform(xform) { }
|
||||
|
||||
bool operator==(const VisiblePlaneKey &other) const
|
||||
{
|
||||
return Picnum == other.Picnum && LightLevel == other.LightLevel && Plane.fD() == other.Plane.fD();
|
||||
}
|
||||
|
||||
FTextureID Picnum;
|
||||
FSWColormap *ColorMap;
|
||||
int LightLevel;
|
||||
secplane_t Plane;
|
||||
FTransform Transform;
|
||||
};
|
||||
|
||||
// Visible plane to be rendered
|
||||
class VisiblePlane
|
||||
{
|
||||
public:
|
||||
VisiblePlane(const VisiblePlaneKey &key) { Clear(key); }
|
||||
|
||||
void Clear(const VisiblePlaneKey &key)
|
||||
{
|
||||
Key = key;
|
||||
Left = viewwidth;
|
||||
Right = 0;
|
||||
for (int i = 0; i < MAXWIDTH; i++)
|
||||
{
|
||||
Top[i] = UnsetValue;
|
||||
Bottom[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VisiblePlaneKey Key;
|
||||
|
||||
enum { UnsetValue = 0x7fff };
|
||||
short Left;
|
||||
short Right;
|
||||
short Top[MAXWIDTH];
|
||||
short Bottom[MAXWIDTH];
|
||||
std::unique_ptr<VisiblePlane> Next;
|
||||
};
|
||||
|
||||
class RenderVisiblePlane
|
||||
{
|
||||
public:
|
||||
RenderVisiblePlane(VisiblePlane *plane, FTexture *tex);
|
||||
void Step();
|
||||
|
||||
double viewx;
|
||||
double viewy;
|
||||
double planeheight;
|
||||
double basexfrac;
|
||||
double baseyfrac;
|
||||
double xstepscale;
|
||||
double ystepscale;
|
||||
};
|
||||
|
||||
// Tracks plane locations and renders them
|
||||
class RenderPlanes
|
||||
{
|
||||
public:
|
||||
void Clear();
|
||||
void MarkCeilingPlane(const VisiblePlaneKey &key, const RenderClipBuffer &clip, const WallCoords &wallCoords);
|
||||
void MarkFloorPlane(const VisiblePlaneKey &key, const RenderClipBuffer &clip, const WallCoords &wallCoords);
|
||||
void Render();
|
||||
|
||||
private:
|
||||
void RenderPlane(VisiblePlane *plane);
|
||||
void RenderSpan(int y, int x1, int x2, const VisiblePlaneKey &key, FTexture *texture, const RenderVisiblePlane &renderInfo);
|
||||
|
||||
VisiblePlane *GetPlaneWithUnsetRange(const VisiblePlaneKey &key, int x0, int x1);
|
||||
VisiblePlane *GetPlane(const VisiblePlaneKey &key);
|
||||
std::unique_ptr<VisiblePlane> AllocPlane(const VisiblePlaneKey &key);
|
||||
static uint32_t Hash(const VisiblePlaneKey &key) { return ((unsigned)((key.Picnum.GetIndex()) * 3 + (key.LightLevel) + (FLOAT2FIXED(key.Plane.fD())) * 7) & (NumBuckets - 1)); }
|
||||
|
||||
enum { NumBuckets = 128 /* must be a power of 2 */ };
|
||||
std::unique_ptr<VisiblePlane> PlaneBuckets[NumBuckets];
|
||||
std::vector<std::unique_ptr<VisiblePlane>> FreePlanes;
|
||||
};
|
||||
|
||||
// Renders a wall texture
|
||||
class RenderWall
|
||||
{
|
||||
public:
|
||||
void Render(const RenderClipBuffer &clip);
|
||||
void RenderMasked(short x1, short x2, const short *clipTop, const short *clipBottom);
|
||||
|
||||
WallCoords Coords;
|
||||
const seg_t *Line;
|
||||
side_t::ETexpart Texpart;
|
||||
double TopZ;
|
||||
double BottomZ;
|
||||
double UnpeggedCeil;
|
||||
FSWColormap *Colormap;
|
||||
bool Masked;
|
||||
|
||||
private:
|
||||
FTexture *GetTexture();
|
||||
int GetShade();
|
||||
float GetLight(short x);
|
||||
};
|
||||
|
||||
// Sprite thing to be rendered
|
||||
class VisibleSprite
|
||||
{
|
||||
public:
|
||||
VisibleSprite(AActor *actor, const DVector3 &eyePos);
|
||||
void Render(RenderClipBuffer *clip);
|
||||
|
||||
private:
|
||||
AActor *Actor;
|
||||
DVector3 EyePos;
|
||||
|
||||
FTexture *GetSpriteTexture(AActor *thing, /*out*/ bool &flipX);
|
||||
visstyle_t GetSpriteVisStyle(AActor *thing, double z);
|
||||
|
||||
friend class RenderBsp; // For sorting
|
||||
};
|
||||
|
||||
// DScreen accelerated sprite to be rendered
|
||||
class ScreenSprite
|
||||
{
|
||||
public:
|
||||
void Render();
|
||||
|
||||
FTexture *Pic = nullptr;
|
||||
double X1 = 0.0;
|
||||
double Y1 = 0.0;
|
||||
double Width = 0.0;
|
||||
double Height = 0.0;
|
||||
FRemapTable *Translation = nullptr;
|
||||
bool Flip = false;
|
||||
visstyle_t visstyle;
|
||||
uint32_t FillColor = 0;
|
||||
FDynamicColormap *Colormap = nullptr;
|
||||
};
|
||||
|
||||
// Renders a BSP tree in a scene
|
||||
class RenderBsp
|
||||
{
|
||||
public:
|
||||
void Render();
|
||||
void RenderScreenSprites();
|
||||
|
||||
private:
|
||||
void RenderNode(void *node);
|
||||
void RenderSubsector(subsector_t *sub);
|
||||
void AddLine(seg_t *line, sector_t *frontsector);
|
||||
|
||||
void AddSprite(AActor *thing);
|
||||
void AddWallSprite(AActor *thing);
|
||||
bool IsThingCulled(AActor *thing);
|
||||
void RenderMaskedObjects();
|
||||
|
||||
void RenderPlayerSprites();
|
||||
void RenderPlayerSprite(DPSprite *sprite, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac);
|
||||
|
||||
int PointOnSide(const DVector2 &pos, const node_t *node);
|
||||
|
||||
// Checks BSP node/subtree bounding box.
|
||||
// Returns true if some part of the bbox might be visible.
|
||||
bool CheckBBox(float *bspcoord);
|
||||
|
||||
ViewPosTransform Transform;
|
||||
RenderClipBuffer Clip;
|
||||
RenderPlanes Planes;
|
||||
std::vector<VisibleSprite> VisibleSprites;
|
||||
std::vector<RenderWall> VisibleMaskedWalls;
|
||||
std::vector<ScreenSprite> ScreenSprites;
|
||||
|
||||
const int BaseXCenter = 160;
|
||||
const int BaseYCenter = 100;
|
||||
};
|
Loading…
Reference in a new issue