- Clean up PolyTriangleDrawer API so that it can better support both softpoly and the swrenderer

- Slightly improve how softpoly processes portals
- Pass the vertex transform matrix via a command rather than being part of the drawer args
- Improve zbuffer drawers in the software renderer
- Misc model rendering fixes
This commit is contained in:
Magnus Norddahl 2018-04-07 15:48:48 +02:00
parent cb3650ed9e
commit 2d51fa5b43
54 changed files with 1209 additions and 842 deletions

View file

@ -801,7 +801,7 @@ set( POLYRENDER_SOURCES
polyrenderer/drawers/poly_triangle.cpp
polyrenderer/drawers/poly_draw_args.cpp
polyrenderer/drawers/screen_triangle.cpp
polyrenderer/math/tri_matrix.cpp
polyrenderer/math/gpu_types.cpp
)
# These files will be flagged as "headers" so that they appear in project files

View file

@ -40,6 +40,7 @@
void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height)
{
mTexture = nullptr;
mTexturePixels = texels;
mTextureWidth = width;
mTextureHeight = height;
@ -48,6 +49,7 @@ void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height)
void PolyDrawArgs::SetTexture(FTexture *texture, FRenderStyle style)
{
mTexture = texture;
mTextureWidth = texture->GetWidth();
mTextureHeight = texture->GetHeight();
if (PolyRenderer::Instance()->RenderTarget->IsBgra())
@ -70,6 +72,7 @@ void PolyDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRender
else
mTranslation = table->Remap;
mTexture = texture;
mTextureWidth = texture->GetWidth();
mTextureHeight = texture->GetHeight();
mTexturePixels = texture->GetPixels(style);
@ -79,6 +82,7 @@ void PolyDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRender
if (style.Flags & STYLEF_RedIsAlpha)
{
mTexture = texture;
mTextureWidth = texture->GetWidth();
mTextureHeight = texture->GetHeight();
mTexturePixels = texture->GetPixels(style);
@ -133,7 +137,7 @@ void PolyDrawArgs::DrawArray(const DrawerCommandQueuePtr &queue, const TriVertex
mVertexCount = vcount;
mElements = nullptr;
mDrawMode = mode;
queue->Push<DrawPolyTrianglesCommand>(*this, PolyTriangleDrawer::is_mirror());
queue->Push<DrawPolyTrianglesCommand>(*this);
}
void PolyDrawArgs::DrawElements(const DrawerCommandQueuePtr &queue, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode)
@ -142,25 +146,7 @@ void PolyDrawArgs::DrawElements(const DrawerCommandQueuePtr &queue, const TriVer
mElements = elements;
mVertexCount = count;
mDrawMode = mode;
queue->Push<DrawPolyTrianglesCommand>(*this, PolyTriangleDrawer::is_mirror());
}
void PolyDrawArgs::DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode)
{
mVertices = vertices;
mVertexCount = vcount;
mElements = nullptr;
mDrawMode = mode;
thread->DrawQueue->Push<DrawPolyTrianglesCommand>(*this, PolyTriangleDrawer::is_mirror());
}
void PolyDrawArgs::DrawElements(PolyRenderThread *thread, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode)
{
mVertices = vertices;
mElements = elements;
mVertexCount = count;
mDrawMode = mode;
thread->DrawQueue->Push<DrawPolyTrianglesCommand>(*this, PolyTriangleDrawer::is_mirror());
queue->Push<DrawPolyTrianglesCommand>(*this);
}
void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright)
@ -224,16 +210,9 @@ void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint3
/////////////////////////////////////////////////////////////////////////////
void RectDrawArgs::SetTexture(const uint8_t *texels, int width, int height)
{
mTexturePixels = texels;
mTextureWidth = width;
mTextureHeight = height;
mTranslation = nullptr;
}
void RectDrawArgs::SetTexture(FTexture *texture, FRenderStyle style)
{
mTexture = texture;
mTextureWidth = texture->GetWidth();
mTextureHeight = texture->GetHeight();
if (PolyRenderer::Instance()->RenderTarget->IsBgra())
@ -255,6 +234,7 @@ void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRender
else
mTranslation = table->Remap;
mTexture = texture;
mTextureWidth = texture->GetWidth();
mTextureHeight = texture->GetHeight();
mTexturePixels = texture->GetPixels(style);
@ -264,6 +244,7 @@ void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRender
if (style.Flags & STYLEF_RedIsAlpha)
{
mTexture = texture;
mTextureWidth = texture->GetWidth();
mTextureHeight = texture->GetHeight();
mTexturePixels = texture->GetPixels(style);
@ -312,6 +293,7 @@ void RectDrawArgs::Draw(PolyRenderThread *thread, double x0, double x1, double y
mU1 = (float)u1;
mV0 = (float)v0;
mV1 = (float)v1;
thread->DrawQueue->Push<DrawRectCommand>(*this);
}

View file

@ -28,7 +28,7 @@
class PolyRenderThread;
class FTexture;
struct TriMatrix;
class Mat4f;
enum class PolyDrawMode
{
@ -75,19 +75,14 @@ public:
void SetWriteColor(bool enable) { mWriteColor = enable; }
void SetWriteStencil(bool enable, uint8_t stencilWriteValue = 0) { mWriteStencil = enable; mStencilWriteValue = stencilWriteValue; }
void SetWriteDepth(bool enable) { mWriteDepth = enable; }
void SetFaceCullCCW(bool counterclockwise) { mFaceCullCCW = counterclockwise; }
void SetStyle(TriBlendMode blendmode, double srcalpha = 1.0, double destalpha = 1.0) { mBlendMode = blendmode; mSrcAlpha = (uint32_t)(srcalpha * 256.0 + 0.5); mDestAlpha = (uint32_t)(destalpha * 256.0 + 0.5); }
void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright);
void SetTransform(const TriMatrix *objectToClip) { mObjectToClip = objectToClip; }
void SetColor(uint32_t bgra, uint8_t palindex);
void SetLights(PolyLight *lights, int numLights) { mLights = lights; mNumLights = numLights; }
void SetDynLightColor(uint32_t color) { mDynLightColor = color; }
void DrawArray(PolyRenderThread *thread, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles);
void DrawElements(PolyRenderThread *thread, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode = PolyDrawMode::Triangles);
void DrawArray(const DrawerCommandQueuePtr &queue, const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles);
void DrawElements(const DrawerCommandQueuePtr &queue, const TriVertex *vertices, const unsigned int *elements, int count, PolyDrawMode mode = PolyDrawMode::Triangles);
const TriMatrix *ObjectToClip() const { return mObjectToClip; }
const PolyClipPlane &ClipPlane(int index) const { return mClipPlane[index]; }
const TriVertex *Vertices() const { return mVertices; }
@ -95,9 +90,9 @@ public:
const unsigned int *Elements() const { return mElements; }
PolyDrawMode DrawMode() const { return mDrawMode; }
bool FaceCullCCW() const { return mFaceCullCCW; }
bool WriteColor() const { return mWriteColor; }
FTexture *Texture() const { return mTexture; }
const uint8_t *TexturePixels() const { return mTexturePixels; }
int TextureWidth() const { return mTextureWidth; }
int TextureHeight() const { return mTextureHeight; }
@ -140,16 +135,15 @@ public:
void SetNormal(const FVector3 &normal) { mNormal = normal; }
private:
const TriMatrix *mObjectToClip = nullptr;
const TriVertex *mVertices = nullptr;
int mVertexCount = 0;
const unsigned int *mElements = nullptr;
PolyDrawMode mDrawMode = PolyDrawMode::Triangles;
bool mFaceCullCCW = false;
bool mDepthTest = false;
bool mWriteStencil = true;
bool mWriteColor = true;
bool mWriteDepth = true;
FTexture *mTexture = nullptr;
const uint8_t *mTexturePixels = nullptr;
int mTextureWidth = 0;
int mTextureHeight = 0;
@ -185,7 +179,6 @@ private:
class RectDrawArgs
{
public:
void SetTexture(const uint8_t *texels, int width, int height);
void SetTexture(FTexture *texture, FRenderStyle style);
void SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style);
void SetLight(FSWColormap *basecolormap, uint32_t lightlevel);
@ -194,6 +187,7 @@ public:
void SetColor(uint32_t bgra, uint8_t palindex);
void Draw(PolyRenderThread *thread, double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1);
FTexture *Texture() const { return mTexture; }
const uint8_t *TexturePixels() const { return mTexturePixels; }
int TextureWidth() const { return mTextureWidth; }
int TextureHeight() const { return mTextureHeight; }
@ -227,6 +221,7 @@ public:
float V1() const { return mV1; }
private:
FTexture *mTexture = nullptr;
const uint8_t *mTexturePixels = nullptr;
int mTextureWidth = 0;
int mTextureHeight = 0;

View file

@ -778,7 +778,7 @@ template<typename BlendT, typename SamplerT>
class RectScreenDrawer32
{
public:
static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread)
static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
@ -798,7 +798,7 @@ public:
private:
template<typename ShadeModeT, typename FilterModeT>
FORCEINLINE static void Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread)
FORCEINLINE static void Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;

View file

@ -805,7 +805,7 @@ template<typename BlendT, typename SamplerT>
class RectScreenDrawer32
{
public:
static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread)
static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
@ -821,7 +821,7 @@ public:
private:
template<typename ShadeModeT, typename FilterModeT>
FORCEINLINE static void VECTORCALL Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread)
FORCEINLINE static void VECTORCALL Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;

View file

@ -429,7 +429,7 @@ template<typename BlendT, typename SamplerT>
class RectScreenDrawer8
{
public:
static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, WorkerThreadData *thread)
static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;

View file

@ -39,52 +39,69 @@
#include "screen_triangle.h"
#include "x86.h"
int PolyTriangleDrawer::viewport_x;
int PolyTriangleDrawer::viewport_y;
int PolyTriangleDrawer::viewport_width;
int PolyTriangleDrawer::viewport_height;
int PolyTriangleDrawer::dest_pitch;
int PolyTriangleDrawer::dest_width;
int PolyTriangleDrawer::dest_height;
uint8_t *PolyTriangleDrawer::dest;
bool PolyTriangleDrawer::dest_bgra;
bool PolyTriangleDrawer::mirror;
void PolyTriangleDrawer::set_viewport(int x, int y, int width, int height, DCanvas *canvas)
void PolyTriangleDrawer::ClearBuffers(DCanvas *canvas)
{
dest = (uint8_t*)canvas->GetBuffer();
dest_width = canvas->GetWidth();
dest_height = canvas->GetHeight();
dest_pitch = canvas->GetPitch();
dest_bgra = canvas->IsBgra();
PolyStencilBuffer::Instance()->Clear(canvas->GetWidth(), canvas->GetHeight(), 0);
PolyZBuffer::Instance()->Resize(canvas->GetPitch(), canvas->GetHeight());
}
void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas, bool span_drawers)
{
uint8_t *dest = (uint8_t*)canvas->GetBuffer();
int dest_width = canvas->GetWidth();
int dest_height = canvas->GetHeight();
int dest_pitch = canvas->GetPitch();
bool dest_bgra = canvas->IsBgra();
int offsetx = clamp(x, 0, dest_width);
int offsety = clamp(y, 0, dest_height);
int pixelsize = dest_bgra ? 4 : 1;
viewport_x = x - offsetx;
viewport_y = y - offsety;
viewport_width = width;
viewport_height = height;
int viewport_x = x - offsetx;
int viewport_y = y - offsety;
int viewport_width = width;
int viewport_height = height;
dest += (offsetx + offsety * dest_pitch) * pixelsize;
dest_width = clamp(viewport_x + viewport_width, 0, dest_width - offsetx);
dest_height = clamp(viewport_y + viewport_height, 0, dest_height - offsety);
queue->Push<PolySetViewportCommand>(viewport_x, viewport_y, viewport_width, viewport_height, dest, dest_width, dest_height, dest_pitch, dest_bgra, span_drawers);
}
void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip)
{
queue->Push<PolySetTransformCommand>(objectToClip);
}
void PolyTriangleDrawer::ToggleMirror(const DrawerCommandQueuePtr &queue)
{
queue->Push<PolyToggleMirrorCommand>();
}
/////////////////////////////////////////////////////////////////////////////
void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra, bool new_span_drawers)
{
viewport_x = x;
viewport_y = y;
viewport_width = width;
viewport_height = height;
dest = new_dest;
dest_width = new_dest_width;
dest_height = new_dest_height;
dest_pitch = new_dest_pitch;
dest_bgra = new_dest_bgra;
span_drawers = new_span_drawers;
mirror = false;
}
void PolyTriangleDrawer::toggle_mirror()
void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip)
{
mirror = !mirror;
objectToClip = newObjectToClip;
}
bool PolyTriangleDrawer::is_mirror()
{
return mirror;
}
void PolyTriangleDrawer::draw_elements(const PolyDrawArgs &drawargs, WorkerThreadData *thread)
void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs)
{
if (drawargs.VertexCount() < 3)
return;
@ -101,7 +118,7 @@ void PolyTriangleDrawer::draw_elements(const PolyDrawArgs &drawargs, WorkerThrea
args.stencilMasks = PolyStencilBuffer::Instance()->Masks();
args.zbuffer = PolyZBuffer::Instance()->Values();
bool ccw = drawargs.FaceCullCCW();
bool ccw = !mirror;
const TriVertex *vinput = drawargs.Vertices();
const unsigned int *elements = drawargs.Elements();
int vcount = drawargs.VertexCount();
@ -112,29 +129,29 @@ void PolyTriangleDrawer::draw_elements(const PolyDrawArgs &drawargs, WorkerThrea
for (int i = 0; i < vcount / 3; i++)
{
for (int j = 0; j < 3; j++)
vert[j] = shade_vertex(drawargs, vinput[*(elements++)]);
draw_shaded_triangle(vert, ccw, &args, thread);
vert[j] = ShadeVertex(drawargs, vinput[*(elements++)]);
DrawShadedTriangle(vert, ccw, &args);
}
}
else if (drawargs.DrawMode() == PolyDrawMode::TriangleFan)
{
vert[0] = shade_vertex(drawargs, vinput[*(elements++)]);
vert[1] = shade_vertex(drawargs, vinput[*(elements++)]);
vert[0] = ShadeVertex(drawargs, vinput[*(elements++)]);
vert[1] = ShadeVertex(drawargs, vinput[*(elements++)]);
for (int i = 2; i < vcount; i++)
{
vert[2] = shade_vertex(drawargs, vinput[*(elements++)]);
draw_shaded_triangle(vert, ccw, &args, thread);
vert[2] = ShadeVertex(drawargs, vinput[*(elements++)]);
DrawShadedTriangle(vert, ccw, &args);
vert[1] = vert[2];
}
}
else // TriangleDrawMode::TriangleStrip
{
vert[0] = shade_vertex(drawargs, vinput[*(elements++)]);
vert[1] = shade_vertex(drawargs, vinput[*(elements++)]);
vert[0] = ShadeVertex(drawargs, vinput[*(elements++)]);
vert[1] = ShadeVertex(drawargs, vinput[*(elements++)]);
for (int i = 2; i < vcount; i++)
{
vert[2] = shade_vertex(drawargs, vinput[*(elements++)]);
draw_shaded_triangle(vert, ccw, &args, thread);
vert[2] = ShadeVertex(drawargs, vinput[*(elements++)]);
DrawShadedTriangle(vert, ccw, &args);
vert[0] = vert[1];
vert[1] = vert[2];
ccw = !ccw;
@ -142,7 +159,7 @@ void PolyTriangleDrawer::draw_elements(const PolyDrawArgs &drawargs, WorkerThrea
}
}
void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadData *thread)
void PolyTriangleThreadData::DrawArrays(const PolyDrawArgs &drawargs)
{
if (drawargs.VertexCount() < 3)
return;
@ -159,7 +176,7 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadD
args.stencilMasks = PolyStencilBuffer::Instance()->Masks();
args.zbuffer = PolyZBuffer::Instance()->Values();
bool ccw = drawargs.FaceCullCCW();
bool ccw = !mirror;
const TriVertex *vinput = drawargs.Vertices();
int vcount = drawargs.VertexCount();
@ -169,29 +186,29 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadD
for (int i = 0; i < vcount / 3; i++)
{
for (int j = 0; j < 3; j++)
vert[j] = shade_vertex(drawargs, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, thread);
vert[j] = ShadeVertex(drawargs, *(vinput++));
DrawShadedTriangle(vert, ccw, &args);
}
}
else if (drawargs.DrawMode() == PolyDrawMode::TriangleFan)
{
vert[0] = shade_vertex(drawargs, *(vinput++));
vert[1] = shade_vertex(drawargs, *(vinput++));
vert[0] = ShadeVertex(drawargs, *(vinput++));
vert[1] = ShadeVertex(drawargs, *(vinput++));
for (int i = 2; i < vcount; i++)
{
vert[2] = shade_vertex(drawargs, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, thread);
vert[2] = ShadeVertex(drawargs, *(vinput++));
DrawShadedTriangle(vert, ccw, &args);
vert[1] = vert[2];
}
}
else // TriangleDrawMode::TriangleStrip
{
vert[0] = shade_vertex(drawargs, *(vinput++));
vert[1] = shade_vertex(drawargs, *(vinput++));
vert[0] = ShadeVertex(drawargs, *(vinput++));
vert[1] = ShadeVertex(drawargs, *(vinput++));
for (int i = 2; i < vcount; i++)
{
vert[2] = shade_vertex(drawargs, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, thread);
vert[2] = ShadeVertex(drawargs, *(vinput++));
DrawShadedTriangle(vert, ccw, &args);
vert[0] = vert[1];
vert[1] = vert[2];
ccw = !ccw;
@ -199,12 +216,10 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadD
}
}
ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, const TriVertex &v)
ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs, const TriVertex &v)
{
const TriMatrix &objectToClip = *drawargs.ObjectToClip();
// Apply transform to get clip coordinates:
FVector4 position = objectToClip * FVector4(v.x, v.y, v.z, v.w);
Vec4f position = (*objectToClip) * Vec4f(v.x, v.y, v.z, v.w);
ShadedTriVertex sv;
sv.x = position.X;
@ -227,7 +242,7 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, c
return sv;
}
bool PolyTriangleDrawer::is_degenerate(const ShadedTriVertex *vert)
bool PolyTriangleThreadData::IsDegenerate(const ShadedTriVertex *vert)
{
// A degenerate triangle has a zero cross product for two of its sides.
float ax = vert[1].x - vert[0].x;
@ -243,7 +258,7 @@ bool PolyTriangleDrawer::is_degenerate(const ShadedTriVertex *vert)
return crosslengthsqr <= 1.e-6f;
}
bool PolyTriangleDrawer::is_frontfacing(TriDrawTriangleArgs *args)
bool PolyTriangleThreadData::IsFrontfacing(TriDrawTriangleArgs *args)
{
float a =
args->v1->x * args->v2->y - args->v2->x * args->v1->y +
@ -252,15 +267,15 @@ bool PolyTriangleDrawer::is_frontfacing(TriDrawTriangleArgs *args)
return a <= 0.0f;
}
void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread)
void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *vert, bool ccw, TriDrawTriangleArgs *args)
{
// Reject triangle if degenerate
if (is_degenerate(vert))
if (IsDegenerate(vert))
return;
// Cull, clip and generate additional vertices as needed
ShadedTriVertex clippedvert[max_additional_vertices];
int numclipvert = clipedge(vert, clippedvert);
int numclipvert = ClipEdge(vert, clippedvert);
#ifdef NO_SSE
// Map to 2D viewport:
@ -333,8 +348,13 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool
args->v1 = &clippedvert[numclipvert - 1];
args->v2 = &clippedvert[i - 1];
args->v3 = &clippedvert[i - 2];
if (is_frontfacing(args) == ccw && args->CalculateGradients())
ScreenTriangle::Draw(args, thread);
if (IsFrontfacing(args) == ccw && args->CalculateGradients())
{
if (!span_drawers)
ScreenTriangle::Draw(args, this);
else
ScreenTriangle::DrawSWRender(args, this);
}
}
}
else
@ -344,13 +364,18 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool
args->v1 = &clippedvert[0];
args->v2 = &clippedvert[i - 1];
args->v3 = &clippedvert[i];
if (is_frontfacing(args) != ccw && args->CalculateGradients())
ScreenTriangle::Draw(args, thread);
if (IsFrontfacing(args) != ccw && args->CalculateGradients())
{
if (!span_drawers)
ScreenTriangle::Draw(args, this);
else
ScreenTriangle::DrawSWRender(args, this);
}
}
}
}
int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert)
int PolyTriangleThreadData::ClipEdge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert)
{
// Clip and cull so that the following is true for all vertices:
// -v.w <= v.x <= v.w
@ -524,35 +549,61 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, ShadedTriVertex *
return inputverts;
}
PolyTriangleThreadData *PolyTriangleThreadData::Get(DrawerThread *thread)
{
if (!thread->poly)
thread->poly = std::make_shared<PolyTriangleThreadData>(thread->core, thread->num_cores);
return thread->poly.get();
}
/////////////////////////////////////////////////////////////////////////////
DrawPolyTrianglesCommand::DrawPolyTrianglesCommand(const PolyDrawArgs &args, bool mirror)
: args(args)
PolySetTransformCommand::PolySetTransformCommand(const Mat4f *objectToClip) : objectToClip(objectToClip)
{
}
void PolySetTransformCommand::Execute(DrawerThread *thread)
{
PolyTriangleThreadData::Get(thread)->SetTransform(objectToClip);
}
/////////////////////////////////////////////////////////////////////////////
void PolyToggleMirrorCommand::Execute(DrawerThread *thread)
{
PolyTriangleThreadData::Get(thread)->ToggleMirror();
}
/////////////////////////////////////////////////////////////////////////////
PolySetViewportCommand::PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, bool span_drawers)
: x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra), span_drawers(span_drawers)
{
}
void PolySetViewportCommand::Execute(DrawerThread *thread)
{
PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, span_drawers);
}
/////////////////////////////////////////////////////////////////////////////
DrawPolyTrianglesCommand::DrawPolyTrianglesCommand(const PolyDrawArgs &args) : args(args)
{
if (mirror)
this->args.SetFaceCullCCW(!this->args.FaceCullCCW());
}
void DrawPolyTrianglesCommand::Execute(DrawerThread *thread)
{
WorkerThreadData thread_data;
thread_data.core = thread->core;
thread_data.num_cores = thread->num_cores;
if (!args.Elements())
PolyTriangleDrawer::draw_arrays(args, &thread_data);
PolyTriangleThreadData::Get(thread)->DrawArrays(args);
else
PolyTriangleDrawer::draw_elements(args, &thread_data);
PolyTriangleThreadData::Get(thread)->DrawElements(args);
}
/////////////////////////////////////////////////////////////////////////////
void DrawRectCommand::Execute(DrawerThread *thread)
{
WorkerThreadData thread_data;
thread_data.core = thread->core;
thread_data.num_cores = thread->num_cores;
auto renderTarget = PolyRenderer::Instance()->RenderTarget;
const void *destOrg = renderTarget->GetBuffer();
int destWidth = renderTarget->GetWidth();
@ -560,7 +611,7 @@ void DrawRectCommand::Execute(DrawerThread *thread)
int destPitch = renderTarget->GetPitch();
int blendmode = (int)args.BlendMode();
if (renderTarget->IsBgra())
ScreenTriangle::RectDrawers32[blendmode](destOrg, destWidth, destHeight, destPitch, &args, &thread_data);
ScreenTriangle::RectDrawers32[blendmode](destOrg, destWidth, destHeight, destPitch, &args, PolyTriangleThreadData::Get(thread));
else
ScreenTriangle::RectDrawers8[blendmode](destOrg, destWidth, destHeight, destPitch, &args, &thread_data);
ScreenTriangle::RectDrawers8[blendmode](destOrg, destWidth, destHeight, destPitch, &args, PolyTriangleThreadData::Get(thread));
}

View file

@ -25,43 +25,110 @@
#include "swrenderer/drawers/r_draw.h"
#include "swrenderer/drawers/r_thread.h"
#include "polyrenderer/drawers/screen_triangle.h"
#include "polyrenderer/math/tri_matrix.h"
#include "polyrenderer/math/gpu_types.h"
#include "polyrenderer/drawers/poly_buffer.h"
#include "polyrenderer/drawers/poly_draw_args.h"
typedef void(*PolyDrawFuncPtr)(const TriDrawTriangleArgs *, WorkerThreadData *);
class PolyTriangleDrawer
{
public:
static void set_viewport(int x, int y, int width, int height, DCanvas *canvas);
static void toggle_mirror();
static bool is_mirror();
static void ClearBuffers(DCanvas *canvas);
static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas, bool span_drawers);
static void ToggleMirror(const DrawerCommandQueuePtr &queue);
static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip);
};
class PolyTriangleThreadData
{
public:
PolyTriangleThreadData(int32_t core, int32_t num_cores) : core(core), num_cores(num_cores) { }
void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, bool span_drawers);
void SetTransform(const Mat4f *objectToClip);
void ToggleMirror() { mirror = !mirror; }
void DrawElements(const PolyDrawArgs &args);
void DrawArrays(const PolyDrawArgs &args);
int32_t core;
int32_t num_cores;
// The number of lines to skip to reach the first line to be rendered by this thread
int skipped_by_thread(int first_line)
{
int core_skip = (num_cores - (first_line - core) % num_cores) % num_cores;
return core_skip;
}
static PolyTriangleThreadData *Get(DrawerThread *thread);
private:
static ShadedTriVertex shade_vertex(const PolyDrawArgs &drawargs, const TriVertex &v);
static void draw_elements(const PolyDrawArgs &args, WorkerThreadData *thread);
static void draw_arrays(const PolyDrawArgs &args, WorkerThreadData *thread);
static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread);
static bool is_degenerate(const ShadedTriVertex *vertices);
static bool is_frontfacing(TriDrawTriangleArgs *args);
ShadedTriVertex ShadeVertex(const PolyDrawArgs &drawargs, const TriVertex &v);
void DrawShadedTriangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args);
static bool IsDegenerate(const ShadedTriVertex *vertices);
static bool IsFrontfacing(TriDrawTriangleArgs *args);
static int ClipEdge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert);
static int clipedge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert);
static int viewport_x, viewport_y, viewport_width, viewport_height, dest_pitch, dest_width, dest_height;
static bool dest_bgra;
static uint8_t *dest;
static bool mirror;
int viewport_x = 0;
int viewport_y = 0;
int viewport_width = 0;
int viewport_height = 0;
int dest_pitch = 0;
int dest_width = 0;
int dest_height = 0;
bool dest_bgra = false;
uint8_t *dest = nullptr;
bool mirror = false;
const Mat4f *objectToClip = nullptr;
bool span_drawers = false;
enum { max_additional_vertices = 16 };
};
friend class DrawPolyTrianglesCommand;
class PolySetTransformCommand : public DrawerCommand
{
public:
PolySetTransformCommand(const Mat4f *objectToClip);
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "PolySetTransform"; }
private:
const Mat4f *objectToClip;
};
class PolyToggleMirrorCommand : public DrawerCommand
{
public:
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "PolyToggleMirror"; }
};
class PolySetViewportCommand : public DrawerCommand
{
public:
PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, bool span_drawers);
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "PolySetViewport"; }
private:
int x;
int y;
int width;
int height;
uint8_t *dest;
int dest_width;
int dest_height;
int dest_pitch;
bool dest_bgra;
bool span_drawers;
};
class DrawPolyTrianglesCommand : public DrawerCommand
{
public:
DrawPolyTrianglesCommand(const PolyDrawArgs &args, bool mirror);
DrawPolyTrianglesCommand(const PolyDrawArgs &args);
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "DrawPolyTriangles"; }

View file

@ -47,7 +47,7 @@
class TriangleBlock
{
public:
TriangleBlock(const TriDrawTriangleArgs *args, WorkerThreadData *thread);
TriangleBlock(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
void Render();
private:
@ -61,7 +61,7 @@ private:
void RenderBlock(int x0, int y0, int x1, int y1);
const TriDrawTriangleArgs *args;
WorkerThreadData *thread;
PolyTriangleThreadData *thread;
// Block size, standard 8x8 (must be power of two)
static const int q = 8;
@ -138,7 +138,7 @@ private:
void DepthWrite(const TriDrawTriangleArgs *args);
};
TriangleBlock::TriangleBlock(const TriDrawTriangleArgs *args, WorkerThreadData *thread) : args(args), thread(thread)
TriangleBlock::TriangleBlock(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) : args(args), thread(thread)
{
const ShadedTriVertex &v1 = *args->v1;
const ShadedTriVertex &v2 = *args->v2;
@ -1071,20 +1071,11 @@ void TriangleBlock::DepthWrite(const TriDrawTriangleArgs *args)
#endif
EXTERN_CVAR(Bool, r_polyrenderer)
void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thread)
{
if (r_polyrenderer)
void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
{
TriangleBlock block(args, thread);
block.Render();
}
else
{
DrawSWRender(args, thread);
}
}
static void SortVertices(const TriDrawTriangleArgs *args, ShadedTriVertex **sortedVertices)
{
@ -1100,7 +1091,7 @@ static void SortVertices(const TriDrawTriangleArgs *args, ShadedTriVertex **sort
std::swap(sortedVertices[1], sortedVertices[2]);
}
void ScreenTriangle::DrawSWRender(const TriDrawTriangleArgs *args, WorkerThreadData *thread)
void ScreenTriangle::DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
{
// Sort vertices by Y position
ShadedTriVertex *sortedVertices[3];
@ -1568,7 +1559,7 @@ void(*ScreenTriangle::TriDrawers32[])(int, int, uint32_t, uint32_t, const TriDra
&TriScreenDrawer32<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::FogBoundarySampler>::Execute // FogBoundary
};
void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *) =
void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) =
{
&RectScreenDrawer8<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureOpaque
&RectScreenDrawer8<TriScreenDrawerModes::MaskedBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureMasked
@ -1596,7 +1587,7 @@ void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDra
&RectScreenDrawer8<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::FogBoundarySampler>::Execute // FogBoundary
};
void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *) =
void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) =
{
&RectScreenDrawer32<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureOpaque
&RectScreenDrawer32<TriScreenDrawerModes::MaskedBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureMasked

View file

@ -27,19 +27,7 @@
class FString;
class PolyDrawArgs;
struct WorkerThreadData
{
int32_t core;
int32_t num_cores;
// The number of lines to skip to reach the first line to be rendered by this thread
int skipped_by_thread(int first_line)
{
int core_skip = (num_cores - (first_line - core) % num_cores) % num_cores;
return core_skip;
}
};
class PolyTriangleThreadData;
struct ShadedTriVertex
{
@ -148,15 +136,15 @@ enum class TriBlendMode
class ScreenTriangle
{
public:
static void Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thread);
static void DrawSWRender(const TriDrawTriangleArgs *args, WorkerThreadData *thread);
static void Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args);
static void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args);
static void(*TriDrawers8[])(int, int, uint32_t, uint32_t, const TriDrawTriangleArgs *);
static void(*TriDrawers32[])(int, int, uint32_t, uint32_t, const TriDrawTriangleArgs *);
static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *);
static void(*RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, WorkerThreadData *);
static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *);
static void(*RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *);
static int FuzzStart;
};

View file

