mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-27 06:02:18 +00:00
Add a stencil buffer
This commit is contained in:
parent
b94096ffe1
commit
204d09efde
4 changed files with 141 additions and 28 deletions
|
@ -922,7 +922,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RenderPolyBsp bsp;
|
static RenderPolyBsp bsp;
|
||||||
bsp.Render();
|
bsp.Render();
|
||||||
}
|
}
|
||||||
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
||||||
|
|
|
@ -41,15 +41,19 @@ CVAR(Bool, r_debug_cull, 0, 0)
|
||||||
|
|
||||||
void RenderPolyBsp::Render()
|
void RenderPolyBsp::Render()
|
||||||
{
|
{
|
||||||
|
// Setup working buffers
|
||||||
PolyVertexBuffer::Clear();
|
PolyVertexBuffer::Clear();
|
||||||
SolidSegments.clear();
|
SolidSegments.clear();
|
||||||
SolidSegments.reserve(MAXWIDTH / 2 + 2);
|
SolidSegments.reserve(MAXWIDTH / 2 + 2);
|
||||||
SolidSegments.push_back({ -0x7fff, 0 });
|
SolidSegments.push_back({ -0x7fff, 0 });
|
||||||
SolidSegments.push_back({ viewwidth, 0x7fff });
|
SolidSegments.push_back({ viewwidth, 0x7fff });
|
||||||
|
|
||||||
SectorSpriteRanges.clear();
|
SectorSpriteRanges.clear();
|
||||||
SectorSpriteRanges.resize(numsectors);
|
SectorSpriteRanges.resize(numsectors);
|
||||||
SortedSprites.clear();
|
SortedSprites.clear();
|
||||||
|
PvsSectors.clear();
|
||||||
|
SectorSpriteRanges.clear();
|
||||||
|
ScreenSprites.clear();
|
||||||
|
PolyStencilBuffer::Instance()->Clear(viewwidth, viewheight, 0);
|
||||||
|
|
||||||
// Perspective correct:
|
// Perspective correct:
|
||||||
float ratio = WidescreenRatio;
|
float ratio = WidescreenRatio;
|
||||||
|
@ -66,13 +70,12 @@ void RenderPolyBsp::Render()
|
||||||
// Y shearing like the Doom renderer:
|
// Y shearing like the Doom renderer:
|
||||||
//worldToClip = TriMatrix::viewToClip() * TriMatrix::worldToView();
|
//worldToClip = TriMatrix::viewToClip() * TriMatrix::worldToView();
|
||||||
|
|
||||||
// Cull front to back (ok, so we dont cull yet, but we should during this!):
|
// Cull front to back
|
||||||
if (numnodes == 0)
|
if (numnodes == 0)
|
||||||
PvsSectors.push_back(subsectors); // RenderSubsector(subsectors);
|
PvsSectors.push_back(subsectors); // RenderSubsector(subsectors);
|
||||||
else
|
else
|
||||||
RenderNode(nodes + numnodes - 1); // The head node is the last node output.
|
RenderNode(nodes + numnodes - 1); // The head node is the last node output.
|
||||||
|
|
||||||
static PolySkyDome skydome;
|
|
||||||
skydome.Render(worldToClip);
|
skydome.Render(worldToClip);
|
||||||
|
|
||||||
// Render back to front (we don't have a zbuffer at the moment, sniff!):
|
// Render back to front (we don't have a zbuffer at the moment, sniff!):
|
||||||
|
@ -227,9 +230,6 @@ void RenderPolyBsp::AddLine(seg_t *line, sector_t *frontsector)
|
||||||
double frontceilz2 = frontsector->ceilingplane.ZatPoint(line->v2);
|
double frontceilz2 = frontsector->ceilingplane.ZatPoint(line->v2);
|
||||||
double frontfloorz2 = frontsector->floorplane.ZatPoint(line->v2);
|
double frontfloorz2 = frontsector->floorplane.ZatPoint(line->v2);
|
||||||
|
|
||||||
//VisiblePlaneKey ceilingPlaneKey(frontsector->GetTexture(sector_t::ceiling), frontsector->ColorMap, frontsector->lightlevel, frontsector->ceilingplane, frontsector->planes[sector_t::ceiling].xform);
|
|
||||||
//VisiblePlaneKey floorPlaneKey(frontsector->GetTexture(sector_t::floor), frontsector->ColorMap, frontsector->lightlevel, frontsector->floorplane, frontsector->planes[sector_t::floor].xform);
|
|
||||||
|
|
||||||
RenderPolyWall wall;
|
RenderPolyWall wall;
|
||||||
wall.Line = line;
|
wall.Line = line;
|
||||||
wall.Colormap = frontsector->ColorMap;
|
wall.Colormap = frontsector->ColorMap;
|
||||||
|
|
44
src/r_poly.h
44
src/r_poly.h
|
@ -69,6 +69,27 @@ public:
|
||||||
int Count = 0;
|
int Count = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PolySkyDome
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PolySkyDome() { CreateDome(); }
|
||||||
|
void Render(const TriMatrix &worldToClip);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TArray<TriVertex> mVertices;
|
||||||
|
TArray<unsigned int> mPrimStart;
|
||||||
|
int mRows, mColumns;
|
||||||
|
|
||||||
|
void SkyVertex(int r, int c, bool yflip);
|
||||||
|
void CreateSkyHemisphere(bool zflip);
|
||||||
|
void CreateDome();
|
||||||
|
void RenderRow(const TriUniforms &uniforms, FTexture *skytex, int row);
|
||||||
|
void RenderCapColorRow(const TriUniforms &uniforms, FTexture *skytex, int row, bool bottomCap);
|
||||||
|
|
||||||
|
TriVertex SetVertex(float xx, float yy, float zz, float uu = 0, float vv = 0);
|
||||||
|
TriVertex SetVertexXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0);
|
||||||
|
};
|
||||||
|
|
||||||
// Renders a GL BSP tree in a scene
|
// Renders a GL BSP tree in a scene
|
||||||
class RenderPolyBsp
|
class RenderPolyBsp
|
||||||
{
|
{
|
||||||
|
@ -121,6 +142,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<SolidSegment> SolidSegments;
|
std::vector<SolidSegment> SolidSegments;
|
||||||
|
|
||||||
|
PolySkyDome skydome;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderPolyWall
|
class RenderPolyWall
|
||||||
|
@ -181,24 +204,3 @@ public:
|
||||||
static TriVertex *GetVertices(int count);
|
static TriVertex *GetVertices(int count);
|
||||||
static void Clear();
|
static void Clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
class PolySkyDome
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PolySkyDome() { CreateDome(); }
|
|
||||||
void Render(const TriMatrix &worldToClip);
|
|
||||||
|
|
||||||
private:
|
|
||||||
TArray<TriVertex> mVertices;
|
|
||||||
TArray<unsigned int> mPrimStart;
|
|
||||||
int mRows, mColumns;
|
|
||||||
|
|
||||||
void SkyVertex(int r, int c, bool yflip);
|
|
||||||
void CreateSkyHemisphere(bool zflip);
|
|
||||||
void CreateDome();
|
|
||||||
void RenderRow(const TriUniforms &uniforms, FTexture *skytex, int row);
|
|
||||||
void RenderCapColorRow(const TriUniforms &uniforms, FTexture *skytex, int row, bool bottomCap);
|
|
||||||
|
|
||||||
TriVertex SetVertex(float xx, float yy, float zz, float uu = 0, float vv = 0);
|
|
||||||
TriVertex SetVertexXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0);
|
|
||||||
};
|
|
||||||
|
|
|
@ -48,6 +48,117 @@ private:
|
||||||
friend class DrawPolyTrianglesCommand;
|
friend class DrawPolyTrianglesCommand;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 8x8 block of stencil values, plus a mask indicating if values are the same for early out stencil testing
|
||||||
|
class PolyStencilBlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PolyStencilBlock(int block, uint8_t *values, uint32_t *masks) : Values(values + block * 64), ValueMask(masks[block])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Set(int x, int y, uint8_t value)
|
||||||
|
{
|
||||||
|
if (ValueMask == 0xffffffff)
|
||||||
|
{
|
||||||
|
if (Values[0] == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 1; i < 8 * 8 + 4 * 4 + 2 * 2 + 1; i++)
|
||||||
|
Values[i] = Values[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Values[x + y * 8] == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Values[x + y * 8] = value;
|
||||||
|
|
||||||
|
int leveloffset = 0;
|
||||||
|
for (int i = 1; i < 4; i++)
|
||||||
|
{
|
||||||
|
int iy = i + 3;
|
||||||
|
|
||||||
|
x >>= 1;
|
||||||
|
y >>= 1;
|
||||||
|
|
||||||
|
bool same =
|
||||||
|
Values[(x << i) + (y << iy)] != value ||
|
||||||
|
Values[((x + 1) << i) + (y << iy)] != value ||
|
||||||
|
Values[(x << i) + ((y + 1) << iy)] != value ||
|
||||||
|
Values[((x + 1) << i) + ((y + 1) << iy)] != value;
|
||||||
|
|
||||||
|
int levelbit = 1 << (leveloffset + x + y * (8 >> i));
|
||||||
|
|
||||||
|
if (same)
|
||||||
|
ValueMask = ValueMask & ~levelbit;
|
||||||
|
else
|
||||||
|
ValueMask = ValueMask | levelbit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Values[0] != value || Values[4] != value || Values[4 * 8] != value || Values[4 * 8 + 4] != value)
|
||||||
|
ValueMask = ValueMask & ~(1 << 22);
|
||||||
|
else
|
||||||
|
ValueMask = ValueMask | (1 << 22);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Get(int x, int y) const
|
||||||
|
{
|
||||||
|
if (ValueMask == 0xffffffff)
|
||||||
|
return Values[0];
|
||||||
|
else
|
||||||
|
return Values[x + y * 8];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear(uint8_t value)
|
||||||
|
{
|
||||||
|
Values[0] = value;
|
||||||
|
ValueMask = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t *Values; // [8 * 8];
|
||||||
|
uint32_t &ValueMask; // 4 * 4 + 2 * 2 + 1 bits indicating is Values are the same
|
||||||
|
};
|
||||||
|
|
||||||
|
class PolyStencilBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static PolyStencilBuffer *Instance()
|
||||||
|
{
|
||||||
|
static PolyStencilBuffer buffer;
|
||||||
|
return &buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear(int newwidth, int newheight, uint8_t stencil_value = 0)
|
||||||
|
{
|
||||||
|
width = newwidth;
|
||||||
|
height = newheight;
|
||||||
|
int count = BlockWidth() * BlockHeight();
|
||||||
|
values.resize(count * 64);
|
||||||
|
masks.resize(count);
|
||||||
|
|
||||||
|
uint8_t *v = Values();
|
||||||
|
uint32_t *m = Masks();
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
PolyStencilBlock block(i, v, m);
|
||||||
|
block.Clear(stencil_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Width() const { return width; }
|
||||||
|
int Height() const { return height; }
|
||||||
|
int BlockWidth() const { return (width + 7) / 8; }
|
||||||
|
int BlockHeight() const { return (height + 7) / 8; }
|
||||||
|
uint8_t *Values() { return values.data(); }
|
||||||
|
uint32_t *Masks() { return masks.data(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
std::vector<uint8_t> values;
|
||||||
|
std::vector<uint32_t> masks;
|
||||||
|
};
|
||||||
|
|
||||||
struct ScreenPolyTriangleDrawerArgs
|
struct ScreenPolyTriangleDrawerArgs
|
||||||
{
|
{
|
||||||
uint8_t *dest;
|
uint8_t *dest;
|
||||||
|
|
Loading…
Reference in a new issue