2016-11-07 08:25:12 +00:00
|
|
|
/*
|
2016-11-14 13:19:48 +00:00
|
|
|
** Polygon Doom software renderer
|
2016-11-07 08:25:12 +00:00
|
|
|
** 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 "templates.h"
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "sbar.h"
|
2017-01-21 06:20:24 +00:00
|
|
|
#include "st_stuff.h"
|
2016-11-07 08:25:12 +00:00
|
|
|
#include "r_data/r_translate.h"
|
2016-11-30 23:42:14 +00:00
|
|
|
#include "r_data/r_interpolate.h"
|
2016-12-27 05:31:55 +00:00
|
|
|
#include "poly_renderer.h"
|
2016-11-17 07:50:54 +00:00
|
|
|
#include "gl/data/gl_data.h"
|
2016-11-30 23:42:14 +00:00
|
|
|
#include "d_net.h"
|
|
|
|
#include "po_man.h"
|
2017-01-15 01:46:43 +00:00
|
|
|
#include "st_stuff.h"
|
2017-03-14 17:31:11 +00:00
|
|
|
#include "g_levellocals.h"
|
2017-01-12 15:21:46 +00:00
|
|
|
#include "swrenderer/scene/r_scene.h"
|
2017-01-15 00:54:25 +00:00
|
|
|
#include "swrenderer/scene/r_light.h"
|
2017-01-15 01:46:43 +00:00
|
|
|
#include "swrenderer/drawers/r_draw_rgba.h"
|
2017-02-02 14:10:06 +00:00
|
|
|
#include "swrenderer/viewport/r_viewport.h"
|
2016-11-07 08:25:12 +00:00
|
|
|
|
2017-01-15 01:46:43 +00:00
|
|
|
EXTERN_CVAR(Bool, r_shadercolormaps)
|
2016-11-17 20:07:00 +00:00
|
|
|
EXTERN_CVAR(Int, screenblocks)
|
2016-11-17 07:50:54 +00:00
|
|
|
void InitGLRMapinfoData();
|
2016-11-09 00:33:40 +00:00
|
|
|
|
2016-11-07 08:25:12 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2016-12-03 13:58:56 +00:00
|
|
|
PolyRenderer *PolyRenderer::Instance()
|
2016-11-24 04:51:37 +00:00
|
|
|
{
|
2016-12-03 13:58:56 +00:00
|
|
|
static PolyRenderer scene;
|
2016-11-24 04:51:37 +00:00
|
|
|
return &scene;
|
|
|
|
}
|
|
|
|
|
2017-02-04 13:00:21 +00:00
|
|
|
PolyRenderer::PolyRenderer() : Thread(nullptr)
|
2017-02-04 11:38:05 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-01-15 01:46:43 +00:00
|
|
|
void PolyRenderer::RenderView(player_t *player)
|
|
|
|
{
|
|
|
|
using namespace swrenderer;
|
2017-02-01 15:02:21 +00:00
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
auto viewport = Thread.Viewport.get();
|
2017-01-15 01:46:43 +00:00
|
|
|
|
2017-02-01 15:02:21 +00:00
|
|
|
viewport->RenderTarget = screen;
|
2017-01-15 02:19:03 +00:00
|
|
|
|
2017-01-15 01:46:43 +00:00
|
|
|
int width = SCREENWIDTH;
|
|
|
|
int height = SCREENHEIGHT;
|
2017-01-21 06:20:24 +00:00
|
|
|
int stHeight = gST_Y;
|
2017-01-15 01:46:43 +00:00
|
|
|
float trueratio;
|
|
|
|
ActiveRatio(width, height, &trueratio);
|
2017-03-12 19:40:00 +00:00
|
|
|
viewport->SetViewport(&Thread, width, height, trueratio);
|
2017-01-15 01:46:43 +00:00
|
|
|
|
|
|
|
RenderActorView(player->mo, false);
|
|
|
|
|
|
|
|
// Apply special colormap if the target cannot do it
|
2017-01-26 09:22:54 +00:00
|
|
|
CameraLight *cameraLight = CameraLight::Instance();
|
2017-02-03 08:00:46 +00:00
|
|
|
if (cameraLight->ShaderColormap() && viewport->RenderTarget->IsBgra() && !(r_shadercolormaps && screen->Accel2D))
|
2017-01-15 01:46:43 +00:00
|
|
|
{
|
2017-02-04 11:38:05 +00:00
|
|
|
Thread.DrawQueue->Push<ApplySpecialColormapRGBACommand>(cameraLight->ShaderColormap(), screen);
|
2017-01-15 01:46:43 +00:00
|
|
|
}
|
2017-02-04 11:38:05 +00:00
|
|
|
|
|
|
|
DrawerThreads::Execute({ Thread.DrawQueue });
|
2017-01-15 01:46:43 +00:00
|
|
|
}
|
|
|
|
|
2016-12-03 13:58:56 +00:00
|
|
|
void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines)
|
2016-11-07 08:25:12 +00:00
|
|
|
{
|
2017-03-12 17:54:39 +00:00
|
|
|
auto viewport = Thread.Viewport.get();
|
2017-02-01 15:02:21 +00:00
|
|
|
|
2016-11-30 23:42:14 +00:00
|
|
|
const bool savedviewactive = viewactive;
|
|
|
|
|
|
|
|
viewwidth = width;
|
2017-02-01 15:02:21 +00:00
|
|
|
viewport->RenderTarget = canvas;
|
2017-03-12 17:54:39 +00:00
|
|
|
R_SetWindow(viewport->viewpoint, viewport->viewwindow, 12, width, height, height, true);
|
2017-03-12 19:40:00 +00:00
|
|
|
viewport->SetViewport(&Thread, width, height, viewport->viewwindow.WidescreenRatio);
|
2016-11-30 23:42:14 +00:00
|
|
|
viewwindowx = x;
|
|
|
|
viewwindowy = y;
|
|
|
|
viewactive = true;
|
|
|
|
|
|
|
|
canvas->Lock(true);
|
|
|
|
|
|
|
|
RenderActorView(actor, dontmaplines);
|
2017-02-04 11:38:05 +00:00
|
|
|
DrawerThreads::Execute({ Thread.DrawQueue });
|
2016-11-30 23:42:14 +00:00
|
|
|
|
|
|
|
canvas->Unlock();
|
|
|
|
|
2017-02-01 15:02:21 +00:00
|
|
|
viewport->RenderTarget = screen;
|
2017-03-12 17:54:39 +00:00
|
|
|
R_ExecuteSetViewSize(viewport->viewpoint, viewport->viewwindow);
|
2017-01-15 01:46:43 +00:00
|
|
|
float trueratio;
|
|
|
|
ActiveRatio(width, height, &trueratio);
|
2017-03-12 19:40:00 +00:00
|
|
|
viewport->SetViewport(&Thread, width, height, viewport->viewwindow.WidescreenRatio);
|
2016-11-30 23:42:14 +00:00
|
|
|
viewactive = savedviewactive;
|
|
|
|
}
|
|
|
|
|
2016-12-03 13:58:56 +00:00
|
|
|
void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines)
|
2016-11-30 23:42:14 +00:00
|
|
|
{
|
|
|
|
NetUpdate();
|
|
|
|
|
2016-12-16 19:52:56 +00:00
|
|
|
DontMapLines = dontmaplines;
|
2016-11-30 23:42:14 +00:00
|
|
|
|
|
|
|
P_FindParticleSubsectors();
|
|
|
|
PO_LinkToSubsectors();
|
2017-03-12 17:54:39 +00:00
|
|
|
R_SetupFrame(Thread.Viewport->viewpoint, Thread.Viewport->viewwindow, actor);
|
|
|
|
swrenderer::CameraLight::Instance()->SetCamera(Thread.Viewport.get(), actor);
|
|
|
|
Thread.Viewport->SetupFreelook();
|
2017-01-15 00:54:25 +00:00
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
ActorRenderFlags savedflags = Thread.Viewport->viewpoint.camera->renderflags;
|
2016-11-30 23:42:14 +00:00
|
|
|
// Never draw the player unless in chasecam mode
|
2017-03-12 17:54:39 +00:00
|
|
|
if (!Thread.Viewport->viewpoint.showviewer)
|
|
|
|
Thread.Viewport->viewpoint.camera->renderflags |= RF_INVISIBLE;
|
2016-11-30 23:42:14 +00:00
|
|
|
|
2016-11-16 10:18:40 +00:00
|
|
|
ClearBuffers();
|
2016-11-18 13:40:53 +00:00
|
|
|
SetSceneViewport();
|
2016-11-16 10:18:40 +00:00
|
|
|
SetupPerspectiveMatrix();
|
2016-11-26 09:49:29 +00:00
|
|
|
MainPortal.SetViewpoint(WorldToClip, Vec4f(0.0f, 0.0f, 0.0f, 1.0f), GetNextStencilValue());
|
2016-11-25 17:15:48 +00:00
|
|
|
MainPortal.Render(0);
|
2016-11-24 04:51:37 +00:00
|
|
|
Skydome.Render(WorldToClip);
|
2016-11-25 17:15:48 +00:00
|
|
|
MainPortal.RenderTranslucent(0);
|
2016-11-16 10:18:40 +00:00
|
|
|
PlayerSprites.Render();
|
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
Thread.Viewport->viewpoint.camera->renderflags = savedflags;
|
2016-11-30 23:42:14 +00:00
|
|
|
interpolator.RestoreInterpolations ();
|
|
|
|
|
|
|
|
NetUpdate();
|
2016-11-16 10:18:40 +00:00
|
|
|
}
|
|
|
|
|
2016-12-03 13:58:56 +00:00
|
|
|
void PolyRenderer::RenderRemainingPlayerSprites()
|
2016-11-16 10:18:40 +00:00
|
|
|
{
|
|
|
|
PlayerSprites.RenderRemainingSprites();
|
|
|
|
}
|
|
|
|
|
2016-12-03 13:58:56 +00:00
|
|
|
void PolyRenderer::ClearBuffers()
|
2016-11-16 10:18:40 +00:00
|
|
|
{
|
2016-11-07 08:25:12 +00:00
|
|
|
PolyVertexBuffer::Clear();
|
2017-03-12 17:54:39 +00:00
|
|
|
auto viewport = Thread.Viewport.get();
|
2017-02-01 15:02:21 +00:00
|
|
|
PolyStencilBuffer::Instance()->Clear(viewport->RenderTarget->GetWidth(), viewport->RenderTarget->GetHeight(), 0);
|
|
|
|
PolySubsectorGBuffer::Instance()->Resize(viewport->RenderTarget->GetPitch(), viewport->RenderTarget->GetHeight());
|
2016-11-25 16:14:26 +00:00
|
|
|
NextStencilValue = 0;
|
2016-12-08 09:29:52 +00:00
|
|
|
SeenLinePortals.clear();
|
|
|
|
SeenMirrors.clear();
|
2016-11-16 10:18:40 +00:00
|
|
|
}
|
2016-11-09 10:38:07 +00:00
|
|
|
|
2016-12-03 13:58:56 +00:00
|
|
|
void PolyRenderer::SetSceneViewport()
|
2016-11-16 10:18:40 +00:00
|
|
|
{
|
2017-01-15 02:19:03 +00:00
|
|
|
using namespace swrenderer;
|
2017-02-01 15:02:21 +00:00
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
auto viewport = Thread.Viewport.get();
|
2017-01-15 02:19:03 +00:00
|
|
|
|
2017-02-01 15:02:21 +00:00
|
|
|
if (viewport->RenderTarget == screen) // Rendering to screen
|
2016-11-23 20:10:19 +00:00
|
|
|
{
|
|
|
|
int height;
|
|
|
|
if (screenblocks >= 10)
|
|
|
|
height = SCREENHEIGHT;
|
|
|
|
else
|
|
|
|
height = (screenblocks*SCREENHEIGHT / 10) & ~7;
|
2016-11-18 00:58:39 +00:00
|
|
|
|
2016-11-23 20:10:19 +00:00
|
|
|
int bottom = SCREENHEIGHT - (height + viewwindowy - ((height - viewheight) / 2));
|
2017-02-01 15:02:21 +00:00
|
|
|
PolyTriangleDrawer::set_viewport(viewwindowx, SCREENHEIGHT - bottom - height, viewwidth, height, viewport->RenderTarget);
|
2016-11-23 20:10:19 +00:00
|
|
|
}
|
|
|
|
else // Rendering to camera texture
|
|
|
|
{
|
2017-02-01 15:02:21 +00:00
|
|
|
PolyTriangleDrawer::set_viewport(0, 0, viewport->RenderTarget->GetWidth(), viewport->RenderTarget->GetHeight(), viewport->RenderTarget);
|
2016-11-23 20:10:19 +00:00
|
|
|
}
|
2016-11-18 13:40:53 +00:00
|
|
|
}
|
|
|
|
|
2016-12-03 13:58:56 +00:00
|
|
|
void PolyRenderer::SetupPerspectiveMatrix()
|
2016-11-18 13:40:53 +00:00
|
|
|
{
|
|
|
|
static bool bDidSetup = false;
|
|
|
|
|
|
|
|
if (!bDidSetup)
|
|
|
|
{
|
|
|
|
InitGLRMapinfoData();
|
|
|
|
bDidSetup = true;
|
|
|
|
}
|
2016-11-17 07:50:54 +00:00
|
|
|
|
2016-11-17 21:44:55 +00:00
|
|
|
// 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.
|
2017-03-12 17:54:39 +00:00
|
|
|
const auto &viewpoint = Thread.Viewport->viewpoint;
|
|
|
|
const auto &viewwindow = Thread.Viewport->viewwindow;
|
|
|
|
double radPitch = viewpoint.Angles.Pitch.Normalized180().Radians();
|
2016-11-17 21:44:55 +00:00
|
|
|
double angx = cos(radPitch);
|
2017-03-14 17:31:11 +00:00
|
|
|
double angy = sin(radPitch) * level.info->pixelstretch;
|
2016-11-17 21:44:55 +00:00
|
|
|
double alen = sqrt(angx*angx + angy*angy);
|
2016-11-18 13:40:53 +00:00
|
|
|
float adjustedPitch = (float)asin(angy / alen);
|
2017-03-12 17:54:39 +00:00
|
|
|
float adjustedViewAngle = (float)(viewpoint.Angles.Yaw - 90).Radians();
|
2016-11-17 21:44:55 +00:00
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
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);
|
2016-11-18 13:40:53 +00:00
|
|
|
|
2016-11-07 08:25:12 +00:00
|
|
|
TriMatrix worldToView =
|
2016-11-18 13:40:53 +00:00
|
|
|
TriMatrix::rotate(adjustedPitch, 1.0f, 0.0f, 0.0f) *
|
|
|
|
TriMatrix::rotate(adjustedViewAngle, 0.0f, -1.0f, 0.0f) *
|
2017-03-14 17:31:11 +00:00
|
|
|
TriMatrix::scale(1.0f, level.info->pixelstretch, 1.0f) *
|
2016-11-07 08:25:12 +00:00
|
|
|
TriMatrix::swapYZ() *
|
2017-03-12 17:54:39 +00:00
|
|
|
TriMatrix::translate((float)-viewpoint.Pos.X, (float)-viewpoint.Pos.Y, (float)-viewpoint.Pos.Z);
|
2016-11-18 00:58:39 +00:00
|
|
|
|
2016-11-14 13:19:48 +00:00
|
|
|
WorldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
|
2016-11-16 10:18:40 +00:00
|
|
|
}
|
2016-12-08 09:29:52 +00:00
|
|
|
|
|
|
|
bool PolyRenderer::InsertSeenLinePortal(FLinePortal *portal)
|
|
|
|
{
|
|
|
|
return SeenLinePortals.insert(portal).second;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PolyRenderer::InsertSeenMirror(line_t *mirrorLine)
|
|
|
|
{
|
|
|
|
return SeenMirrors.insert(mirrorLine).second;
|
|
|
|
}
|