@ -0,0 +1,271 @@
/*
** Hardpoly renderer
** Copyright (c) 2016 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include <stdlib.h>
#include "gpu_types.h"
#include "doomtype.h"
#include <cmath>
Mat4f Mat4f::Null()
{
Mat4f m;
memset(m.Matrix, 0, sizeof(m.Matrix));
return m;
}
Mat4f Mat4f::Identity()
{
Mat4f m = Null();
m.Matrix[0] = 1.0f;
m.Matrix[5] = 1.0f;
m.Matrix[10] = 1.0f;
m.Matrix[15] = 1.0f;
return m;
}
Mat4f Mat4f::FromValues(float *matrix)
{
Mat4f m;
memcpy(m.Matrix, matrix, sizeof(m.Matrix));
return m;
}
Mat4f Mat4f::Transpose(const Mat4f &matrix)
{
Mat4f m;
for (int y = 0; y < 4; y++)
for (int x = 0; x < 4; x++)
m.Matrix[x + y * 4] = matrix.Matrix[y + x * 4];
return m;
}
Mat4f Mat4f::Translate(float x, float y, float z)
{
Mat4f m = Identity();
m.Matrix[0 + 3 * 4] = x;
m.Matrix[1 + 3 * 4] = y;
m.Matrix[2 + 3 * 4] = z;
return m;
}
Mat4f Mat4f::Scale(float x, float y, float z)
{
Mat4f m = Null();
m.Matrix[0 + 0 * 4] = x;
m.Matrix[1 + 1 * 4] = y;
m.Matrix[2 + 2 * 4] = z;
m.Matrix[3 + 3 * 4] = 1;
return m;
}
Mat4f Mat4f::Rotate(float angle, float x, float y, float z)
{
float c = cosf(angle);
float s = sinf(angle);
Mat4f m = Null();
m.Matrix[0 + 0 * 4] = (x*x*(1.0f - c) + c);
m.Matrix[0 + 1 * 4] = (x*y*(1.0f - c) - z*s);
m.Matrix[0 + 2 * 4] = (x*z*(1.0f - c) + y*s);
m.Matrix[1 + 0 * 4] = (y*x*(1.0f - c) + z*s);
m.Matrix[1 + 1 * 4] = (y*y*(1.0f - c) + c);
m.Matrix[1 + 2 * 4] = (y*z*(1.0f - c) - x*s);
m.Matrix[2 + 0 * 4] = (x*z*(1.0f - c) - y*s);
m.Matrix[2 + 1 * 4] = (y*z*(1.0f - c) + x*s);
m.Matrix[2 + 2 * 4] = (z*z*(1.0f - c) + c);
m.Matrix[3 + 3 * 4] = 1.0f;
return m;
}
Mat4f Mat4f::SwapYZ()
{
Mat4f m = Null();
m.Matrix[0 + 0 * 4] = 1.0f;
m.Matrix[1 + 2 * 4] = 1.0f;
m.Matrix[2 + 1 * 4] = -1.0f;
m.Matrix[3 + 3 * 4] = 1.0f;
return m;
}
Mat4f Mat4f::Perspective(float fovy, float aspect, float z_near, float z_far, Handedness handedness, ClipZRange clipZ)
{
float f = (float)(1.0 / tan(fovy * M_PI / 360.0));
Mat4f m = Null();
m.Matrix[0 + 0 * 4] = f / aspect;
m.Matrix[1 + 1 * 4] = f;
m.Matrix[2 + 2 * 4] = (z_far + z_near) / (z_near - z_far);
m.Matrix[2 + 3 * 4] = (2.0f * z_far * z_near) / (z_near - z_far);
m.Matrix[3 + 2 * 4] = -1.0f;
if (handedness == Handedness::Left)
{
m = m * Mat4f::Scale(1.0f, 1.0f, -1.0f);
}
if (clipZ == ClipZRange::ZeroPositiveW)
{
Mat4f scale_translate = Identity();
scale_translate.Matrix[2 + 2 * 4] = 0.5f;
scale_translate.Matrix[2 + 3 * 4] = 0.5f;
m = scale_translate * m;
}
return m;
}
Mat4f Mat4f::Frustum(float left, float right, float bottom, float top, float near, float far, Handedness handedness, ClipZRange clipZ)
{
float a = (right + left) / (right - left);
float b = (top + bottom) / (top - bottom);
float c = -(far + near) / (far - near);
float d = -(2.0f * far) / (far - near);
Mat4f m = Null();
m.Matrix[0 + 0 * 4] = 2.0f * near / (right - left);
m.Matrix[1 + 1 * 4] = 2.0f * near / (top - bottom);
m.Matrix[0 + 2 * 4] = a;
m.Matrix[1 + 2 * 4] = b;
m.Matrix[2 + 2 * 4] = c;
m.Matrix[2 + 3 * 4] = d;
m.Matrix[3 + 2 * 4] = -1;
if (handedness == Handedness::Left)
{
m = m * Mat4f::Scale(1.0f, 1.0f, -1.0f);
}
if (clipZ == ClipZRange::ZeroPositiveW)
{
Mat4f scale_translate = Identity();
scale_translate.Matrix[2 + 2 * 4] = 0.5f;
scale_translate.Matrix[2 + 3 * 4] = 0.5f;
m = scale_translate * m;
}
return m;
}
Mat4f Mat4f::operator*(const Mat4f &mult) const
{
Mat4f result;
for (int x = 0; x < 4; x++)
{
for (int y = 0; y < 4; y++)
{
result.Matrix[x + y * 4] =
Matrix[0 * 4 + x] * mult.Matrix[y * 4 + 0] +
Matrix[1 * 4 + x] * mult.Matrix[y * 4 + 1] +
Matrix[2 * 4 + x] * mult.Matrix[y * 4 + 2] +
Matrix[3 * 4 + x] * mult.Matrix[y * 4 + 3];
}
}
return result;
}
Vec4f Mat4f::operator*(const Vec4f &v) const
{
Vec4f result;
#ifdef NO_SSE
result.X = Matrix[0 * 4 + 0] * v.X + Matrix[1 * 4 + 0] * v.Y + Matrix[2 * 4 + 0] * v.Z + Matrix[3 * 4 + 0] * v.W;
result.Y = Matrix[0 * 4 + 1] * v.X + Matrix[1 * 4 + 1] * v.Y + Matrix[2 * 4 + 1] * v.Z + Matrix[3 * 4 + 1] * v.W;
result.Z = Matrix[0 * 4 + 2] * v.X + Matrix[1 * 4 + 2] * v.Y + Matrix[2 * 4 + 2] * v.Z + Matrix[3 * 4 + 2] * v.W;
result.W = Matrix[0 * 4 + 3] * v.X + Matrix[1 * 4 + 3] * v.Y + Matrix[2 * 4 + 3] * v.Z + Matrix[3 * 4 + 3] * v.W;
#else
__m128 m0 = _mm_loadu_ps(Matrix);
__m128 m1 = _mm_loadu_ps(Matrix + 4);
__m128 m2 = _mm_loadu_ps(Matrix + 8);
__m128 m3 = _mm_loadu_ps(Matrix + 12);
__m128 mv = _mm_loadu_ps(&v.X);
m0 = _mm_mul_ps(m0, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(0, 0, 0, 0)));
m1 = _mm_mul_ps(m1, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(1, 1, 1, 1)));
m2 = _mm_mul_ps(m2, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(2, 2, 2, 2)));
m3 = _mm_mul_ps(m3, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(3, 3, 3, 3)));
mv = _mm_add_ps(_mm_add_ps(_mm_add_ps(m0, m1), m2), m3);
Vec4f sv;
_mm_storeu_ps(&result.X, mv);
#endif
return result;
}
/////////////////////////////////////////////////////////////////////////////
Mat3f::Mat3f(const Mat4f &matrix)
{
for (int y = 0; y < 3; y++)
for (int x = 0; x < 3; x++)
Matrix[x + y * 3] = matrix.Matrix[x + y * 4];
}
Mat3f Mat3f::Null()
{
Mat3f m;
memset(m.Matrix, 0, sizeof(m.Matrix));
return m;
}
Mat3f Mat3f::Identity()
{
Mat3f m = Null();
m.Matrix[0] = 1.0f;
m.Matrix[4] = 1.0f;
m.Matrix[8] = 1.0f;
return m;
}
Mat3f Mat3f::FromValues(float *matrix)
{
Mat3f m;
memcpy(m.Matrix, matrix, sizeof(m.Matrix));
return m;
}
Mat3f Mat3f::Transpose(const Mat3f &matrix)
{
Mat3f m;
for (int y = 0; y < 3; y++)
for (int x = 0; x < 3; x++)
m.Matrix[x + y * 3] = matrix.Matrix[y + x * 3];
return m;
}
Mat3f Mat3f::operator*(const Mat3f &mult) const
{
Mat3f result;
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
result.Matrix[x + y * 3] =
Matrix[0 * 3 + x] * mult.Matrix[y * 3 + 0] +
Matrix[1 * 3 + x] * mult.Matrix[y * 3 + 1] +
Matrix[2 * 3 + x] * mult.Matrix[y * 3 + 2];
}
}
return result;
}
Vec3f Mat3f::operator*(const Vec3f &v) const
{
Vec3f result;
result.X = Matrix[0 * 3 + 0] * v.X + Matrix[1 * 3 + 0] * v.Y + Matrix[2 * 3 + 0] * v.Z;
result.Y = Matrix[0 * 3 + 1] * v.X + Matrix[1 * 3 + 1] * v.Y + Matrix[2 * 3 + 1] * v.Z;
result.Z = Matrix[0 * 3 + 2] * v.X + Matrix[1 * 3 + 2] * v.Y + Matrix[2 * 3 + 2] * v.Z;
return result;
}

View file

@ -0,0 +1,148 @@
/*
** Hardpoly renderer
** Copyright (c) 2016 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#pragma once
#include <memory>
template<typename Type> class Vec4;
template<typename Type> class Vec3;
template<typename Type>
class Vec2
{
public:
Vec2() : X(Type(0)), Y(Type(0)) { }
Vec2(float v) : X(v), Y(v) { }
Vec2(float x, float y) : X(x), Y(y) { }
float X, Y;
bool operator==(const Vec2 &other) const { return X == other.X && Y == other.Y; }
bool operator!=(const Vec2 &other) const { return X != other.X || Y != other.Y; }
};
template<typename Type>
class Vec3
{
public:
Vec3() : X(Type(0)), Y(Type(0)), Z(Type(0)) { }
Vec3(float v) : X(v), Y(v), Z(v) { }
Vec3(float x, float y, float z) : X(x), Y(y), Z(z) { }
Vec3(const Vec2<Type> &v, float z) : X(v.X), Y(v.Y), Z(z) { }
float X, Y, Z;
bool operator==(const Vec3 &other) const { return X == other.X && Y == other.Y && Z == other.Z; }
bool operator!=(const Vec3 &other) const { return X != other.X || Y != other.Y || Z != other.Z; }
};
template<typename Type>
class Vec4
{
public:
Vec4() : X(Type(0)), Y(Type(0)), Z(Type(0)), W(Type(0)) { }
Vec4(Type v) : X(v), Y(v), Z(v), W(v) { }
Vec4(Type x, Type y, Type z, Type w = 1.0f) : X(x), Y(y), Z(z), W(w) { }
Vec4(const Vec2<Type> &v, Type z, Type w) : X(v.X), Y(v.Y), Z(z), W(w) { }
Vec4(const Vec3<Type> &v, Type w) : X(v.X), Y(v.Y), Z(v.Z), W(w) { }
Type X, Y, Z, W;
bool operator==(const Vec4 &other) const { return X == other.X && Y == other.Y && Z == other.Z && W == other.W; }
bool operator!=(const Vec4 &other) const { return X != other.X || Y != other.Y || Z != other.Z || W != other.W; }
};
typedef Vec4<double> Vec4d;
typedef Vec3<double> Vec3d;
typedef Vec2<double> Vec2d;
typedef Vec4<float> Vec4f;
typedef Vec3<float> Vec3f;
typedef Vec2<float> Vec2f;
typedef Vec4<int32_t> Vec4i;
typedef Vec3<int32_t> Vec3i;
typedef Vec2<int32_t> Vec2i;
typedef Vec4<int16_t> Vec4s;
typedef Vec3<int16_t> Vec3s;
typedef Vec2<int16_t> Vec2s;
typedef Vec4<int8_t> Vec4b;
typedef Vec3<int8_t> Vec3b;
typedef Vec2<int8_t> Vec2b;
typedef Vec4<uint32_t> Vec4ui;
typedef Vec3<uint32_t> Vec3ui;
typedef Vec2<uint32_t> Vec2ui;
typedef Vec4<uint16_t> Vec4us;
typedef Vec3<uint16_t> Vec3us;
typedef Vec2<uint16_t> Vec2us;
typedef Vec4<uint8_t> Vec4ub;
typedef Vec3<uint8_t> Vec3ub;
typedef Vec2<uint8_t> Vec2ub;
enum class Handedness
{
Left,
Right
};
enum class ClipZRange
{
NegativePositiveW, // OpenGL, -wclip <= zclip <= wclip
ZeroPositiveW // Direct3D, 0 <= zclip <= wclip
};
class Mat4f
{
public:
static Mat4f Null();
static Mat4f Identity();
static Mat4f FromValues(float *matrix);
static Mat4f Transpose(const Mat4f &matrix);
static Mat4f Translate(float x, float y, float z);
static Mat4f Scale(float x, float y, float z);
static Mat4f Rotate(float angle, float x, float y, float z);
static Mat4f SwapYZ();
static Mat4f Perspective(float fovy, float aspect, float near, float far, Handedness handedness, ClipZRange clipZ);
static Mat4f Frustum(float left, float right, float bottom, float top, float near, float far, Handedness handedness, ClipZRange clipZ);
Vec4f operator*(const Vec4f &v) const;
Mat4f operator*(const Mat4f &m) const;
float Matrix[16];
};
class Mat3f
{
public:
Mat3f() { }
Mat3f(const Mat4f &matrix);
static Mat3f Null();
static Mat3f Identity();
static Mat3f FromValues(float *matrix);
static Mat3f Transpose(const Mat3f &matrix);
Vec3f operator*(const Vec3f &v) const;
Mat3f operator*(const Mat3f &m) const;
float Matrix[9];
};

View file

@ -1,197 +0,0 @@
/*
** Polygon Doom software renderer
** Copyright (c) 2016 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#include <stddef.h>
#include "templates.h"
#include "doomdef.h"
#include "i_system.h"
#include "w_wad.h"
#include "v_video.h"
#include "doomstat.h"
#include "st_stuff.h"
#include "g_game.h"
#include "g_level.h"
#include "r_data/r_translate.h"
#include "v_palette.h"
#include "r_data/colormaps.h"
#include "r_utility.h"
#include "tri_matrix.h"
#include "polyrenderer/drawers/poly_triangle.h"
#include "swrenderer/drawers/r_draw_rgba.h"
#include "swrenderer/viewport/r_viewport.h"
TriMatrix TriMatrix::null()
{
TriMatrix m;
memset(m.matrix, 0, sizeof(m.matrix));
return m;
}
TriMatrix TriMatrix::identity()
{
TriMatrix m = null();
m.matrix[0] = 1.0f;
m.matrix[5] = 1.0f;
m.matrix[10] = 1.0f;
m.matrix[15] = 1.0f;
return m;
}
TriMatrix TriMatrix::translate(float x, float y, float z)
{
TriMatrix m = identity();
m.matrix[0 + 3 * 4] = x;
m.matrix[1 + 3 * 4] = y;
m.matrix[2 + 3 * 4] = z;
return m;
}
TriMatrix TriMatrix::scale(float x, float y, float z)
{
TriMatrix m = null();
m.matrix[0 + 0 * 4] = x;
m.matrix[1 + 1 * 4] = y;
m.matrix[2 + 2 * 4] = z;
m.matrix[3 + 3 * 4] = 1;
return m;
}
TriMatrix TriMatrix::rotate(float angle, float x, float y, float z)
{
float c = cosf(angle);
float s = sinf(angle);
TriMatrix m = null();
m.matrix[0 + 0 * 4] = (x*x*(1.0f - c) + c);
m.matrix[0 + 1 * 4] = (x*y*(1.0f - c) - z*s);
m.matrix[0 + 2 * 4] = (x*z*(1.0f - c) + y*s);
m.matrix[1 + 0 * 4] = (y*x*(1.0f - c) + z*s);
m.matrix[1 + 1 * 4] = (y*y*(1.0f - c) + c);
m.matrix[1 + 2 * 4] = (y*z*(1.0f - c) - x*s);
m.matrix[2 + 0 * 4] = (x*z*(1.0f - c) - y*s);
m.matrix[2 + 1 * 4] = (y*z*(1.0f - c) + x*s);
m.matrix[2 + 2 * 4] = (z*z*(1.0f - c) + c);
m.matrix[3 + 3 * 4] = 1.0f;
return m;
}
TriMatrix TriMatrix::swapYZ()
{
TriMatrix m = null();
m.matrix[0 + 0 * 4] = 1.0f;
m.matrix[1 + 2 * 4] = 1.0f;
m.matrix[2 + 1 * 4] = -1.0f;
m.matrix[3 + 3 * 4] = 1.0f;
return m;
}
TriMatrix TriMatrix::perspective(float fovy, float aspect, float z_near, float z_far)
{
float f = (float)(1.0 / tan(fovy * M_PI / 360.0));
TriMatrix m = null();
m.matrix[0 + 0 * 4] = f / aspect;
m.matrix[1 + 1 * 4] = f;
m.matrix[2 + 2 * 4] = (z_far + z_near) / (z_near - z_far);
m.matrix[2 + 3 * 4] = (2.0f * z_far * z_near) / (z_near - z_far);
m.matrix[3 + 2 * 4] = -1.0f;
return m;
}
TriMatrix TriMatrix::frustum(float left, float right, float bottom, float top, float near, float far)
{
float a = (right + left) / (right - left);
float b = (top + bottom) / (top - bottom);
float c = -(far + near) / (far - near);
float d = -(2.0f * far) / (far - near);
TriMatrix m = null();
m.matrix[0 + 0 * 4] = 2.0f * near / (right - left);
m.matrix[1 + 1 * 4] = 2.0f * near / (top - bottom);
m.matrix[0 + 2 * 4] = a;
m.matrix[1 + 2 * 4] = b;
m.matrix[2 + 2 * 4] = c;
m.matrix[2 + 3 * 4] = d;
m.matrix[3 + 2 * 4] = -1;
return m;
}
TriMatrix TriMatrix::worldToView(const FRenderViewpoint &viewpoint)
{
TriMatrix m = null();
m.matrix[0 + 0 * 4] = (float)viewpoint.Sin;
m.matrix[0 + 1 * 4] = (float)-viewpoint.Cos;
m.matrix[1 + 2 * 4] = 1.0f;
m.matrix[2 + 0 * 4] = (float)-viewpoint.Cos;
m.matrix[2 + 1 * 4] = (float)-viewpoint.Sin;
m.matrix[3 + 3 * 4] = 1.0f;
return m * translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z);
}
TriMatrix TriMatrix::viewToClip(double focalTangent, double centerY, double YaspectMul)
{
float near = 5.0f;
float far = 65536.0f;
float width = (float)(focalTangent * near);
float top = (float)(centerY / viewheight * YaspectMul * near);
float bottom = (float)(top - YaspectMul * near);
return frustum(-width, width, bottom, top, near, far);
}
TriMatrix TriMatrix::operator*(const TriMatrix &mult) const
{
TriMatrix result;
for (int x = 0; x < 4; x++)
{
for (int y = 0; y < 4; y++)
{
result.matrix[x + y * 4] =
matrix[0 * 4 + x] * mult.matrix[y * 4 + 0] +
matrix[1 * 4 + x] * mult.matrix[y * 4 + 1] +
matrix[2 * 4 + x] * mult.matrix[y * 4 + 2] +
matrix[3 * 4 + x] * mult.matrix[y * 4 + 3];
}
}
return result;
}
FVector4 TriMatrix::operator*(const FVector4 &v) const
{
#ifdef NO_SSE
float vx = matrix[0 * 4 + 0] * v.X + matrix[1 * 4 + 0] * v.Y + matrix[2 * 4 + 0] * v.Z + matrix[3 * 4 + 0] * v.W;
float vy = matrix[0 * 4 + 1] * v.X + matrix[1 * 4 + 1] * v.Y + matrix[2 * 4 + 1] * v.Z + matrix[3 * 4 + 1] * v.W;
float vz = matrix[0 * 4 + 2] * v.X + matrix[1 * 4 + 2] * v.Y + matrix[2 * 4 + 2] * v.Z + matrix[3 * 4 + 2] * v.W;
float vw = matrix[0 * 4 + 3] * v.X + matrix[1 * 4 + 3] * v.Y + matrix[2 * 4 + 3] * v.Z + matrix[3 * 4 + 3] * v.W;
return{ vx, vy, vz, vw };
#else
__m128 m0 = _mm_loadu_ps(matrix);
__m128 m1 = _mm_loadu_ps(matrix + 4);
__m128 m2 = _mm_loadu_ps(matrix + 8);
__m128 m3 = _mm_loadu_ps(matrix + 12);
__m128 mv = _mm_loadu_ps(&v.X);
m0 = _mm_mul_ps(m0, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(0, 0, 0, 0)));
m1 = _mm_mul_ps(m1, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(1, 1, 1, 1)));
m2 = _mm_mul_ps(m2, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(2, 2, 2, 2)));
m3 = _mm_mul_ps(m3, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(3, 3, 3, 3)));
mv = _mm_add_ps(_mm_add_ps(_mm_add_ps(m0, m1), m2), m3);
FVector4 sv;
_mm_storeu_ps(&sv.X, mv);
return sv;
#endif
}

View file

@ -1,46 +0,0 @@
/*
** Polygon Doom software renderer
** Copyright (c) 2016 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#pragma once
struct TriVertex;
struct FRenderViewpoint;
struct TriMatrix
{
static TriMatrix null();
static TriMatrix identity();
static TriMatrix translate(float x, float y, float z);
static TriMatrix scale(float x, float y, float z);
static TriMatrix rotate(float angle, float x, float y, float z);
static TriMatrix swapYZ();
static TriMatrix perspective(float fovy, float aspect, float near, float far);
static TriMatrix frustum(float left, float right, float bottom, float top, float near, float far);
static TriMatrix worldToView(const FRenderViewpoint &viewpoint); // Software renderer world to view space transform
static TriMatrix viewToClip(double focalTangent, double centerY, double YaspectMul); // Software renderer shearing projection
FVector4 operator*(const FVector4 &v) const;
TriMatrix operator*(const TriMatrix &m) const;
float matrix[16];
};

View file

@ -4,7 +4,7 @@
#include "drawers/poly_draw_args.cpp"
#include "drawers/poly_triangle.cpp"
#include "drawers/screen_triangle.cpp"
#include "math/tri_matrix.cpp"
#include "math/gpu_types.cpp"
#include "scene/poly_cull.cpp"
#include "scene/poly_decal.cpp"
#include "scene/poly_particle.cpp"

View file

@ -38,10 +38,12 @@
#include "swrenderer/drawers/r_draw_rgba.h"
#include "swrenderer/viewport/r_viewport.h"
#include "swrenderer/r_swcolormaps.h"
#include "gl/system/gl_swframebuffer.h"
EXTERN_CVAR(Bool, r_shadercolormaps)
EXTERN_CVAR(Int, screenblocks)
EXTERN_CVAR(Float, r_visibility)
void InitGLRMapinfoData();
/////////////////////////////////////////////////////////////////////////////
@ -78,7 +80,9 @@ void PolyRenderer::RenderView(player_t *player)
}
Threads.MainThread()->FlushDrawQueue();
PolyDrawerWaitCycles.Clock();
DrawerThreads::WaitForWorkers();
PolyDrawerWaitCycles.Unclock();
}
void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines)
@ -111,6 +115,14 @@ void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int
void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines)
{
PolyTotalBatches = 0;
PolyTotalTriangles = 0;
PolyTotalDrawCalls = 0;
PolyCullCycles.Reset();
PolyOpaqueCycles.Reset();
PolyMaskedCycles.Reset();
PolyDrawerWaitCycles.Reset();
NetUpdate();
DontMapLines = dontmaplines;
@ -139,10 +151,15 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines)
ClearBuffers();
SetSceneViewport();
SetupPerspectiveMatrix();
MainPortal.SetViewpoint(WorldToClip, PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f), GetNextStencilValue());
MainPortal.Render(0);
Skydome.Render(Threads.MainThread(), WorldToClip);
MainPortal.RenderTranslucent(0);
PolyPortalViewpoint mainViewpoint;
mainViewpoint.WorldToView = WorldToView;
mainViewpoint.WorldToClip = WorldToClip;
mainViewpoint.StencilValue = GetNextStencilValue();
mainViewpoint.PortalPlane = PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f);
Scene.Render(&mainViewpoint);
Skydome.Render(Threads.MainThread(), WorldToView, WorldToClip);
Scene.RenderTranslucent(&mainViewpoint);
PlayerSprites.Render(Threads.MainThread());
Viewpoint.camera->renderflags = savedflags;
@ -159,9 +176,11 @@ void PolyRenderer::RenderRemainingPlayerSprites()
void PolyRenderer::ClearBuffers()
{
Threads.Clear();
PolyStencilBuffer::Instance()->Clear(RenderTarget->GetWidth(), RenderTarget->GetHeight(), 0);
PolyZBuffer::Instance()->Resize(RenderTarget->GetPitch(), RenderTarget->GetHeight());
PolyTriangleDrawer::ClearBuffers(RenderTarget);
NextStencilValue = 0;
Threads.MainThread()->SectorPortals.clear();
Threads.MainThread()->LinePortals.clear();
Threads.MainThread()->TranslucentObjects.clear();
}
void PolyRenderer::SetSceneViewport()
@ -177,11 +196,11 @@ void PolyRenderer::SetSceneViewport()
height = (screenblocks*SCREENHEIGHT / 10) & ~7;
int bottom = SCREENHEIGHT - (height + viewwindowy - ((height - viewheight) / 2));
PolyTriangleDrawer::set_viewport(viewwindowx, SCREENHEIGHT - bottom - height, viewwidth, height, RenderTarget);
PolyTriangleDrawer::SetViewport(Threads.MainThread()->DrawQueue, viewwindowx, SCREENHEIGHT - bottom - height, viewwidth, height, RenderTarget, false);
}
else // Rendering to camera texture
{
PolyTriangleDrawer::set_viewport(0, 0, RenderTarget->GetWidth(), RenderTarget->GetHeight(), RenderTarget);
PolyTriangleDrawer::SetViewport(Threads.MainThread()->DrawQueue, 0, 0, RenderTarget->GetWidth(), RenderTarget->GetHeight(), RenderTarget, false);
}
}
@ -195,7 +214,6 @@ void PolyRenderer::SetupPerspectiveMatrix()
bDidSetup = true;
}
// Code provided courtesy of Graf Zahl. Now we just have to plug it into the viewmatrix code...
// We have to scale the pitch to account for the pixel stretching, because the playsim doesn't know about this and treats it as 1:1.
double radPitch = Viewpoint.Angles.Pitch.Normalized180().Radians();
double angx = cos(radPitch);
@ -209,12 +227,24 @@ void PolyRenderer::SetupPerspectiveMatrix()
float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(Viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees);
WorldToView =
TriMatrix::rotate((float)Viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) *
TriMatrix::rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) *
TriMatrix::rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) *
TriMatrix::scale(1.0f, level.info->pixelstretch, 1.0f) *
TriMatrix::swapYZ() *
TriMatrix::translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z);
Mat4f::Rotate((float)Viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) *
Mat4f::Rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) *
Mat4f::Rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) *
Mat4f::Scale(1.0f, level.info->pixelstretch, 1.0f) *
Mat4f::SwapYZ() *
Mat4f::Translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z);
WorldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * WorldToView;
WorldToClip = Mat4f::Perspective(fovy, ratio, 5.0f, 65535.0f, Handedness::Right, ClipZRange::NegativePositiveW) * WorldToView;
}
cycle_t PolyCullCycles, PolyOpaqueCycles, PolyMaskedCycles, PolyDrawerWaitCycles;
int PolyTotalBatches, PolyTotalTriangles, PolyTotalDrawCalls;
ADD_STAT(polyfps)
{
FString out;
out.Format("frame=%04.1f ms cull=%04.1f ms opaque=%04.1f ms masked=%04.1f ms drawers=%04.1f ms",
FrameCycles.TimeMS(), PolyCullCycles.TimeMS(), PolyOpaqueCycles.TimeMS(), PolyMaskedCycles.TimeMS(), PolyDrawerWaitCycles.TimeMS());
out.AppendFormat("\nbatches drawn: %d triangles drawn: %d drawcalls: %d", PolyTotalBatches, PolyTotalTriangles, PolyTotalDrawCalls);
return out;
}

View file

@ -34,12 +34,16 @@
#include "scene/poly_light.h"
#include "swrenderer/r_memory.h"
#include "poly_renderthread.h"
#include "stats.h"
class AActor;
class DCanvas;
class DrawerCommandQueue;
typedef std::shared_ptr<DrawerCommandQueue> DrawerCommandQueuePtr;
extern cycle_t PolyCullCycles, PolyOpaqueCycles, PolyMaskedCycles, PolyDrawerWaitCycles;
extern int PolyTotalBatches, PolyTotalTriangles, PolyTotalDrawCalls;
class PolyRenderer
{
public:
@ -60,9 +64,10 @@ public:
FViewWindow Viewwindow;
FRenderViewpoint Viewpoint;
PolyLightVisibility Light;
RenderPolyScene Scene;
TriMatrix WorldToView;
TriMatrix WorldToClip;
Mat4f WorldToView;
Mat4f WorldToClip;
private:
void RenderActorView(AActor *actor, bool dontmaplines);
@ -70,7 +75,6 @@ private:
void SetSceneViewport();
void SetupPerspectiveMatrix();
RenderPolyScene MainPortal;
PolySkyDome Skydome;
RenderPolyPlayerSprites PlayerSprites;
uint32_t NextStencilValue = 0;

View file

@ -29,6 +29,9 @@
class DrawerCommandQueue;
typedef std::shared_ptr<DrawerCommandQueue> DrawerCommandQueuePtr;
class RenderMemory;
class PolyTranslucentObject;
class PolyDrawSectorPortal;
class PolyDrawLinePortal;
class PolyRenderThread
{
@ -46,6 +49,10 @@ public:
std::unique_ptr<RenderMemory> FrameMemory;
DrawerCommandQueuePtr DrawQueue;
std::vector<PolyTranslucentObject *> TranslucentObjects;
std::vector<std::unique_ptr<PolyDrawSectorPortal>> SectorPortals;
std::vector<std::unique_ptr<PolyDrawLinePortal>> LinePortals;
// Make sure texture can accessed safely
void PrepareTexture(FTexture *texture, FRenderStyle style);
@ -72,6 +79,8 @@ public:
PolyRenderThread *MainThread() { return Threads.front().get(); }
int NumThreads() const { return (int)Threads.size(); }
std::vector<std::unique_ptr<PolyRenderThread>> Threads;
private:
void RenderThreadSlice(PolyRenderThread *thread);
@ -80,7 +89,6 @@ private:
std::function<void(PolyRenderThread *)> WorkerCallback;
std::vector<std::unique_ptr<PolyRenderThread>> Threads;
std::mutex start_mutex;
std::condition_variable start_condition;
bool shutdown_flag = false;

View file

@ -32,7 +32,7 @@
#include "a_sharedglobal.h"
#include "swrenderer/scene/r_scene.h"
void RenderPolyDecal::RenderWallDecals(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue)
void RenderPolyDecal::RenderWallDecals(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue)
{
if (line->linedef == nullptr && line->sidedef == nullptr)
return;
@ -40,11 +40,11 @@ void RenderPolyDecal::RenderWallDecals(PolyRenderThread *thread, const TriMatrix
for (DBaseDecal *decal = line->sidedef->AttachedDecals; decal != nullptr; decal = decal->WallNext)
{
RenderPolyDecal render;
render.Render(thread, worldToClip, clipPlane, decal, line, stencilValue);
render.Render(thread, clipPlane, decal, line, stencilValue);
}
}
void RenderPolyDecal::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue)
void RenderPolyDecal::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue)
{
if (decal->RenderFlags & RF_INVISIBLE || !viewactive || !decal->PicNum.isValid())
return;
@ -186,15 +186,12 @@ void RenderPolyDecal::Render(PolyRenderThread *thread, const TriMatrix &worldToC
args.SetLight(GetColorTable(front->Colormap), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), fullbrightSprite);
args.SetColor(0xff000000 | decal->AlphaColor, decal->AlphaColor >> 24);
args.SetStyle(decal->RenderStyle, decal->Alpha, decal->AlphaColor, decal->Translation, tex, false);
args.SetTransform(&worldToClip);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue);
args.SetClipPlane(0, clipPlane);
args.SetDepthTest(true);
args.SetWriteStencil(false);
args.SetWriteDepth(false);
args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan);
}
void RenderPolyDecal::GetDecalSectors(DBaseDecal *decal, const seg_t *line, sector_t **front, sector_t **back)

View file

@ -27,10 +27,10 @@
class RenderPolyDecal
{
public:
static void RenderWallDecals(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue);
static void RenderWallDecals(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const seg_t *line, uint32_t stencilValue);
private:
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue);
void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t stencilValue);
void GetDecalSectors(DBaseDecal *decal, const seg_t *line, sector_t **front, sector_t **back);
double GetDecalZ(DBaseDecal *decal, const seg_t *line, sector_t *front, sector_t *back);

View file

@ -36,13 +36,13 @@
void gl_FlushModels();
bool polymodelsInUse;
void PolyRenderModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
{
PolyModelRenderer renderer(thread, worldToClip, clipPlane, stencilValue);
renderer.RenderModel(x, y, z, smf, actor);
}
void PolyRenderHUDModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy)
void PolyRenderHUDModel(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy)
{
PolyModelRenderer renderer(thread, worldToClip, clipPlane, stencilValue);
renderer.RenderHUDModel(psp, ofsx, ofsy);
@ -50,7 +50,7 @@ void PolyRenderHUDModel(PolyRenderThread *thread, const TriMatrix &worldToClip,
/////////////////////////////////////////////////////////////////////////////
PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue) : Thread(thread), WorldToClip(worldToClip), ClipPlane(clipPlane), StencilValue(stencilValue)
PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue) : Thread(thread), WorldToClip(worldToClip), ClipPlane(clipPlane), StencilValue(stencilValue)
{
if (!polymodelsInUse)
{
@ -62,7 +62,8 @@ PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const TriMatrix &
void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix)
{
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.matrix);
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.Matrix);
SetTransform();
}
void PolyModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
@ -85,14 +86,14 @@ void PolyModelRenderer::ResetVertexBuffer()
VSMatrix PolyModelRenderer::GetViewToWorldMatrix()
{
TriMatrix swapYZ = TriMatrix::null();
swapYZ.matrix[0 + 0 * 4] = 1.0f;
swapYZ.matrix[1 + 2 * 4] = 1.0f;
swapYZ.matrix[2 + 1 * 4] = 1.0f;
swapYZ.matrix[3 + 3 * 4] = 1.0f;
Mat4f swapYZ = Mat4f::Null();
swapYZ.Matrix[0 + 0 * 4] = 1.0f;
swapYZ.Matrix[1 + 2 * 4] = 1.0f;
swapYZ.Matrix[2 + 1 * 4] = 1.0f;
swapYZ.Matrix[3 + 3 * 4] = 1.0f;
VSMatrix worldToView;
worldToView.loadMatrix((PolyRenderer::Instance()->WorldToView * swapYZ).matrix);
worldToView.loadMatrix((PolyRenderer::Instance()->WorldToView * swapYZ).Matrix);
VSMatrix objectToWorld;
worldToView.inverseMatrix(objectToWorld);
@ -102,7 +103,8 @@ VSMatrix PolyModelRenderer::GetViewToWorldMatrix()
void PolyModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix)
{
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.matrix);
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.Matrix);
SetTransform();
}
void PolyModelRenderer::EndDrawHUDModel(AActor *actor)
@ -120,6 +122,17 @@ void PolyModelRenderer::SetMaterial(FTexture *skin, bool clampNoFilter, int tran
SkinTexture = skin;
}
void PolyModelRenderer::SetTransform()
{
Mat4f swapYZ = Mat4f::Null();
swapYZ.Matrix[0 + 0 * 4] = 1.0f;
swapYZ.Matrix[1 + 2 * 4] = 1.0f;
swapYZ.Matrix[2 + 1 * 4] = 1.0f;
swapYZ.Matrix[3 + 3 * 4] = 1.0f;
PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject<Mat4f>(WorldToClip * swapYZ * ObjectToWorld));
}
void PolyModelRenderer::DrawArrays(int start, int count)
{
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
@ -131,19 +144,8 @@ void PolyModelRenderer::DrawArrays(int start, int count)
bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT));
int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight;
TriMatrix swapYZ = TriMatrix::null();
swapYZ.matrix[0 + 0 * 4] = 1.0f;
swapYZ.matrix[1 + 2 * 4] = 1.0f;
swapYZ.matrix[2 + 1 * 4] = 1.0f;
swapYZ.matrix[3 + 3 * 4] = 1.0f;
TriMatrix *transform = Thread->FrameMemory->NewObject<TriMatrix>();
*transform = WorldToClip * swapYZ * ObjectToWorld;
PolyDrawArgs args;
args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite);
args.SetTransform(transform);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(StencilValue);
args.SetClipPlane(0, PolyClipPlane());
args.SetStyle(TriBlendMode::TextureOpaque);
@ -151,7 +153,7 @@ void PolyModelRenderer::DrawArrays(int start, int count)
args.SetDepthTest(true);
args.SetWriteDepth(true);
args.SetWriteStencil(false);
args.DrawArray(Thread, VertexBuffer + start, count);
args.DrawArray(Thread->DrawQueue, VertexBuffer + start, count);
}
void PolyModelRenderer::DrawElements(int numIndices, size_t offset)
@ -165,19 +167,8 @@ void PolyModelRenderer::DrawElements(int numIndices, size_t offset)
bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT));
int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight;
TriMatrix swapYZ = TriMatrix::null();
swapYZ.matrix[0 + 0 * 4] = 1.0f;
swapYZ.matrix[1 + 2 * 4] = 1.0f;
swapYZ.matrix[2 + 1 * 4] = 1.0f;
swapYZ.matrix[3 + 3 * 4] = 1.0f;
TriMatrix *transform = Thread->FrameMemory->NewObject<TriMatrix>();
*transform = WorldToClip * swapYZ * ObjectToWorld;
PolyDrawArgs args;
args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite);
args.SetTransform(transform);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(StencilValue);
args.SetClipPlane(0, PolyClipPlane());
args.SetStyle(TriBlendMode::TextureOpaque);
@ -185,12 +176,12 @@ void PolyModelRenderer::DrawElements(int numIndices, size_t offset)
args.SetDepthTest(true);
args.SetWriteDepth(true);
args.SetWriteStencil(false);
args.DrawElements(Thread, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices);
args.DrawElements(Thread->DrawQueue, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices);
}
double PolyModelRenderer::GetTimeFloat()
{
return (float)I_msTime() * (float)TICRATE / 1000.0f;
return (double)I_msTime() * (double)TICRATE / 1000.;
}
/////////////////////////////////////////////////////////////////////////////
@ -227,7 +218,7 @@ void PolyModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int fr
{
PolyModelRenderer *polyrenderer = (PolyModelRenderer *)renderer;
if (true)//if (frame1 == frame2 || size == 0 || polyrenderer->InterpolationFactor == 0.f)
if (frame1 == frame2 || size == 0 || polyrenderer->InterpolationFactor == 0.f)
{
TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory<TriVertex>(size);
@ -252,11 +243,12 @@ void PolyModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int fr
TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory<TriVertex>(size);
float frac = polyrenderer->InterpolationFactor;
float inv_frac = 1.0f - frac;
for (unsigned int i = 0; i < size; i++)
{
vertices[i].x = mVertexBuffer[frame1 + i].x * (1.0f - frac) + mVertexBuffer[frame2 + i].x * frac;
vertices[i].y = mVertexBuffer[frame1 + i].y * (1.0f - frac) + mVertexBuffer[frame2 + i].y * frac;
vertices[i].z = mVertexBuffer[frame1 + i].z * (1.0f - frac) + mVertexBuffer[frame2 + i].z * frac;
vertices[i].x = mVertexBuffer[frame1 + i].x * inv_frac + mVertexBuffer[frame2 + i].x * frac;
vertices[i].y = mVertexBuffer[frame1 + i].y * inv_frac + mVertexBuffer[frame2 + i].y * frac;
vertices[i].z = mVertexBuffer[frame1 + i].z * inv_frac + mVertexBuffer[frame2 + i].z * frac;
vertices[i].w = 1.0f;
vertices[i].u = mVertexBuffer[frame1 + i].u;
vertices[i].v = mVertexBuffer[frame1 + i].v;

View file

@ -26,13 +26,13 @@
#include "r_data/matrix.h"
#include "r_data/models/models.h"
void PolyRenderModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor);
void PolyRenderHUDModel(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy);
void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor);
void PolyRenderHUDModel(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue, DPSprite *psp, float ofsx, float ofsy);
class PolyModelRenderer : public FModelRenderer
{
public:
PolyModelRenderer(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue);
PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, const PolyClipPlane &clipPlane, uint32_t stencilValue);
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
@ -48,13 +48,15 @@ public:
void DrawElements(int numIndices, size_t offset) override;
double GetTimeFloat() override;
void SetTransform();
PolyRenderThread *Thread = nullptr;
const TriMatrix &WorldToClip;
const Mat4f &WorldToClip;
const PolyClipPlane &ClipPlane;
uint32_t StencilValue = 0;
AActor *ModelActor = nullptr;
TriMatrix ObjectToWorld;
Mat4f ObjectToWorld;
FTexture *SkinTexture = nullptr;
unsigned int *IndexBuffer = nullptr;
TriVertex *VertexBuffer = nullptr;

View file

@ -32,7 +32,7 @@
EXTERN_CVAR(Int, gl_particles_style)
void RenderPolyParticle::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue)
void RenderPolyParticle::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue)
{
double timefrac = r_viewpoint.TicFrac;
if (paused || bglobal.freeze || (level.flags2 & LEVEL2_FROZEN))
@ -82,14 +82,12 @@ void RenderPolyParticle::Render(PolyRenderThread *thread, const TriMatrix &world
args.SetDepthTest(true);
args.SetColor(particle->color | 0xff000000, particle->color >> 24);
args.SetStyle(TriBlendMode::Shaded, particle->alpha, 1.0 - particle->alpha);
args.SetTransform(&worldToClip);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(false);
args.SetWriteDepth(false);
args.SetClipPlane(0, clipPlane);
args.SetTexture(GetParticleTexture(), ParticleTextureSize, ParticleTextureSize);
args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan);
}
uint8_t *RenderPolyParticle::GetParticleTexture()

View file

@ -28,7 +28,7 @@
class RenderPolyParticle
{
public:
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue);
void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, particle_t *particle, subsector_t *sub, uint32_t stencilValue);
private:
static uint8_t *GetParticleTexture();
@ -45,10 +45,10 @@ class PolyTranslucentParticle : public PolyTranslucentObject
public:
PolyTranslucentParticle(particle_t *particle, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue) : PolyTranslucentObject(subsectorDepth, 0.0), particle(particle), sub(sub), StencilValue(stencilValue) { }
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override
void Render(PolyRenderThread *thread, const PolyClipPlane &portalPlane) override
{
RenderPolyParticle spr;
spr.Render(thread, worldToClip, portalPlane, particle, sub, StencilValue + 1);
spr.Render(thread, portalPlane, particle, sub, StencilValue + 1);
}
particle_t *particle = nullptr;

View file

@ -36,30 +36,30 @@
EXTERN_CVAR(Int, r_3dfloors)
void RenderPolyPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
void RenderPolyPlane::RenderPlanes(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
{
if (fakeflat.FrontSector->CenterFloor() == fakeflat.FrontSector->CenterCeiling())
return;
RenderPolyPlane plane;
plane.Render(thread, worldToClip, clipPlane, fakeflat, stencilValue, true, skyCeilingHeight, sectorPortals);
plane.Render(thread, worldToClip, clipPlane, fakeflat, stencilValue, false, skyFloorHeight, sectorPortals);
plane.Render(thread, clipPlane, fakeflat, stencilValue, true, skyCeilingHeight, sectorPortals);
plane.Render(thread, clipPlane, fakeflat, stencilValue, false, skyFloorHeight, sectorPortals);
}
void RenderPolyPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
void RenderPolyPlane::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
{
FSectorPortal *portal = fakeflat.FrontSector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor);
if (!portal || (portal->mFlags & PORTSF_INSKYBOX) == PORTSF_INSKYBOX) // Do not recurse into portals we already recursed into
{
RenderNormal(thread, worldToClip, clipPlane, fakeflat, stencilValue, ceiling, skyHeight);
RenderNormal(thread, clipPlane, fakeflat, stencilValue, ceiling, skyHeight);
}
else
{
RenderPortal(thread, worldToClip, clipPlane, fakeflat, stencilValue, ceiling, skyHeight, portal, sectorPortals);
RenderPortal(thread, clipPlane, fakeflat, stencilValue, ceiling, skyHeight, portal, sectorPortals);
}
}
void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight)
void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight)
{
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
@ -76,35 +76,30 @@ void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &wo
PolyDrawArgs args;
SetLightLevel(thread, args, fakeflat, ceiling);
SetDynLights(thread, args, fakeflat.Subsector, ceiling);
args.SetTransform(&worldToClip);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue + 1);
args.SetClipPlane(0, clipPlane);
args.SetTexture(tex, DefaultRenderStyle());
args.SetStyle(TriBlendMode::TextureOpaque);
args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan);
}
else
{
TriVertex *vertices = CreateSkyPlaneVertices(thread, fakeflat.Subsector, skyHeight);
PolyDrawArgs args;
args.SetTransform(&worldToClip);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue + 1);
args.SetClipPlane(0, clipPlane);
args.SetWriteStencil(true, 255);
args.SetWriteColor(false);
args.SetWriteDepth(false);
args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan);
RenderSkyWalls(thread, args, fakeflat.Subsector, nullptr, ceiling, skyHeight);
}
}
void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
{
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
@ -160,19 +155,16 @@ void RenderPolyPlane::RenderPortal(PolyRenderThread *thread, const TriMatrix &wo
TriVertex *vertices = CreateSkyPlaneVertices(thread, fakeflat.Subsector, skyHeight);
PolyDrawArgs args;
args.SetTransform(&worldToClip);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue + 1);
args.SetClipPlane(0, clipPlane);
args.SetWriteStencil(true, polyportal->StencilValue);
args.SetWriteColor(false);
args.SetWriteDepth(false);
args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan);
RenderSkyWalls(thread, args, fakeflat.Subsector, polyportal, ceiling, skyHeight);
polyportal->Shape.push_back({ vertices, (int)fakeflat.Subsector->numlines, true });
polyportal->Shape.push_back({ vertices, (int)fakeflat.Subsector->numlines });
}
void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight)
@ -246,11 +238,11 @@ void RenderPolyPlane::RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &arg
wallvert[3] = GetSkyVertex(line->v1, skyHeight);
}
args.DrawArray(thread, wallvert, 4, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, wallvert, 4, PolyDrawMode::TriangleFan);
if (polyportal)
{
polyportal->Shape.push_back({ wallvert, 4, args.FaceCullCCW() });
polyportal->Shape.push_back({ wallvert, 4 });
}
}
}
@ -421,7 +413,7 @@ PolyPlaneUVTransform::PolyPlaneUVTransform(const FTransform &transform, FTexture
/////////////////////////////////////////////////////////////////////////////
void Render3DFloorPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector<PolyTranslucentObject *> &translucentObjects)
void Render3DFloorPlane::RenderPlanes(PolyRenderThread *thread, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector<PolyTranslucentObject *> &translucentObjects)
{
if (!r_3dfloors || sub->sector->CenterFloor() == sub->sector->CenterCeiling())
return;
@ -465,7 +457,7 @@ void Render3DFloorPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix
}
if (!plane.Masked)
plane.Render(thread, worldToClip, clipPlane);
plane.Render(thread, clipPlane);
else
translucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucent3DFloorPlane>(plane, subsectorDepth));
}
@ -505,14 +497,14 @@ void Render3DFloorPlane::RenderPlanes(PolyRenderThread *thread, const TriMatrix
}
if (!plane.Masked)
plane.Render(thread, worldToClip, clipPlane);
plane.Render(thread, clipPlane);
else
translucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucent3DFloorPlane>(plane, subsectorDepth));
}
}
}
void Render3DFloorPlane::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane)
void Render3DFloorPlane::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane)
{
FTextureID picnum = ceiling ? *fakeFloor->bottom.texture : *fakeFloor->top.texture;
FTexture *tex = TexMan(picnum);
@ -555,7 +547,6 @@ void Render3DFloorPlane::Render(PolyRenderThread *thread, const TriMatrix &world
PolyDrawArgs args;
args.SetLight(GetColorTable(sub->sector->Colormap), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false);
args.SetTransform(&worldToClip);
if (!Masked)
{
args.SetStyle(TriBlendMode::TextureOpaque);
@ -567,12 +558,10 @@ void Render3DFloorPlane::Render(PolyRenderThread *thread, const TriMatrix &world
args.SetStyle(TriBlendMode::TextureAdd, srcalpha, destalpha);
args.SetDepthTest(true);
args.SetWriteDepth(true);
args.SetWriteStencil(false);
}
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue + 1);
args.SetTexture(tex, DefaultRenderStyle());
args.SetClipPlane(0, clipPlane);
args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, sub->numlines, PolyDrawMode::TriangleFan);
}

View file

@ -57,13 +57,13 @@ private:
class RenderPolyPlane
{
public:
static void RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
static void RenderPlanes(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
private:
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
void RenderPortal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
void RenderNormal(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight);
void RenderPortal(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, FSectorPortal *portal, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
void RenderNormal(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight);
void RenderSkyWalls(PolyRenderThread *thread, PolyDrawArgs &args, subsector_t *sub, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight);
@ -79,9 +79,9 @@ private:
class Render3DFloorPlane
{
public:
static void RenderPlanes(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector<PolyTranslucentObject *> &translucentObjects);
static void RenderPlanes(PolyRenderThread *thread, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector<PolyTranslucentObject *> &translucentObjects);
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane);
void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane);
subsector_t *sub = nullptr;
uint32_t stencilValue = 0;
@ -97,9 +97,9 @@ class PolyTranslucent3DFloorPlane : public PolyTranslucentObject
public:
PolyTranslucent3DFloorPlane(Render3DFloorPlane plane, uint32_t subsectorDepth) : PolyTranslucentObject(subsectorDepth, 1e7), plane(plane) { }
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override
void Render(PolyRenderThread *thread, const PolyClipPlane &portalPlane) override
{
plane.Render(thread, worldToClip, portalPlane);
plane.Render(thread, portalPlane);
}
Render3DFloorPlane plane;

View file

@ -43,8 +43,6 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread)
//
// We also can't move it because the model render code relies on it
//renderHUDModel = gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
int i;
@ -62,6 +60,8 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread)
(r_deathcamera && viewpoint.camera->health <= 0))
return;
renderHUDModel = gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
PolyTransferHeights fakeflat(viewpoint.camera->subsector);
FDynamicColormap *basecolormap;

View file

@ -30,6 +30,7 @@
#include "poly_portal.h"
#include "polyrenderer/poly_renderer.h"
#include "polyrenderer/scene/poly_light.h"
#include "polyrenderer/scene/poly_scene.h"
/////////////////////////////////////////////////////////////////////////////
@ -58,31 +59,35 @@ void PolyDrawSectorPortal::Render(int portalDepth)
float ratio = viewwindow.WidescreenRatio;
float fovratio = (viewwindow.WidescreenRatio >= 1.3f) ? 1.333333f : ratio;
float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees);
TriMatrix worldToView =
TriMatrix::rotate((float)viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) *
TriMatrix::rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) *
TriMatrix::rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) *
TriMatrix::scale(1.0f, level.info->pixelstretch, 1.0f) *
TriMatrix::swapYZ() *
TriMatrix::translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z);
TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
Mat4f worldToView =
Mat4f::Rotate((float)viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) *
Mat4f::Rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) *
Mat4f::Rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) *
Mat4f::Scale(1.0f, level.info->pixelstretch, 1.0f) *
Mat4f::SwapYZ() *
Mat4f::Translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z);
Mat4f worldToClip = Mat4f::Perspective(fovy, ratio, 5.0f, 65535.0f, Handedness::Right, ClipZRange::NegativePositiveW) * worldToView;
PolyClipPlane portalPlane(0.0f, 0.0f, 0.0f, 1.0f);
RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue);
//RenderPortal.SetPortalSegments(Segments);
RenderPortal.Render(portalDepth);
PortalViewpoint = PolyPortalViewpoint();
PortalViewpoint.WorldToView = worldToView;
PortalViewpoint.WorldToClip = worldToClip;
PortalViewpoint.StencilValue = StencilValue;
PortalViewpoint.PortalPlane = PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f);
PortalViewpoint.PortalDepth = portalDepth;
PolyRenderer::Instance()->Scene.Render(&PortalViewpoint);
RestoreGlobals();
}
void PolyDrawSectorPortal::RenderTranslucent(int portalDepth)
void PolyDrawSectorPortal::RenderTranslucent()
{
if (Portal->mType == PORTS_HORIZON || Portal->mType == PORTS_PLANE)
return;
SaveGlobals();
RenderPortal.RenderTranslucent(portalDepth);
PolyRenderer::Instance()->Scene.RenderTranslucent(&PortalViewpoint);
RestoreGlobals();
}
@ -169,16 +174,16 @@ void PolyDrawLinePortal::Render(int portalDepth)
float ratio = viewwindow.WidescreenRatio;
float fovratio = (viewwindow.WidescreenRatio >= 1.3f) ? 1.333333f : ratio;
float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees);
TriMatrix worldToView =
TriMatrix::rotate((float)viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) *
TriMatrix::rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) *
TriMatrix::rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) *
TriMatrix::scale(1.0f, level.info->pixelstretch, 1.0f) *
TriMatrix::swapYZ() *
TriMatrix::translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z);
Mat4f worldToView =
Mat4f::Rotate((float)viewpoint.Angles.Roll.Radians(), 0.0f, 0.0f, 1.0f) *
Mat4f::Rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) *
Mat4f::Rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) *
Mat4f::Scale(1.0f, level.info->pixelstretch, 1.0f) *
Mat4f::SwapYZ() *
Mat4f::Translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z);
if (Mirror)
worldToView = TriMatrix::scale(-1.0f, 1.0f, 1.0f) * worldToView;
TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
worldToView = Mat4f::Scale(-1.0f, 1.0f, 1.0f) * worldToView;
Mat4f worldToClip = Mat4f::Perspective(fovy, ratio, 5.0f, 65535.0f, Handedness::Right, ClipZRange::NegativePositiveW) * worldToView;
// Find portal destination line and make sure it faces the right way
line_t *clipLine = Portal ? Portal->mDestination : Mirror;
@ -202,18 +207,23 @@ void PolyDrawLinePortal::Render(int portalDepth)
Segments.clear();
Segments.push_back({ angle1, angle2 });*/
RenderPortal.LastPortalLine = clipLine;
RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue);
//RenderPortal.SetPortalSegments(Segments);
RenderPortal.Render(portalDepth);
PortalViewpoint = PolyPortalViewpoint();
PortalViewpoint.WorldToView = worldToView;
PortalViewpoint.WorldToClip = worldToClip;
PortalViewpoint.StencilValue = StencilValue;
PortalViewpoint.PortalPlane = portalPlane;
PortalViewpoint.PortalDepth = portalDepth;
PortalViewpoint.LastPortalLine = clipLine;
PolyRenderer::Instance()->Scene.Render(&PortalViewpoint);
RestoreGlobals();
}
void PolyDrawLinePortal::RenderTranslucent(int portalDepth)
void PolyDrawLinePortal::RenderTranslucent()
{
SaveGlobals();
RenderPortal.RenderTranslucent(portalDepth);
PolyRenderer::Instance()->Scene.RenderTranslucent(&PortalViewpoint);
RestoreGlobals();
}
@ -304,7 +314,7 @@ void PolyDrawLinePortal::SaveGlobals()
R_SetViewAngle(viewpoint, viewwindow);
if (Mirror)
PolyTriangleDrawer::toggle_mirror();
PolyTriangleDrawer::ToggleMirror(PolyRenderer::Instance()->Threads.MainThread()->DrawQueue);
}
void PolyDrawLinePortal::RestoreGlobals()
@ -328,5 +338,5 @@ void PolyDrawLinePortal::RestoreGlobals()
R_SetViewAngle(viewpoint, viewwindow);
if (Mirror)
PolyTriangleDrawer::toggle_mirror();
PolyTriangleDrawer::ToggleMirror(PolyRenderer::Instance()->Threads.MainThread()->DrawQueue);
}

View file

@ -26,10 +26,9 @@
struct PolyPortalVertexRange
{
PolyPortalVertexRange(const TriVertex *vertices, int count, bool ccw) : Vertices(vertices), Count(count), Ccw(ccw) { }
PolyPortalVertexRange(const TriVertex *vertices, int count) : Vertices(vertices), Count(count) { }
const TriVertex *Vertices;
int Count;
bool Ccw;
};
class PolyPortalSegment
@ -45,7 +44,7 @@ public:
PolyDrawSectorPortal(FSectorPortal *portal, bool ceiling);
void Render(int portalDepth);
void RenderTranslucent(int portalDepth);
void RenderTranslucent();
FSectorPortal *Portal = nullptr;
uint32_t StencilValue = 0;
@ -57,7 +56,7 @@ private:
void RestoreGlobals();
bool Ceiling;
RenderPolyScene RenderPortal;
PolyPortalViewpoint PortalViewpoint;
int savedextralight;
DVector3 savedpos;
@ -74,7 +73,7 @@ public:
PolyDrawLinePortal(line_t *mirror);
void Render(int portalDepth);
void RenderTranslucent(int portalDepth);
void RenderTranslucent();
FLinePortal *Portal = nullptr;
line_t *Mirror = nullptr;
@ -86,7 +85,7 @@ private:
void SaveGlobals();
void RestoreGlobals();
RenderPolyScene RenderPortal;
PolyPortalViewpoint PortalViewpoint;
int savedextralight;
DVector3 savedpos;

