mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-25 13:31:07 +00:00
- 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:
parent
cb3650ed9e
commit
2d51fa5b43
54 changed files with 1209 additions and 842 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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"; }
|
||||
|
|
|
@ -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,19 +1071,10 @@ void TriangleBlock::DepthWrite(const TriDrawTriangleArgs *args)
|
|||
|
||||
#endif
|
||||
|
||||
EXTERN_CVAR(Bool, r_polyrenderer)
|
||||
|
||||
void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thread)
|
||||
void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
|
||||
{
|
||||
if (r_polyrenderer)
|
||||
{
|
||||
TriangleBlock block(args, thread);
|
||||
block.Render();
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSWRender(args, thread);
|
||||
}
|
||||
TriangleBlock block(args, thread);
|
||||
block.Render();
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
271
src/polyrenderer/math/gpu_types.cpp
Normal file
271
src/polyrenderer/math/gpu_types.cpp
Normal 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;
|
||||
}
|
148
src/polyrenderer/math/gpu_types.h
Normal file
148
src/polyrenderer/math/gpu_types.h
Normal 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];
|
||||
};
|
|
@ -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
|
||||
}
|
|
@ -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];
|
||||
};
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -76,9 +78,11 @@ void PolyRenderer::RenderView(player_t *player)
|
|||
{
|
||||
Threads.MainThread()->DrawQueue->Push<ApplySpecialColormapRGBACommand>(cameraLight->ShaderColormap(), screen);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
|
@ -98,9 +102,9 @@ void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int
|
|||
RenderActorView(actor, dontmaplines);
|
||||
Threads.MainThread()->FlushDrawQueue();
|
||||
DrawerThreads::WaitForWorkers();
|
||||
|
||||
canvas->Unlock();
|
||||
|
||||
canvas->Unlock();
|
||||
|
||||
RenderTarget = screen;
|
||||
R_ExecuteSetViewSize(Viewpoint, Viewwindow);
|
||||
float trueratio;
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>> §orPortals)
|
||||
void RenderPolyPlane::RenderPlanes(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> §orPortals)
|
||||
{
|
||||
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>> §orPortals)
|
||||
void RenderPolyPlane::Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> §orPortals)
|
||||
{
|
||||
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>> §orPortals)
|
||||
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>> §orPortals)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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>> §orPortals);
|
||||
static void RenderPlanes(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> §orPortals);
|
||||
|
||||
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>> §orPortals);
|
||||
void Render(PolyRenderThread *thread, const PolyClipPlane &clipPlane, const PolyTransferHeights &fakeflat, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> §orPortals);
|
||||
|
||||
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>> §orPortals);
|
||||
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>> §orPortals);
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
PolyMaskedCycles.Clock();
|
||||
|
||||
// Draw all translucent objects back to front
|
||||
if (CurrentViewpoint->ObjectsEnd > CurrentViewpoint->ObjectsStart)
|
||||
{
|
||||
sector_t *sector = &level.sectors[sectorIndex];
|
||||
for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext)
|
||||
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)
|
||||
{
|
||||
DVector2 left, right;
|
||||
if (!RenderPolySprite::GetLine(thing, left, right))
|
||||
continue;
|
||||
double distanceSquared = (thing->Pos() - viewpoint.Pos).LengthSquared();
|
||||
RenderSprite(thread, thing, distanceSquared, left, right);
|
||||
PolyTranslucentObject *obj = objects[i];
|
||||
obj->Render(thread, CurrentViewpoint->PortalPlane);
|
||||
obj->~PolyTranslucentObject();
|
||||
if (i == start)
|
||||
break;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
std::stable_sort(TranslucentObjects[0].begin(), TranslucentObjects[0].end(), [](auto a, auto b) { return *a < *b; });
|
||||
thread->TranslucentObjects.clear();
|
||||
|
||||
for (auto it = TranslucentObjects[0].rbegin(); it != TranslucentObjects[0].rend(); ++it)
|
||||
{
|
||||
PolyTranslucentObject *obj = *it;
|
||||
obj->Render(thread, WorldToClip, PortalPlane);
|
||||
obj->~PolyTranslucentObject();
|
||||
}
|
||||
PolyMaskedCycles.Unclock();
|
||||
|
||||
TranslucentObjects[0].clear();
|
||||
CurrentViewpoint = nullptr;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
for (int x = x1; x <= end; x++)
|
||||
|
||||
if (idepth1 == idepth2)
|
||||
{
|
||||
values[x] = depth;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -276,7 +276,7 @@ namespace swrenderer
|
|||
|
||||
drawerargs.DrawSpan(Thread);
|
||||
if (r_models)
|
||||
drawerargs.DrawDepthSpan(Thread, zbufferdepth);
|
||||
drawerargs.DrawDepthSpan(Thread, zbufferdepth, zbufferdepth);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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);
|
||||
drawerargs.SetDestX1(x1);
|
||||
drawerargs.SetDestX2(x2);
|
||||
drawerargs.SetDestY(Thread->Viewport.get(), y);
|
||||
drawerargs.DrawDepthSpan(Thread, zbufferdepth);
|
||||
*/
|
||||
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, 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);
|
||||
}
|
||||
|
|
|
@ -48,5 +48,8 @@ namespace swrenderer
|
|||
fixed_t xscale, yscale;
|
||||
FDynamicColormap *basecolormap;
|
||||
SpanDrawerArgs drawerargs;
|
||||
|
||||
DVector3 planeNormal;
|
||||
double planeD;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue