- draw models in mirrors and portals at the right location in the software renderer

This commit is contained in:
Magnus Norddahl 2018-06-05 19:36:57 +02:00
parent 512082b222
commit b74a9965b8
5 changed files with 42 additions and 8 deletions

View file

@ -173,6 +173,7 @@ namespace swrenderer
Thread->Viewport->viewpoint.sector = port->mDestination;
assert(Thread->Viewport->viewpoint.sector != nullptr);
R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow);
Thread->Viewport->SetupPolyViewport(Thread);
Thread->OpaquePass->ClearSeenSprites();
Thread->Clip3D->ClearFakeFloors();
@ -239,6 +240,7 @@ namespace swrenderer
// Masked textures and planes need the view coordinates restored for proper positioning.
viewposStack.Pop(Thread->Viewport->viewpoint.Pos);
Thread->Viewport->SetupPolyViewport(Thread);
Thread->TranslucentPass->Render();
VisiblePlane *pl = nullptr; // quiet, GCC!
@ -259,6 +261,7 @@ namespace swrenderer
Thread->Viewport->viewpoint.extralight = savedextralight;
Thread->Viewport->viewpoint.Angles = savedangles;
R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow);
Thread->Viewport->SetupPolyViewport(Thread);
CurrentPortalInSkybox = false;
Thread->Clip3D->LeaveSkybox();
@ -426,6 +429,8 @@ namespace swrenderer
else MirrorFlags |= RF_XFLIP;
}
Thread->Viewport->SetupPolyViewport(Thread);
// some portals have height differences, account for this here
Thread->Clip3D->EnterSkybox(); // push 3D floor height map
CurrentPortalInSkybox = false; // first portal in a skybox should set this variable to false for proper clipping in skyboxes.
@ -478,6 +483,8 @@ namespace swrenderer
viewpoint.Pos = startpos;
viewpoint.Path[0] = savedpath[0];
viewpoint.Path[1] = savedpath[1];
viewport->SetupPolyViewport(Thread);
}
#if 0

View file

@ -159,6 +159,8 @@ namespace swrenderer
if (r_models)
MainThread()->Viewport->SetupPolyViewport(MainThread());
FRenderViewpoint origviewpoint = MainThread()->Viewport->viewpoint;
ActorRenderFlags savedflags = MainThread()->Viewport->viewpoint.camera->renderflags;
// Never draw the player unless in chasecam mode
if (!MainThread()->Viewport->viewpoint.showviewer)
@ -167,6 +169,12 @@ namespace swrenderer
}
RenderThreadSlices();
// Mirrors fail to restore the original viewpoint -- we need it for the HUD weapon to draw correctly.
MainThread()->Viewport->viewpoint = origviewpoint;
if (r_models)
MainThread()->Viewport->SetupPolyViewport(MainThread());
RenderPSprites();
MainThread()->Viewport->viewpoint.camera->renderflags = savedflags;

View file

@ -47,12 +47,22 @@ namespace swrenderer
if (tz < MINZ)
return;
// too far off the side?
double tx = tr_x * thread->Viewport->viewpoint.Sin - tr_y * thread->Viewport->viewpoint.Cos;
// Flip for mirrors
if (thread->Portal->MirrorFlags & RF_XFLIP)
{
tx = viewwidth - tx - 1;
}
// too far off the side?
if (fabs(tx / 64) > fabs(tz))
return;
RenderModel *vis = thread->FrameMemory->NewObject<RenderModel>(x, y, z, smf, actor, float(1 / tz));
vis->CurrentPortalUniq = thread->Portal->CurrentPortalUniq;
vis->WorldToClip = thread->Viewport->WorldToClip;
vis->MirrorWorldToClip = !!(thread->Portal->MirrorFlags & RF_XFLIP);
thread->SpriteList->Push(vis);
}
@ -64,7 +74,7 @@ namespace swrenderer
void RenderModel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor)
{
SWModelRenderer renderer(thread, clip3DFloor);
SWModelRenderer renderer(thread, clip3DFloor, &WorldToClip, MirrorWorldToClip);
renderer.RenderModel(x, y, z, smf, actor);
}
@ -72,13 +82,14 @@ namespace swrenderer
void RenderHUDModel(RenderThread *thread, DPSprite *psp, float ofsx, float ofsy)
{
SWModelRenderer renderer(thread, Fake3DTranslucent());
SWModelRenderer renderer(thread, Fake3DTranslucent(), &thread->Viewport->WorldToClip, false);
renderer.RenderHUDModel(psp, ofsx, ofsy);
}
/////////////////////////////////////////////////////////////////////////////
SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor) : Thread(thread), Clip3DFloor(clip3DFloor)
SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip)
: Thread(thread), Clip3DFloor(clip3DFloor), WorldToClip(worldToClip), MirrorWorldToClip(mirrorWorldToClip)
{
}
@ -123,7 +134,7 @@ namespace swrenderer
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES))
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !mirrored);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !(mirrored ^ MirrorWorldToClip));
}
void SWModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
@ -194,7 +205,7 @@ namespace swrenderer
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal])
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, mirrored);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !(mirrored ^ MirrorWorldToClip));
}
void SWModelRenderer::EndDrawHUDModel(AActor *actor)
@ -225,7 +236,7 @@ namespace swrenderer
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));
PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject<Mat4f>((*WorldToClip) * swapYZ * ObjectToWorld));
}
void SWModelRenderer::DrawArrays(int start, int count)

View file

@ -47,12 +47,14 @@ namespace swrenderer
float x, y, z;
FSpriteModelFrame *smf;
AActor *actor;
Mat4f WorldToClip;
bool MirrorWorldToClip;
};
class SWModelRenderer : public FModelRenderer
{
public:
SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor);
SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip);
ModelRendererType GetType() const override { return SWModelRendererType; }
@ -81,6 +83,8 @@ namespace swrenderer
unsigned int *IndexBuffer = nullptr;
TriVertex *VertexBuffer = nullptr;
float InterpolationFactor = 0.0;
Mat4f *WorldToClip = nullptr;
bool MirrorWorldToClip = false;
};
class SWModelVertexBuffer : public IModelVertexBuffer

View file

@ -62,6 +62,10 @@ namespace swrenderer
void RenderViewport::SetupPolyViewport(RenderThread *thread)
{
WorldToView = SoftwareWorldToView(viewpoint);
if (thread->Portal->MirrorFlags & RF_XFLIP)
WorldToView = Mat4f::Scale(-1.0f, 1.0f, 1.0f) * WorldToView;
ViewToClip = SoftwareViewToClip();
WorldToClip = ViewToClip * WorldToView;
}