View file

@ -47,22 +47,45 @@ RenderPolyScene::~RenderPolyScene()
{
}
void RenderPolyScene::SetViewpoint(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane, uint32_t stencilValue)
void RenderPolyScene::Render(PolyPortalViewpoint *viewpoint)
{
WorldToClip = worldToClip;
StencilValue = stencilValue;
PortalPlane = portalPlane;
}
CurrentViewpoint = viewpoint;
void RenderPolyScene::Render(int portalDepth)
{
PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread();
SectorPortals.clear();
LinePortals.clear();
Cull.CullScene(PortalPlane);
CurrentViewpoint->ObjectsStart = thread->TranslucentObjects.size();
CurrentViewpoint->SectorPortalsStart = thread->SectorPortals.size();
CurrentViewpoint->LinePortalsStart = thread->LinePortals.size();
PolyCullCycles.Clock();
Cull.CullScene(CurrentViewpoint->PortalPlane);
PolyCullCycles.Unclock();
RenderSectors();
RenderPortals(portalDepth);
PolyMaskedCycles.Clock();
const auto &rviewpoint = PolyRenderer::Instance()->Viewpoint;
for (uint32_t sectorIndex : Cull.SeenSectors)
{
sector_t *sector = &level.sectors[sectorIndex];
for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext)
{
DVector2 left, right;
if (!RenderPolySprite::GetLine(thing, left, right))
continue;
double distanceSquared = (thing->Pos() - rviewpoint.Pos).LengthSquared();
AddSprite(thread, thing, distanceSquared, left, right);
}
}
PolyMaskedCycles.Unclock();
CurrentViewpoint->ObjectsEnd = thread->TranslucentObjects.size();
CurrentViewpoint->SectorPortalsEnd = thread->SectorPortals.size();
CurrentViewpoint->LinePortalsEnd = thread->LinePortals.size();
RenderPortals();
CurrentViewpoint = nullptr;
}
void RenderPolyScene::RenderSectors()
@ -72,11 +95,18 @@ void RenderPolyScene::RenderSectors()
int totalcount = (int)Cull.PvsSubsectors.size();
uint32_t *subsectors = Cull.PvsSubsectors.data();
TranslucentObjects.resize(PolyRenderer::Instance()->Threads.NumThreads());
PolyOpaqueCycles.Clock();
PolyRenderer::Instance()->Threads.RenderThreadSlices(totalcount, [&](PolyRenderThread *thread)
{
TranslucentObjects[thread->ThreadIndex].clear();
PolyTriangleDrawer::SetTransform(thread->DrawQueue, thread->FrameMemory->NewObject<Mat4f>(CurrentViewpoint->WorldToClip));
if (thread != mainthread)
{
thread->TranslucentObjects.clear();
thread->SectorPortals.clear();
thread->LinePortals.clear();
}
int start = thread->Start;
int end = thread->End;
@ -86,9 +116,11 @@ void RenderPolyScene::RenderSectors()
}
}, [&](PolyRenderThread *thread)
{
const auto &objects = TranslucentObjects[thread->ThreadIndex];
TranslucentObjects[0].insert(TranslucentObjects[0].end(), objects.begin(), objects.end());
const auto &objects = thread->TranslucentObjects;
mainthread->TranslucentObjects.insert(mainthread->TranslucentObjects.end(), objects.begin(), objects.end());
});
PolyOpaqueCycles.Unclock();
}
void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth)
@ -121,15 +153,15 @@ void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub
RenderPolyNode(thread, &sub->BSP->Nodes.Last(), subsectorDepth, frontsector);
}
Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects[thread->ThreadIndex]);
RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals);
Render3DFloorPlane::RenderPlanes(thread, CurrentViewpoint->PortalPlane, sub, CurrentViewpoint->StencilValue, subsectorDepth, thread->TranslucentObjects);
RenderPolyPlane::RenderPlanes(thread, CurrentViewpoint->PortalPlane, sub, CurrentViewpoint->StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals);
}
else
{
PolyTransferHeights fakeflat(sub);
Render3DFloorPlane::RenderPlanes(thread, WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects[thread->ThreadIndex]);
RenderPolyPlane::RenderPlanes(thread, WorldToClip, PortalPlane, fakeflat, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals);
Render3DFloorPlane::RenderPlanes(thread, CurrentViewpoint->PortalPlane, sub, CurrentViewpoint->StencilValue, subsectorDepth, thread->TranslucentObjects);
RenderPolyPlane::RenderPlanes(thread, CurrentViewpoint->PortalPlane, fakeflat, CurrentViewpoint->StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals);
for (uint32_t i = 0; i < sub->numlines; i++)
{
@ -147,7 +179,7 @@ void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub
for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext)
{
particle_t *particle = Particles + i;
TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject<PolyTranslucentParticle>(particle, sub, subsectorDepth, StencilValue));
thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucentParticle>(particle, sub, subsectorDepth, CurrentViewpoint->StencilValue));
}
}
}
@ -200,7 +232,7 @@ void RenderPolyScene::RenderPolySubsector(PolyRenderThread *thread, subsector_t
sub->flags |= SSECF_DRAWN;
}
RenderPolyWall::RenderLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects[thread->ThreadIndex], LinePortals, LastPortalLine);
RenderPolyWall::RenderLine(thread, CurrentViewpoint->PortalPlane, line, frontsector, subsectorDepth, CurrentViewpoint->StencilValue, thread->TranslucentObjects, thread->LinePortals, CurrentViewpoint->LastPortalLine);
}
}
}
@ -210,21 +242,21 @@ int RenderPolyScene::PointOnSide(const DVector2 &pos, const node_t *node)
return DMulScale32(FLOAT2FIXED(pos.Y) - node->y, node->dx, node->x - FLOAT2FIXED(pos.X), node->dy) > 0;
}
void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right)
void RenderPolyScene::AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right)
{
if (level.nodes.Size() == 0)
{
subsector_t *sub = &level.subsectors[0];
if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff)
TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject<PolyTranslucentThing>(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, StencilValue));
thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucentThing>(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, CurrentViewpoint->StencilValue));
}
else
{
RenderSprite(thread, thing, sortDistance, left, right, 0.0, 1.0, level.HeadNode());
AddSprite(thread, thing, sortDistance, left, right, 0.0, 1.0, level.HeadNode());
}
}
void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node)
void RenderPolyScene::AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node)
{
while (!((size_t)node & 1)) // Keep going until found a subsector
{
@ -246,7 +278,7 @@ void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, doub
DVector2 mid = left * (1.0 - t) + right * t;
double tmid = t1 * (1.0 - t) + t2 * t;
RenderSprite(thread, thing, sortDistance, mid, right, tmid, t2, bsp->children[sideRight]);
AddSprite(thread, thing, sortDistance, mid, right, tmid, t2, bsp->children[sideRight]);
right = mid;
t2 = tmid;
}
@ -256,7 +288,7 @@ void RenderPolyScene::RenderSprite(PolyRenderThread *thread, AActor *thing, doub
subsector_t *sub = (subsector_t *)((uint8_t *)node - 1);
if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff)
TranslucentObjects[thread->ThreadIndex].push_back(thread->FrameMemory->NewObject<PolyTranslucentThing>(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, (float)t1, (float)t2, StencilValue));
thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucentThing>(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, (float)t1, (float)t2, CurrentViewpoint->StencilValue));
}
void RenderPolyScene::RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth)
@ -274,127 +306,129 @@ void RenderPolyScene::RenderLine(PolyRenderThread *thread, subsector_t *sub, seg
for (unsigned int i = 0; i < line->backsector->e->XFloor.ffloors.Size(); i++)
{
F3DFloor *fakeFloor = line->backsector->e->XFloor.ffloors[i];
RenderPolyWall::Render3DFloorLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, fakeFloor, TranslucentObjects[thread->ThreadIndex]);
RenderPolyWall::Render3DFloorLine(thread, CurrentViewpoint->PortalPlane, line, frontsector, subsectorDepth, CurrentViewpoint->StencilValue, fakeFloor, thread->TranslucentObjects);
}
}
// Render wall, and update culling info if its an occlusion blocker
RenderPolyWall::RenderLine(thread, WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, TranslucentObjects[thread->ThreadIndex], LinePortals, LastPortalLine);
RenderPolyWall::RenderLine(thread, CurrentViewpoint->PortalPlane, line, frontsector, subsectorDepth, CurrentViewpoint->StencilValue, thread->TranslucentObjects, thread->LinePortals, CurrentViewpoint->LastPortalLine);
}
void RenderPolyScene::RenderPortals(int portalDepth)
void RenderPolyScene::RenderPortals()
{
PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread();
bool foggy = false;
if (portalDepth < r_portal_recursions)
if (CurrentViewpoint->PortalDepth < r_portal_recursions)
{
for (auto &portal : SectorPortals)
portal->Render(portalDepth + 1);
for (auto &portal : thread->SectorPortals)
portal->Render(CurrentViewpoint->PortalDepth + 1);
for (auto &portal : LinePortals)
portal->Render(portalDepth + 1);
for (auto &portal : thread->LinePortals)
portal->Render(CurrentViewpoint->PortalDepth + 1);
}
else // Fill with black
{
PolyDrawArgs args;
args.SetTransform(&WorldToClip);
args.SetLight(&NormalLight, 255, PolyRenderer::Instance()->Light.WallGlobVis(foggy), true);
args.SetColor(0, 0);
args.SetClipPlane(0, PortalPlane);
args.SetClipPlane(0, CurrentViewpoint->PortalPlane);
args.SetStyle(TriBlendMode::FillOpaque);
for (auto &portal : SectorPortals)
for (auto &portal : thread->SectorPortals)
{
args.SetStencilTestValue(portal->StencilValue);
args.SetWriteStencil(true, portal->StencilValue + 1);
for (const auto &verts : portal->Shape)
{
args.SetFaceCullCCW(verts.Ccw);
args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan);
}
}
for (auto &portal : LinePortals)
for (auto &portal : thread->LinePortals)
{
args.SetStencilTestValue(portal->StencilValue);
args.SetWriteStencil(true, portal->StencilValue + 1);
for (const auto &verts : portal->Shape)
{
args.SetFaceCullCCW(verts.Ccw);
args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan);
}
}
}
}
void RenderPolyScene::RenderTranslucent(int portalDepth)
void RenderPolyScene::RenderTranslucent(PolyPortalViewpoint *viewpoint)
{
CurrentViewpoint = viewpoint;
PolyRenderThread *thread = PolyRenderer::Instance()->Threads.MainThread();
if (portalDepth < r_portal_recursions)
PolyTriangleDrawer::SetTransform(thread->DrawQueue, thread->FrameMemory->NewObject<Mat4f>(CurrentViewpoint->WorldToClip));
if (CurrentViewpoint->PortalDepth < r_portal_recursions)
{
for (auto it = SectorPortals.rbegin(); it != SectorPortals.rend(); ++it)
for (auto it = thread->SectorPortals.rbegin(); it != thread->SectorPortals.rend(); ++it)
{
auto &portal = *it;
portal->RenderTranslucent(portalDepth + 1);
portal->RenderTranslucent();
PolyDrawArgs args;
args.SetTransform(&WorldToClip);
args.SetStencilTestValue(portal->StencilValue + 1);
args.SetWriteStencil(true, StencilValue + 1);
args.SetClipPlane(0, PortalPlane);
args.SetWriteStencil(true, CurrentViewpoint->StencilValue + 1);
args.SetClipPlane(0, CurrentViewpoint->PortalPlane);
for (const auto &verts : portal->Shape)
{
args.SetFaceCullCCW(verts.Ccw);
args.SetWriteColor(false);
args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan);
}
}
for (auto it = LinePortals.rbegin(); it != LinePortals.rend(); ++it)
for (auto it = thread->LinePortals.rbegin(); it != thread->LinePortals.rend(); ++it)
{
auto &portal = *it;
portal->RenderTranslucent(portalDepth + 1);
portal->RenderTranslucent();
PolyDrawArgs args;
args.SetTransform(&WorldToClip);
args.SetStencilTestValue(portal->StencilValue + 1);
args.SetWriteStencil(true, StencilValue + 1);
args.SetClipPlane(0, PortalPlane);
args.SetWriteStencil(true, CurrentViewpoint->StencilValue + 1);
args.SetClipPlane(0, CurrentViewpoint->PortalPlane);
for (const auto &verts : portal->Shape)
{
args.SetFaceCullCCW(verts.Ccw);
args.SetWriteColor(false);
args.DrawArray(thread, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, verts.Vertices, verts.Count, PolyDrawMode::TriangleFan);
}
}
}
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
for (uint32_t sectorIndex : Cull.SeenSectors)
{
sector_t *sector = &level.sectors[sectorIndex];
for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext)
{
DVector2 left, right;
if (!RenderPolySprite::GetLine(thing, left, right))
continue;
double distanceSquared = (thing->Pos() - viewpoint.Pos).LengthSquared();
RenderSprite(thread, thing, distanceSquared, left, right);
}
}
PolyMaskedCycles.Clock();
std::stable_sort(TranslucentObjects[0].begin(), TranslucentObjects[0].end(), [](auto a, auto b) { return *a < *b; });
for (auto it = TranslucentObjects[0].rbegin(); it != TranslucentObjects[0].rend(); ++it)
// Draw all translucent objects back to front
if (CurrentViewpoint->ObjectsEnd > CurrentViewpoint->ObjectsStart)
{
PolyTranslucentObject *obj = *it;
obj->Render(thread, WorldToClip, PortalPlane);
std::stable_sort(
thread->TranslucentObjects.begin() + CurrentViewpoint->ObjectsStart,
thread->TranslucentObjects.begin() + CurrentViewpoint->ObjectsEnd,
[](auto a, auto b) { return *a < *b; });
size_t i = CurrentViewpoint->ObjectsEnd - 1;
size_t start = CurrentViewpoint->ObjectsStart;
auto objects = thread->TranslucentObjects.data();
while (true)
{
PolyTranslucentObject *obj = objects[i];
obj->Render(thread, CurrentViewpoint->PortalPlane);
obj->~PolyTranslucentObject();
if (i == start)
break;
i--;
}
}
TranslucentObjects[0].clear();
thread->TranslucentObjects.clear();
PolyMaskedCycles.Unclock();
CurrentViewpoint = nullptr;
}
/////////////////////////////////////////////////////////////////////////////

View file

@ -29,6 +29,7 @@
#include "doomdata.h"
#include "r_utility.h"
#include "polyrenderer/drawers/poly_triangle.h"
#include "polyrenderer/math/gpu_types.h"
#include "poly_playersprite.h"
#include "poly_cull.h"
@ -38,7 +39,7 @@ public:
PolyTranslucentObject(uint32_t subsectorDepth = 0, double distanceSquared = 0.0) : subsectorDepth(subsectorDepth), DistanceSquared(distanceSquared) { }
virtual ~PolyTranslucentObject() { }
virtual void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) = 0;
virtual void Render(PolyRenderThread *thread, const PolyClipPlane &portalPlane) = 0;
bool operator<(const PolyTranslucentObject &other) const
{
@ -53,41 +54,52 @@ class PolyDrawSectorPortal;
class PolyDrawLinePortal;
class PolyPortalSegment;
class PolyPortalViewpoint
{
public:
Mat4f WorldToView;
Mat4f WorldToClip;
PolyClipPlane PortalPlane;
uint32_t StencilValue = 0;
int PortalDepth = 0;
line_t *LastPortalLine = nullptr;
size_t ObjectsStart = 0;
size_t ObjectsEnd = 0;
size_t SectorPortalsStart = 0;
size_t SectorPortalsEnd = 0;
size_t LinePortalsStart = 0;
size_t LinePortalsEnd = 0;
};
// Renders everything from a specific viewpoint
class RenderPolyScene
{
public:
RenderPolyScene();
~RenderPolyScene();
void SetViewpoint(const TriMatrix &worldToClip, const PolyClipPlane &portalPlane, uint32_t stencilValue);
void Render(int portalDepth);
void RenderTranslucent(int portalDepth);
void Render(PolyPortalViewpoint *viewpoint);
void RenderTranslucent(PolyPortalViewpoint *viewpoint);
static const uint32_t SkySubsectorDepth = 0x7fffffff;
line_t *LastPortalLine = nullptr;
PolyPortalViewpoint *CurrentViewpoint = nullptr;
private:
void RenderPortals(int portalDepth);
void RenderPortals();
void RenderSectors();
void RenderSubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth);
void RenderLine(PolyRenderThread *thread, subsector_t *sub, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth);
void RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right);
void RenderSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node);
void AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right);
void AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node);
void RenderPolySubsector(PolyRenderThread *thread, subsector_t *sub, uint32_t subsectorDepth, sector_t *frontsector);
void RenderPolyNode(PolyRenderThread *thread, void *node, uint32_t subsectorDepth, sector_t *frontsector);
static int PointOnSide(const DVector2 &pos, const node_t *node);
TriMatrix WorldToClip;
PolyClipPlane PortalPlane;
uint32_t StencilValue = 0;
PolyCull Cull;
bool PortalSegmentsAdded = false;
std::vector<std::vector<PolyTranslucentObject *>> TranslucentObjects;
std::vector<std::unique_ptr<PolyDrawSectorPortal>> SectorPortals;
std::vector<std::unique_ptr<PolyDrawLinePortal>> LinePortals;
};
enum class PolyWaterFakeSide

View file

@ -35,12 +35,12 @@ PolySkyDome::PolySkyDome()
CreateDome();
}
void PolySkyDome::Render(PolyRenderThread *thread, const TriMatrix &worldToClip)
void PolySkyDome::Render(PolyRenderThread *thread, const Mat4f &worldToView, const Mat4f &worldToClip)
{
#ifdef USE_GL_DOME_MATH
TriMatrix modelMatrix = GLSkyMath();
Mat4f modelMatrix = GLSkyMath();
#else
TriMatrix modelMatrix = TriMatrix::identity();
Mat4f modelMatrix = Mat4f::Identity();
PolySkySetup frameSetup;
frameSetup.Update();
@ -76,14 +76,14 @@ void PolySkyDome::Render(PolyRenderThread *thread, const TriMatrix &worldToClip)
#endif
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
TriMatrix objectToWorld = TriMatrix::translate((float)viewpoint.Pos.X, (float)viewpoint.Pos.Y, (float)viewpoint.Pos.Z) * modelMatrix;
objectToClip = worldToClip * objectToWorld;
Mat4f objectToWorld = Mat4f::Translate((float)viewpoint.Pos.X, (float)viewpoint.Pos.Y, (float)viewpoint.Pos.Z) * modelMatrix;
int rc = mRows + 1;
PolyTriangleDrawer::SetTransform(thread->DrawQueue, thread->FrameMemory->NewObject<Mat4f>(worldToClip * objectToWorld));
PolyDrawArgs args;
args.SetLight(&NormalLight, 255, PolyRenderer::Instance()->Light.WallGlobVis(false), true);
args.SetTransform(&objectToClip);
args.SetStencilTestValue(255);
args.SetWriteStencil(true, 1);
args.SetClipPlane(0, PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f));
@ -107,10 +107,9 @@ void PolySkyDome::Render(PolyRenderThread *thread, const TriMatrix &worldToClip)
void PolySkyDome::RenderRow(PolyRenderThread *thread, PolyDrawArgs &args, int row, uint32_t capcolor, uint8_t capcolorindex)
{
args.SetFaceCullCCW(false);
args.SetColor(capcolor, capcolorindex);
args.SetStyle(TriBlendMode::Skycap);
args.DrawArray(thread, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleStrip);
args.DrawArray(thread->DrawQueue, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleStrip);
}
void PolySkyDome::RenderCapColorRow(PolyRenderThread *thread, PolyDrawArgs &args, FTexture *skytex, int row, bool bottomCap)
@ -118,10 +117,9 @@ void PolySkyDome::RenderCapColorRow(PolyRenderThread *thread, PolyDrawArgs &args
uint32_t solid = skytex->GetSkyCapColor(bottomCap);
uint8_t palsolid = RGB32k.RGB[(RPART(solid) >> 3)][(GPART(solid) >> 3)][(BPART(solid) >> 3)];
args.SetFaceCullCCW(bottomCap);
args.SetColor(solid, palsolid);
args.SetStyle(TriBlendMode::FillOpaque);
args.DrawArray(thread, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], PolyDrawMode::TriangleFan);
}
void PolySkyDome::CreateDome()
@ -141,7 +139,7 @@ void PolySkyDome::CreateSkyHemisphere(bool zflip)
for (c = 0; c < mColumns; c++)
{
SkyVertex(1, c, zflip);
SkyVertex(1, zflip ? c : (mColumns - 1 - c), zflip);
}
// The total number of triangles per hemisphere can be calculated
@ -151,8 +149,8 @@ void PolySkyDome::CreateSkyHemisphere(bool zflip)
mPrimStart.Push(mVertices.Size());
for (c = 0; c <= mColumns; c++)
{
SkyVertex(r + zflip, c, zflip);
SkyVertex(r + 1 - zflip, c, zflip);
SkyVertex(r + zflip, c, zflip);
}
}
}
@ -204,7 +202,7 @@ void PolySkyDome::SkyVertex(int r, int c, bool zflip)
mInitialUV.Push({ vert.u, vert.v });
}
TriMatrix PolySkyDome::GLSkyMath()
Mat4f PolySkyDome::GLSkyMath()
{
PolySkySetup frameSetup;
frameSetup.Update();
@ -222,43 +220,43 @@ TriMatrix PolySkyDome::GLSkyMath()
// 57 world units roughly represent one sky texel for the glTranslate call.
const float skyoffsetfactor = 57;
TriMatrix modelMatrix = TriMatrix::identity();
Mat4f modelMatrix = Mat4f::Identity();
if (tex)
{
texw = tex->GetWidth();
texh = tex->GetHeight();
modelMatrix = TriMatrix::rotate(-180.0f + x_offset, 0.f, 0.f, 1.f);
modelMatrix = Mat4f::Rotate(-180.0f + x_offset, 0.f, 0.f, 1.f);
float xscale = texw < 1024.f ? floor(1024.f / float(texw)) : 1.f;
float yscale = 1.f;
if (texh <= 128 && (level.flags & LEVEL_FORCETILEDSKY))
{
modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, (-40 + tex->SkyOffset + skyoffset)*skyoffsetfactor);
modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 1.2f * 1.17f);
modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, (-40 + tex->SkyOffset + skyoffset)*skyoffsetfactor);
modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 1.2f * 1.17f);
yscale = 240.f / texh;
}
else if (texh < 128)
{
// smaller sky textures must be tiled. We restrict it to 128 sky pixels, though
modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, -1250.f);
modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 128 / 230.f);
modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, -1250.f);
modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 128 / 230.f);
yscale = (float)(128 / texh); // intentionally left as integer.
}
else if (texh < 200)
{
modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, -1250.f);
modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, texh / 230.f);
modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, -1250.f);
modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, texh / 230.f);
}
else if (texh <= 240)
{
modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, (200 - texh + tex->SkyOffset + skyoffset)*skyoffsetfactor);
modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f);
modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, (200 - texh + tex->SkyOffset + skyoffset)*skyoffsetfactor);
modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 1.f + ((texh - 200.f) / 200.f) * 1.17f);
}
else
{
modelMatrix = modelMatrix * TriMatrix::translate(0.f, 0.f, (-40 + tex->SkyOffset + skyoffset)*skyoffsetfactor);
modelMatrix = modelMatrix * TriMatrix::scale(1.f, 1.f, 1.2f * 1.17f);
modelMatrix = modelMatrix * Mat4f::Translate(0.f, 0.f, (-40 + tex->SkyOffset + skyoffset)*skyoffsetfactor);
modelMatrix = modelMatrix * Mat4f::Scale(1.f, 1.f, 1.2f * 1.17f);
yscale = 240.f / texh;
}

View file

@ -46,14 +46,13 @@ class PolySkyDome
{
public:
PolySkyDome();
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip);
void Render(PolyRenderThread *thread, const Mat4f &worldToView, const Mat4f &worldToClip);
private:
TArray<FVector2> mInitialUV;
TArray<TriVertex> mVertices;
TArray<unsigned int> mPrimStart;
int mRows, mColumns;
TriMatrix objectToClip;
void SkyVertex(int r, int c, bool yflip);
void CreateSkyHemisphere(bool zflip);
@ -63,7 +62,7 @@ private:
TriVertex SetVertexXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0);
TriMatrix GLSkyMath();
Mat4f GLSkyMath();
PolySkySetup mCurrentSetup;
};

View file

@ -72,18 +72,18 @@ bool RenderPolySprite::GetLine(AActor *thing, DVector2 &left, DVector2 &right)
return true;
}
void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2)
void RenderPolySprite::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2)
{
/*int spritenum = thing->sprite;
int spritenum = thing->sprite;
bool isPicnumOverride = thing->picnum.isValid();
FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
if (modelframe)
{
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
DVector3 pos = thing->InterpolatedPosition(viewpoint.TicFrac);
PolyRenderModel(thread, worldToClip, clipPlane, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing);
PolyRenderModel(thread, PolyRenderer::Instance()->WorldToClip, clipPlane, stencilValue, (float)pos.X, (float)pos.Y, (float)pos.Z, modelframe, thing);
return;
}*/
}
DVector2 line[2];
if (!GetLine(thing, line[0], line[1]))
@ -157,10 +157,7 @@ void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldTo
PolyDrawArgs args;
SetDynlight(thing, args);
args.SetLight(GetColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite);
args.SetTransform(&worldToClip);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue);
args.SetClipPlane(0, clipPlane);
if ((thing->renderflags & RF_ZDOOMTRANS) && r_UseVanillaTransparency)
args.SetStyle(LegacyRenderStyles[STYLE_Normal], 1.0f, thing->fillcolor, thing->Translation, tex, fullbrightSprite);
@ -169,7 +166,7 @@ void RenderPolySprite::Render(PolyRenderThread *thread, const TriMatrix &worldTo
args.SetDepthTest(true);
args.SetWriteDepth(false);
args.SetWriteStencil(false);
args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan);
}
double RenderPolySprite::GetSpriteFloorZ(AActor *thing, const DVector2 &thingpos)

View file

@ -27,7 +27,7 @@
class RenderPolySprite
{
public:
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2);
void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue, float t1, float t2);
static bool GetLine(AActor *thing, DVector2 &left, DVector2 &right);
static bool IsThingCulled(AActor *thing);
@ -45,17 +45,17 @@ class PolyTranslucentThing : public PolyTranslucentObject
public:
PolyTranslucentThing(AActor *thing, subsector_t *sub, uint32_t subsectorDepth, double dist, float t1, float t2, uint32_t stencilValue) : PolyTranslucentObject(subsectorDepth, dist), thing(thing), sub(sub), SpriteLeft(t1), SpriteRight(t2), StencilValue(stencilValue) { }
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override
void Render(PolyRenderThread *thread, const PolyClipPlane &portalPlane) override
{
if ((thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE)
{
RenderPolyWallSprite wallspr;
wallspr.Render(thread, worldToClip, portalPlane, thing, sub, StencilValue + 1);
wallspr.Render(thread, portalPlane, thing, sub, StencilValue + 1);
}
else
{
RenderPolySprite spr;
spr.Render(thread, worldToClip, portalPlane, thing, sub, StencilValue + 1, SpriteLeft, SpriteRight);
spr.Render(thread, portalPlane, thing, sub, StencilValue + 1, SpriteLeft, SpriteRight);
}
}

View file

@ -40,7 +40,7 @@
EXTERN_CVAR(Bool, r_drawmirrors)
EXTERN_CVAR(Bool, r_fogboundary)
bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject*> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals, line_t *lastPortalLine)
bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject*> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals, line_t *lastPortalLine)
{
double frontceilz1 = frontsector->ceilingplane.ZatPoint(line->v1);
double frontfloorz1 = frontsector->floorplane.ZatPoint(line->v1);
@ -108,7 +108,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &world
wall.Wallpart = side_t::mid;
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid);
wall.Polyportal = polyportal;
wall.Render(thread, worldToClip, clipPlane);
wall.Render(thread, clipPlane);
return true;
}
}
@ -145,7 +145,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &world
wall.BottomTexZ = MIN(MIN(backceilz1, frontceilz1), MIN(backceilz2, frontceilz2));
wall.Wallpart = side_t::top;
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::top);
wall.Render(thread, worldToClip, clipPlane);
wall.Render(thread, clipPlane);
}
if ((bottomfloorz1 < bottomceilz1 || bottomfloorz2 < bottomceilz2) && line->sidedef && !bothSkyFloor)
@ -157,7 +157,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &world
wall.UnpeggedCeil2 = topceilz2;
wall.Wallpart = side_t::bottom;
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::bottom);
wall.Render(thread, worldToClip, clipPlane);
wall.Render(thread, clipPlane);
}
if (line->sidedef)
@ -179,7 +179,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, const TriMatrix &world
if (polyportal)
{
wall.Polyportal = polyportal;
wall.Render(thread, worldToClip, clipPlane);
wall.Render(thread, clipPlane);
}
}
}
@ -193,7 +193,7 @@ bool RenderPolyWall::IsFogBoundary(sector_t *front, sector_t *back)
(front->GetTexture(sector_t::ceiling) != skyflatnum || back->GetTexture(sector_t::ceiling) != skyflatnum);
}
void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject*> &translucentWallsOutput)
void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject*> &translucentWallsOutput)
{
if (!(fakeFloor->flags & FF_EXISTS)) return;
if (!(fakeFloor->flags & FF_RENDERPLANES)) return;
@ -243,7 +243,7 @@ void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, const TriMatrix
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid);
if (!wall.Masked)
wall.Render(thread, worldToClip, clipPlane);
wall.Render(thread, clipPlane);
else
translucentWallsOutput.push_back(thread->FrameMemory->NewObject<PolyTranslucentWall>(wall));
}
@ -258,7 +258,7 @@ void RenderPolyWall::SetCoords(const DVector2 &v1, const DVector2 &v2, double ce
this->floor2 = floor2;
}
void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane)
void RenderPolyWall::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane)
{
bool foggy = false;
if (!Texture && !Polyportal && !FogBoundary)
@ -322,10 +322,7 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl
PolyDrawArgs args;
args.SetLight(Colormap, GetLightLevel(), PolyRenderer::Instance()->Light.WallGlobVis(foggy), false);
args.SetTransform(&worldToClip);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(StencilValue);
args.SetWriteStencil(true, StencilValue + 1);
if (Texture && !Polyportal)
args.SetTexture(Texture, DefaultRenderStyle());
args.SetClipPlane(0, clipPlane);
@ -339,7 +336,7 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl
args.SetDepthTest(true);
args.SetWriteDepth(true);
args.SetWriteStencil(false);
args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan);
if (!Texture)
return;
}
@ -349,11 +346,12 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl
args.SetWriteStencil(true, Polyportal->StencilValue);
args.SetWriteColor(false);
args.SetWriteDepth(false);
args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan);
Polyportal->Shape.push_back({ vertices, 4, true });
args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan);
Polyportal->Shape.push_back({ vertices, 4 });
}
else if (!Masked)
{
args.SetWriteStencil(true, StencilValue + 1);
args.SetStyle(TriBlendMode::TextureOpaque);
DrawStripes(thread, args, vertices);
}
@ -368,7 +366,7 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl
DrawStripes(thread, args, vertices);
}
RenderPolyDecal::RenderWallDecals(thread, worldToClip, clipPlane, LineSeg, StencilValue);
RenderPolyDecal::RenderWallDecals(thread, clipPlane, LineSeg, StencilValue);
}
void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args)
@ -465,7 +463,7 @@ void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, T
args.SetClipPlane(1, topPlane);
args.SetClipPlane(2, bottomPlane);
args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan);
FDynamicColormap *basecolormap = GetColorTable(lit->extra_colormap, Line->frontsector->SpecialColors[sector_t::walltop]);
@ -488,11 +486,11 @@ void RenderPolyWall::DrawStripes(PolyRenderThread *thread, PolyDrawArgs &args, T
args.SetClipPlane(1, topPlane);
args.SetClipPlane(2, PolyClipPlane());
args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan);
}
else
{
args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan);
}
}

View file

@ -31,11 +31,11 @@ class PolyCull;
class RenderPolyWall
{
public:
static bool RenderLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject*> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals, line_t *lastPortalLine);
static void Render3DFloorLine(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject*> &translucentWallsOutput);
static bool RenderLine(PolyRenderThread *thread, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject*> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals, line_t *lastPortalLine);
static void Render3DFloorLine(PolyRenderThread *thread, const PolyClipPlane &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject*> &translucentWallsOutput);
void SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2);
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane);
void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane);
DVector2 v1;
DVector2 v2;
@ -101,9 +101,9 @@ class PolyTranslucentWall : public PolyTranslucentObject
public:
PolyTranslucentWall(RenderPolyWall wall) : PolyTranslucentObject(wall.SubsectorDepth, 1e6), wall(wall) { }
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &portalPlane) override
void Render(PolyRenderThread *thread, const PolyClipPlane &portalPlane) override
{
wall.Render(thread, worldToClip, portalPlane);
wall.Render(thread, portalPlane);
}
RenderPolyWall wall;

View file

@ -30,7 +30,7 @@
#include "polyrenderer/scene/poly_light.h"
#include "polyrenderer/poly_renderthread.h"
void RenderPolyWallSprite::Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue)
void RenderPolyWallSprite::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue)
{
if (RenderPolySprite::IsThingCulled(thing))
return;
@ -102,8 +102,6 @@ void RenderPolyWallSprite::Render(PolyRenderThread *thread, const TriMatrix &wor
PolyDrawArgs args;
args.SetLight(GetColorTable(sub->sector->Colormap, sub->sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), fullbrightSprite);
args.SetTransform(&worldToClip);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetTexture(tex, thing->RenderStyle);
args.SetClipPlane(0, clipPlane);
@ -111,5 +109,5 @@ void RenderPolyWallSprite::Render(PolyRenderThread *thread, const TriMatrix &wor
args.SetWriteDepth(false);
args.SetWriteStencil(false);
args.SetStyle(TriBlendMode::TextureMasked);
args.DrawArray(thread, vertices, 4, PolyDrawMode::TriangleFan);
args.DrawArray(thread->DrawQueue, vertices, 4, PolyDrawMode::TriangleFan);
}

View file

@ -27,5 +27,5 @@
class RenderPolyWallSprite
{
public:
void Render(PolyRenderThread *thread, const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue);
void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, AActor *thing, subsector_t *sub, uint32_t stencilValue);
};

View file

@ -292,7 +292,7 @@ namespace swrenderer
class DepthSpanCommand : public DrawerCommand
{
public:
DepthSpanCommand(const SpanDrawerArgs &args, float idepth) : idepth(idepth)
DepthSpanCommand(const SpanDrawerArgs &args, float idepth1, float idepth2) : idepth1(idepth1), idepth2(idepth2)
{
y = args.DestY();
x1 = args.DestX1();
@ -310,16 +310,30 @@ namespace swrenderer
int pitch = PolyStencilBuffer::Instance()->BlockWidth() * 8;
float *values = zbuffer->Values() + y * pitch;
int end = x2;
float depth = idepth;
if (idepth1 == idepth2)
{
float depth = idepth1;
for (int x = x1; x <= end; x++)
{
values[x] = depth;
}
}
else
{
float depth = idepth1;
float step = (idepth2 - idepth1) / (x2 - x1 + 1);
for (int x = x1; x <= end; x++)
{
values[x] = depth;
depth += step;
}
}
}
private:
int y, x1, x2;
float idepth;
float idepth1, idepth2;
};
void SWPixelFormatDrawers::DrawDepthSkyColumn(const SkyDrawerArgs &args, float idepth)
@ -332,8 +346,8 @@ namespace swrenderer
Queue->Push<DepthColumnCommand>(args, idepth);
}
void SWPixelFormatDrawers::DrawDepthSpan(const SpanDrawerArgs &args, float idepth)
void SWPixelFormatDrawers::DrawDepthSpan(const SpanDrawerArgs &args, float idepth1, float idepth2)
{
Queue->Push<DepthSpanCommand>(args, idepth);
Queue->Push<DepthSpanCommand>(args, idepth1, idepth2);
}
}

View file

@ -97,7 +97,7 @@ namespace swrenderer
void DrawDepthSkyColumn(const SkyDrawerArgs &args, float idepth);
void DrawDepthWallColumn(const WallDrawerArgs &args, float idepth);
void DrawDepthSpan(const SpanDrawerArgs &args, float idepth);
void DrawDepthSpan(const SpanDrawerArgs &args, float idepth1, float idepth2);
DrawerCommandQueuePtr Queue;
};

View file

@ -32,6 +32,8 @@
// Use multiple threads when drawing
EXTERN_CVAR(Bool, r_multithreaded)
class PolyTriangleThreadData;
// Worker data for each thread executing drawer commands
class DrawerThread
{
@ -48,6 +50,8 @@ public:
// Working buffer used by the tilted (sloped) span drawer
const uint8_t *tiltlighting[MAXWIDTH];
std::shared_ptr<PolyTriangleThreadData> poly;
// Checks if a line is rendered by this thread
bool line_skipped_by_thread(int line)
{

View file

@ -276,7 +276,7 @@ namespace swrenderer
drawerargs.DrawSpan(Thread);
if (r_models)
drawerargs.DrawDepthSpan(Thread, zbufferdepth);
drawerargs.DrawDepthSpan(Thread, zbufferdepth, zbufferdepth);
}
/////////////////////////////////////////////////////////////////////////

View file

@ -88,6 +88,14 @@ namespace swrenderer
auto viewport = Thread->Viewport.get();
DVector3 worldNormal = pl->height.Normal();
double worldD = pl->height.fD();
planeNormal.X = worldNormal.X * viewport->viewpoint.Sin - worldNormal.Y * viewport->viewpoint.Cos;
planeNormal.Y = worldNormal.X * viewport->viewpoint.Cos + worldNormal.Y * viewport->viewpoint.Sin;
planeNormal.Z = worldNormal.Z;
planeD = worldD + planeNormal.Z * viewport->viewpoint.Pos.Z;
drawerargs.SetSolidColor(3);
drawerargs.SetTexture(Thread, texture);
@ -205,14 +213,23 @@ namespace swrenderer
void RenderSlopePlane::RenderLine(int y, int x1, int x2)
{
/* To do: project (x1,y) and (x2,y) on the plane to calculate the depth
double distance = Thread->Viewport->PlaneDepth(y, planeheight);
float zbufferdepth = 1.0f / (distance * Thread->Viewport->viewwindow.FocalTangent);
if (r_models)
{
// Calculate normalized device coordinates for the span
// 1.5 is not a typo. The range is [x1,x2]
double devY = -(y + 0.5 - Thread->Viewport->CenterY) / Thread->Viewport->InvZtoScale / Thread->Viewport->viewwindow.FocalTangent;
double devX1 = (x1 + 0.5 - Thread->Viewport->CenterX) / Thread->Viewport->CenterX;
double devX2 = (x2 + 1.5 - Thread->Viewport->CenterX) / Thread->Viewport->CenterX;
// Find depth values for the span
float zbufferdepth1 = (float)-planeD / (planeNormal | DVector3(devX1, 1.0, devY));
float zbufferdepth2 = (float)-planeD / (planeNormal | DVector3(devX2, 1.0, devY));
drawerargs.SetDestX1(x1);
drawerargs.SetDestX2(x2);
drawerargs.SetDestY(Thread->Viewport.get(), y);
drawerargs.DrawDepthSpan(Thread, zbufferdepth);
*/
drawerargs.DrawDepthSpan(Thread, 1.0f / zbufferdepth1, 1.0f / zbufferdepth2);
}
drawerargs.DrawTiltedSpan(Thread, y, x1, x2, plane_sz, plane_su, plane_sv, plane_shade, planeshade, planelightfloat, pviewx, pviewy, basecolormap);
}

View file

@ -48,5 +48,8 @@ namespace swrenderer
fixed_t xscale, yscale;
FDynamicColormap *basecolormap;
SpanDrawerArgs drawerargs;
DVector3 planeNormal;
double planeD;
};
}

View file

@ -401,7 +401,7 @@ void SWCanvas::DrawLine(DCanvas *canvas, int x0, int y0, int x1, int y1, int pal
palColor = PalFromRGB(realcolor);
}
canvas->Lock();
canvas->Lock(true);
int deltaX, deltaY, xDir;
if (y0 > y1)

View file

@ -203,16 +203,15 @@ void FSoftwareRenderer::RemapVoxels()
void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, int height)
{
DCanvas *pic = new DSimpleCanvas (width, height, false);
DSimpleCanvas pic(width, height, false);
PalEntry palette[256];
// Take a snapshot of the player's view
pic->Lock ();
if (r_polyrenderer)
{
PolyRenderer::Instance()->Viewpoint = r_viewpoint;
PolyRenderer::Instance()->Viewwindow = r_viewwindow;
PolyRenderer::Instance()->RenderViewToCanvas(player->mo, pic, 0, 0, width, height, true);
PolyRenderer::Instance()->RenderViewToCanvas(player->mo, &pic, 0, 0, width, height, true);
r_viewpoint = PolyRenderer::Instance()->Viewpoint;
r_viewwindow = PolyRenderer::Instance()->Viewwindow;
}
@ -220,14 +219,12 @@ void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int wi
{
mScene.MainThread()->Viewport->viewpoint = r_viewpoint;
mScene.MainThread()->Viewport->viewwindow = r_viewwindow;
mScene.RenderViewToCanvas(player->mo, pic, 0, 0, width, height);
mScene.RenderViewToCanvas(player->mo, &pic, 0, 0, width, height);
r_viewpoint = mScene.MainThread()->Viewport->viewpoint;
r_viewwindow = mScene.MainThread()->Viewport->viewwindow;
}
screen->GetFlashedPalette (palette);
M_CreatePNG (file, pic->GetBuffer(), palette, SS_PAL, width, height, pic->GetPitch(), Gamma);
pic->Unlock ();
delete pic;
M_CreatePNG (file, pic.GetBuffer(), palette, SS_PAL, width, height, pic.GetPitch(), Gamma);
}
void FSoftwareRenderer::DrawRemainingPlayerSprites()

View file

@ -67,7 +67,7 @@ EXTERN_CVAR(Bool, r_shadercolormaps)
EXTERN_CVAR(Int, r_clearbuffer)
CVAR(Bool, r_scene_multithreaded, false, 0);
CVAR(Bool, r_models, false, 0);
CVAR(Bool, r_models, true, 0);
namespace swrenderer
{
@ -98,6 +98,8 @@ namespace swrenderer
float trueratio;
ActiveRatio(width, height, &trueratio);
viewport->SetViewport(MainThread(), width, height, trueratio);
if (r_models)
PolyTriangleDrawer::ClearBuffers(viewport->RenderTarget);
if (r_clearbuffer != 0)
{
@ -158,7 +160,7 @@ namespace swrenderer
R_UpdateFuzzPosFrameStart();
if (r_models)
MainThread()->Viewport->SetupPolyViewport();
MainThread()->Viewport->SetupPolyViewport(MainThread());
ActorRenderFlags savedflags = MainThread()->Viewport->viewpoint.camera->renderflags;
// Never draw the player unless in chasecam mode
@ -267,6 +269,8 @@ namespace swrenderer
thread->OpaquePass->ResetFakingUnderwater(); // [RH] Hack to make windows into underwater areas possible
thread->Portal->SetMainPortal();
PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget, true);
// Cull things outside the range seen by this thread
VisibleSegmentRenderer visitor;
if (thread->X1 > 0)
@ -361,6 +365,8 @@ namespace swrenderer
viewwindowy = y;
viewactive = true;
viewport->SetViewport(MainThread(), width, height, MainThread()->Viewport->viewwindow.WidescreenRatio);
if (r_models)
PolyTriangleDrawer::ClearBuffers(viewport->RenderTarget);
RenderActorView(actor, dontmaplines);
DrawerWaitCycles.Clock();
@ -372,9 +378,7 @@ namespace swrenderer
R_ExecuteSetViewSize(MainThread()->Viewport->viewpoint, MainThread()->Viewport->viewwindow);
float trueratio;
ActiveRatio(width, height, &trueratio);
screen->Lock(true);
viewport->SetViewport(MainThread(), width, height, trueratio);
screen->Unlock();
viewactive = savedviewactive;
}
@ -387,9 +391,7 @@ namespace swrenderer
int height = SCREENHEIGHT;
float trueratio;
ActiveRatio(width, height, &trueratio);
screen->Lock(true);
viewport->SetViewport(MainThread(), SCREENWIDTH, SCREENHEIGHT, trueratio);
screen->Unlock();
}
void RenderScene::Init()

View file

@ -92,7 +92,8 @@ namespace swrenderer
void SWModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix)
{
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.matrix);
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.Matrix);
SetTransform();
}
void SWModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
@ -127,21 +128,21 @@ namespace swrenderer
float ratio = Viewwindow.WidescreenRatio;
float fovratio = (Viewwindow.WidescreenRatio >= 1.3f) ? 1.333333f : ratio;
float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(Viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees);
TriMatrix altWorldToView =
TriMatrix::rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) *
TriMatrix::rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) *
TriMatrix::scale(1.0f, level.info->pixelstretch, 1.0f) *
TriMatrix::swapYZ() *
TriMatrix::translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z);
Mat4f altWorldToView =
Mat4f::Rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) *
Mat4f::Rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) *
Mat4f::Scale(1.0f, level.info->pixelstretch, 1.0f) *
Mat4f::SwapYZ() *
Mat4f::Translate((float)-Viewpoint.Pos.X, (float)-Viewpoint.Pos.Y, (float)-Viewpoint.Pos.Z);
TriMatrix swapYZ = TriMatrix::null();
swapYZ.matrix[0 + 0 * 4] = 1.0f;
swapYZ.matrix[1 + 2 * 4] = 1.0f;
swapYZ.matrix[2 + 1 * 4] = 1.0f;
swapYZ.matrix[3 + 3 * 4] = 1.0f;
Mat4f swapYZ = Mat4f::Null();
swapYZ.Matrix[0 + 0 * 4] = 1.0f;
swapYZ.Matrix[1 + 2 * 4] = 1.0f;
swapYZ.Matrix[2 + 1 * 4] = 1.0f;
swapYZ.Matrix[3 + 3 * 4] = 1.0f;
VSMatrix worldToView;
worldToView.loadMatrix((altWorldToView * swapYZ).matrix);
worldToView.loadMatrix((altWorldToView * swapYZ).Matrix);
VSMatrix objectToWorld;
worldToView.inverseMatrix(objectToWorld);
@ -151,7 +152,8 @@ namespace swrenderer
void SWModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix)
{
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.matrix);
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.Matrix);
SetTransform();
}
void SWModelRenderer::EndDrawHUDModel(AActor *actor)
@ -169,6 +171,17 @@ namespace swrenderer
SkinTexture = skin;
}
void SWModelRenderer::SetTransform()
{
Mat4f swapYZ = Mat4f::Null();
swapYZ.Matrix[0 + 0 * 4] = 1.0f;
swapYZ.Matrix[1 + 2 * 4] = 1.0f;
swapYZ.Matrix[2 + 1 * 4] = 1.0f;
swapYZ.Matrix[3 + 3 * 4] = 1.0f;
PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject<Mat4f>(Thread->Viewport->WorldToClip * swapYZ * ObjectToWorld));
}
void SWModelRenderer::DrawArrays(int start, int count)
{
const auto &viewpoint = Thread->Viewport->viewpoint;
@ -180,19 +193,8 @@ namespace swrenderer
bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT));
int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight;
TriMatrix swapYZ = TriMatrix::null();
swapYZ.matrix[0 + 0 * 4] = 1.0f;
swapYZ.matrix[1 + 2 * 4] = 1.0f;
swapYZ.matrix[2 + 1 * 4] = 1.0f;
swapYZ.matrix[3 + 3 * 4] = 1.0f;
TriMatrix *transform = Thread->FrameMemory->NewObject<TriMatrix>();
*transform = Thread->Viewport->WorldToClip * swapYZ * ObjectToWorld;
PolyDrawArgs args;
args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, Thread->Light->SpriteGlobVis(foggy), fullbrightSprite);
args.SetTransform(transform);
args.SetFaceCullCCW(true);
args.SetClipPlane(0, PolyClipPlane());
args.SetStyle(TriBlendMode::TextureOpaque);
@ -218,19 +220,8 @@ namespace swrenderer
bool fullbrightSprite = ((ModelActor->renderflags & RF_FULLBRIGHT) || (ModelActor->flags5 & MF5_BRIGHT));
int lightlevel = fullbrightSprite ? 255 : ModelActor->Sector->lightlevel + actualextralight;
TriMatrix swapYZ = TriMatrix::null();
swapYZ.matrix[0 + 0 * 4] = 1.0f;
swapYZ.matrix[1 + 2 * 4] = 1.0f;
swapYZ.matrix[2 + 1 * 4] = 1.0f;
swapYZ.matrix[3 + 3 * 4] = 1.0f;
TriMatrix *transform = Thread->FrameMemory->NewObject<TriMatrix>();
*transform = Thread->Viewport->WorldToClip * swapYZ * ObjectToWorld;
PolyDrawArgs args;
args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, Thread->Light->SpriteGlobVis(foggy), fullbrightSprite);
args.SetTransform(transform);
args.SetFaceCullCCW(true);
args.SetClipPlane(0, PolyClipPlane());
args.SetStyle(TriBlendMode::TextureOpaque);
@ -247,7 +238,7 @@ namespace swrenderer
double SWModelRenderer::GetTimeFloat()
{
return (double)screen->FrameTime * (double)TICRATE / 1000.0;
return (double)I_msTime() * (double)TICRATE / 1000.;
}
/////////////////////////////////////////////////////////////////////////////
@ -282,11 +273,11 @@ namespace swrenderer
void SWModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size)
{
SWModelRenderer *polyrenderer = (SWModelRenderer *)renderer;
SWModelRenderer *swrenderer = (SWModelRenderer *)renderer;
if (true)//if (frame1 == frame2 || size == 0 || polyrenderer->InterpolationFactor == 0.f)
if (frame1 == frame2 || size == 0 || swrenderer->InterpolationFactor == 0.f)
{
TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory<TriVertex>(size);
TriVertex *vertices = swrenderer->Thread->FrameMemory->AllocMemory<TriVertex>(size);
for (unsigned int i = 0; i < size; i++)
{
@ -301,26 +292,27 @@ namespace swrenderer
};
}
polyrenderer->VertexBuffer = vertices;
polyrenderer->IndexBuffer = &mIndexBuffer[0];
swrenderer->VertexBuffer = vertices;
swrenderer->IndexBuffer = &mIndexBuffer[0];
}
else
{
TriVertex *vertices = polyrenderer->Thread->FrameMemory->AllocMemory<TriVertex>(size);
TriVertex *vertices = swrenderer->Thread->FrameMemory->AllocMemory<TriVertex>(size);
float frac = polyrenderer->InterpolationFactor;
float frac = swrenderer->InterpolationFactor;
float inv_frac = 1.0f - frac;
for (unsigned int i = 0; i < size; i++)
{
vertices[i].x = mVertexBuffer[frame1 + i].x * (1.0f - frac) + mVertexBuffer[frame2 + i].x * frac;
vertices[i].y = mVertexBuffer[frame1 + i].y * (1.0f - frac) + mVertexBuffer[frame2 + i].y * frac;
vertices[i].z = mVertexBuffer[frame1 + i].z * (1.0f - frac) + mVertexBuffer[frame2 + i].z * frac;
vertices[i].x = mVertexBuffer[frame1 + i].x * inv_frac + mVertexBuffer[frame2 + i].x * frac;
vertices[i].y = mVertexBuffer[frame1 + i].y * inv_frac + mVertexBuffer[frame2 + i].y * frac;
vertices[i].z = mVertexBuffer[frame1 + i].z * inv_frac + mVertexBuffer[frame2 + i].z * frac;
vertices[i].w = 1.0f;
vertices[i].u = mVertexBuffer[frame1 + i].u;
vertices[i].v = mVertexBuffer[frame1 + i].v;
}
polyrenderer->VertexBuffer = vertices;
polyrenderer->IndexBuffer = &mIndexBuffer[0];
swrenderer->VertexBuffer = vertices;
swrenderer->IndexBuffer = &mIndexBuffer[0];
}
}
}

View file

@ -68,10 +68,12 @@ namespace swrenderer
void DrawElements(int numIndices, size_t offset) override;
double GetTimeFloat() override;
void SetTransform();
RenderThread *Thread = nullptr;
AActor *ModelActor = nullptr;
TriMatrix ObjectToWorld;
Mat4f ObjectToWorld;
FTexture *SkinTexture = nullptr;
unsigned int *IndexBuffer = nullptr;
TriVertex *VertexBuffer = nullptr;

View file

@ -107,9 +107,9 @@ namespace swrenderer
}
}
void SpanDrawerArgs::DrawDepthSpan(RenderThread *thread, float idepth)
void SpanDrawerArgs::DrawDepthSpan(RenderThread *thread, float idepth1, float idepth2)
{
thread->Drawers(ds_viewport)->DrawDepthSpan(*this, idepth);
thread->Drawers(ds_viewport)->DrawDepthSpan(*this, idepth1, idepth2);
}
void SpanDrawerArgs::DrawSpan(RenderThread *thread)

View file

@ -27,7 +27,7 @@ namespace swrenderer
void SetTextureVStep(double vstep) { ds_ystep = (uint32_t)(int64_t)(vstep * 4294967296.0); }
void SetSolidColor(int colorIndex) { ds_color = colorIndex; }
void DrawDepthSpan(RenderThread *thread, float idepth);
void DrawDepthSpan(RenderThread *thread, float idepth1, float idepth2);
void DrawSpan(RenderThread *thread);
void DrawTiltedSpan(RenderThread *thread, int y, int x1, int x2, const FVector3 &plane_sz, const FVector3 &plane_su, const FVector3 &plane_sv, bool plane_shade, int planeshade, float planelightfloat, fixed_t pviewx, fixed_t pviewy, FDynamicColormap *basecolormap);
void DrawColoredSpan(RenderThread *thread, int y, int x1, int x2);

View file

@ -59,17 +59,35 @@ namespace swrenderer
{
}
void RenderViewport::SetupPolyViewport()
void RenderViewport::SetupPolyViewport(RenderThread *thread)
{
PolyStencilBuffer::Instance()->Clear(RenderTarget->GetWidth(), RenderTarget->GetHeight(), 0);
PolyZBuffer::Instance()->Resize(RenderTarget->GetPitch(), RenderTarget->GetHeight());
PolyTriangleDrawer::set_viewport(viewwindowx, viewwindowy, viewwidth, viewheight, RenderTarget);
WorldToView = TriMatrix::worldToView(viewpoint);
ViewToClip = TriMatrix::viewToClip(viewwindow.FocalTangent, CenterY, YaspectMul);
WorldToView = SoftwareWorldToView(viewpoint);
ViewToClip = SoftwareViewToClip(viewwindow.FocalTangent, CenterY, YaspectMul);
WorldToClip = ViewToClip * WorldToView;
}
Mat4f RenderViewport::SoftwareWorldToView(const FRenderViewpoint &viewpoint)
{
Mat4f m = Mat4f::Null();
m.Matrix[0 + 0 * 4] = (float)viewpoint.Sin;
m.Matrix[0 + 1 * 4] = (float)-viewpoint.Cos;
m.Matrix[1 + 2 * 4] = 1.0f;
m.Matrix[2 + 0 * 4] = (float)-viewpoint.Cos;
m.Matrix[2 + 1 * 4] = (float)-viewpoint.Sin;
m.Matrix[3 + 3 * 4] = 1.0f;
return m * Mat4f::Translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z);
}
Mat4f RenderViewport::SoftwareViewToClip(double focalTangent, double centerY, double YaspectMul)
{
float near = 5.0f;
float far = 65536.0f;
float width = (float)(focalTangent * near);
float top = (float)(centerY / viewheight * YaspectMul * near);
float bottom = (float)(top - YaspectMul * near);
return Mat4f::Frustum(-width, width, bottom, top, near, far, Handedness::Right, ClipZRange::NegativePositiveW);
}
void RenderViewport::SetViewport(RenderThread *thread, int fullWidth, int fullHeight, float trueratio)
{
int virtheight, virtwidth, virtwidth2, virtheight2;

View file

@ -5,7 +5,7 @@
#include <memory>
#include "v_video.h"
#include "r_defs.h"
#include "polyrenderer/math/tri_matrix.h"
#include "polyrenderer/math/gpu_types.h"
namespace swrenderer
{
@ -20,11 +20,11 @@ namespace swrenderer
void SetViewport(RenderThread *thread, int width, int height, float trueratio);
void SetupFreelook();
void SetupPolyViewport();
void SetupPolyViewport(RenderThread *thread);
TriMatrix WorldToView;
TriMatrix ViewToClip;
TriMatrix WorldToClip;
Mat4f WorldToView;
Mat4f ViewToClip;
Mat4f WorldToClip;
DCanvas *RenderTarget = nullptr;
@ -72,5 +72,8 @@ namespace swrenderer
private:
void InitTextureMapping();
void SetupBuffer();
static Mat4f SoftwareWorldToView(const FRenderViewpoint &viewpoint);
static Mat4f SoftwareViewToClip(double focalTangent, double centerY, double YaspectMul);
};
}