gzdoom-gles/src/swrenderer/scene/r_scene.cpp
2017-01-15 22:57:42 +01:00

342 lines
8.4 KiB
C++

//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
#include <stdlib.h>
#include <float.h>
#include "templates.h"
#include "i_system.h"
#include "w_wad.h"
#include "doomdef.h"
#include "doomstat.h"
#include "r_sky.h"
#include "stats.h"
#include "v_video.h"
#include "a_sharedglobal.h"
#include "c_console.h"
#include "c_dispatch.h"
#include "cmdlib.h"
#include "d_net.h"
#include "g_level.h"
#include "p_effect.h"
#include "po_man.h"
#include "st_stuff.h"
#include "r_data/r_interpolate.h"
#include "swrenderer/scene/r_scene.h"
#include "swrenderer/scene/r_viewport.h"
#include "swrenderer/scene/r_light.h"
#include "swrenderer/scene/r_3dfloors.h"
#include "swrenderer/scene/r_opaque_pass.h"
#include "swrenderer/scene/r_translucent_pass.h"
#include "swrenderer/scene/r_portal.h"
#include "swrenderer/segments/r_clipsegment.h"
#include "swrenderer/segments/r_drawsegment.h"
#include "swrenderer/segments/r_portalsegment.h"
#include "swrenderer/plane/r_visibleplanelist.h"
#include "swrenderer/drawers/r_draw.h"
#include "swrenderer/drawers/r_draw_rgba.h"
#include "swrenderer/drawers/r_thread.h"
#include "swrenderer/r_memory.h"
EXTERN_CVAR(Bool, r_shadercolormaps)
EXTERN_CVAR(Int, r_clearbuffer)
namespace swrenderer
{
cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
RenderScene *RenderScene::Instance()
{
static RenderScene instance;
return &instance;
}
void RenderScene::SetClearColor(int color)
{
clearcolor = color;
}
void RenderScene::RenderView(player_t *player)
{
RenderTarget = screen;
int width = SCREENWIDTH;
int height = SCREENHEIGHT;
float trueratio;
ActiveRatio(width, height, &trueratio);
RenderViewport::Instance()->SetViewport(width, height, trueratio);
if (r_swtruecolor != screen->IsBgra())
{
r_swtruecolor = screen->IsBgra();
R_InitColumnDrawers();
}
if (r_clearbuffer != 0)
{
if (!r_swtruecolor)
{
memset(RenderTarget->GetBuffer(), clearcolor, RenderTarget->GetPitch() * RenderTarget->GetHeight());
}
else
{
uint32_t bgracolor = GPalette.BaseColors[clearcolor].d;
int size = RenderTarget->GetPitch() * RenderTarget->GetHeight();
uint32_t *dest = (uint32_t *)RenderTarget->GetBuffer();
for (int i = 0; i < size; i++)
dest[i] = bgracolor;
}
}
R_BeginDrawerCommands();
RenderActorView(player->mo);
// Apply special colormap if the target cannot do it
if (realfixedcolormap && r_swtruecolor && !(r_shadercolormaps && screen->Accel2D))
{
DrawerCommandQueue::QueueCommand<ApplySpecialColormapRGBACommand>(realfixedcolormap, screen);
}
R_EndDrawerCommands();
}
void RenderScene::RenderActorView(AActor *actor, bool dontmaplines)
{
WallCycles.Reset();
PlaneCycles.Reset();
MaskedCycles.Reset();
WallScanCycles.Reset();
RenderMemory::Clear();
Clip3DFloors *clip3d = Clip3DFloors::Instance();
clip3d->Cleanup();
clip3d->ResetClip(); // reset clips (floor/ceiling)
R_SetupFrame(actor);
R_SetupColormap(actor);
RenderViewport::Instance()->SetupFreelook();
RenderPortal::Instance()->CopyStackedViewParameters();
// Clear buffers.
RenderClipSegment::Instance()->Clear(0, viewwidth);
R_ClearDrawSegs();
VisiblePlaneList::Instance()->Clear(true);
RenderTranslucentPass::Clear();
// opening / clipping determination
RenderOpaquePass::Instance()->ClearClip();
NetUpdate();
colfunc = basecolfunc;
spanfunc = &SWPixelFormatDrawers::DrawSpan;
RenderPortal::Instance()->SetMainPortal();
this->dontmaplines = dontmaplines;
// [RH] Hack to make windows into underwater areas possible
RenderOpaquePass::Instance()->ResetFakingUnderwater();
// [RH] Setup particles for this frame
P_FindParticleSubsectors();
WallCycles.Clock();
ActorRenderFlags savedflags = camera->renderflags;
// Never draw the player unless in chasecam mode
if (!r_showviewer)
{
camera->renderflags |= RF_INVISIBLE;
}
// Link the polyobjects right before drawing the scene to reduce the amounts of calls to this function
PO_LinkToSubsectors();
RenderOpaquePass::Instance()->RenderScene();
Clip3DFloors::Instance()->ResetClip(); // reset clips (floor/ceiling)
camera->renderflags = savedflags;
WallCycles.Unclock();
NetUpdate();
if (viewactive)
{
PlaneCycles.Clock();
VisiblePlaneList::Instance()->Render();
RenderPortal::Instance()->RenderPlanePortals();
PlaneCycles.Unclock();
RenderPortal::Instance()->RenderLinePortals();
NetUpdate();
MaskedCycles.Clock();
RenderTranslucentPass::Render();
MaskedCycles.Unclock();
NetUpdate();
}
WallPortals.Clear();
interpolator.RestoreInterpolations();
// If we don't want shadered colormaps, NULL it now so that the
// copy to the screen does not use a special colormap shader.
if (!r_shadercolormaps && !r_swtruecolor)
{
realfixedcolormap = NULL;
}
}
void RenderScene::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines)
{
const bool savedviewactive = viewactive;
const bool savedoutputformat = r_swtruecolor;
if (r_swtruecolor != canvas->IsBgra())
{
r_swtruecolor = canvas->IsBgra();
R_InitColumnDrawers();
}
R_BeginDrawerCommands();
viewwidth = width;
RenderTarget = canvas;
bRenderingToCanvas = true;
R_SetWindow(12, width, height, height, true);
viewwindowx = x;
viewwindowy = y;
viewactive = true;
RenderViewport::Instance()->SetViewport(width, height, WidescreenRatio);
RenderActorView(actor, dontmaplines);
R_EndDrawerCommands();
RenderTarget = screen;
bRenderingToCanvas = false;
R_ExecuteSetViewSize();
float trueratio;
ActiveRatio(width, height, &trueratio);
screen->Lock(true);
RenderViewport::Instance()->SetViewport(width, height, trueratio);
screen->Unlock();
viewactive = savedviewactive;
r_swtruecolor = savedoutputformat;
if (r_swtruecolor != canvas->IsBgra())
{
R_InitColumnDrawers();
}
}
void RenderScene::ScreenResized()
{
VisiblePlaneList::Instance()->Init();
RenderTarget = screen;
int width = SCREENWIDTH;
int height = SCREENHEIGHT;
float trueratio;
ActiveRatio(width, height, &trueratio);
screen->Lock(true);
RenderViewport::Instance()->SetViewport(SCREENWIDTH, SCREENHEIGHT, trueratio);
screen->Unlock();
}
void RenderScene::Init()
{
atterm([]() { RenderScene::Instance()->Deinit(); });
// viewwidth / viewheight are set by the defaults
fillshort(zeroarray, MAXWIDTH, 0);
R_InitShadeMaps();
R_InitColumnDrawers();
}
void RenderScene::Deinit()
{
RenderTranslucentPass::Deinit();
VisiblePlaneList::Instance()->Deinit();
Clip3DFloors::Instance()->Cleanup();
R_FreeDrawSegs();
}
/////////////////////////////////////////////////////////////////////////
ADD_STAT(fps)
{
FString out;
out.Format("frame=%04.1f ms walls=%04.1f ms planes=%04.1f ms masked=%04.1f ms",
FrameCycles.TimeMS(), WallCycles.TimeMS(), PlaneCycles.TimeMS(), MaskedCycles.TimeMS());
return out;
}
static double f_acc, w_acc, p_acc, m_acc;
static int acc_c;
ADD_STAT(fps_accumulated)
{
f_acc += FrameCycles.TimeMS();
w_acc += WallCycles.TimeMS();
p_acc += PlaneCycles.TimeMS();
m_acc += MaskedCycles.TimeMS();
acc_c++;
FString out;
out.Format("frame=%04.1f ms walls=%04.1f ms planes=%04.1f ms masked=%04.1f ms %d counts",
f_acc / acc_c, w_acc / acc_c, p_acc / acc_c, m_acc / acc_c, acc_c);
Printf(PRINT_LOG, "%s\n", out.GetChars());
return out;
}
static double bestwallcycles = HUGE_VAL;
ADD_STAT(wallcycles)
{
FString out;
double cycles = WallCycles.Time();
if (cycles && cycles < bestwallcycles)
bestwallcycles = cycles;
out.Format("%g", bestwallcycles);
return out;
}
CCMD(clearwallcycles)
{
bestwallcycles = HUGE_VAL;
}
#if 0
// The replacement code for Build's wallscan doesn't have any timing calls so this does not work anymore.
static double bestscancycles = HUGE_VAL;
ADD_STAT(scancycles)
{
FString out;
double scancycles = WallScanCycles.Time();
if (scancycles && scancycles < bestscancycles)
bestscancycles = scancycles;
out.Format("%g", bestscancycles);
return out;
}
CCMD(clearscancycles)
{
bestscancycles = HUGE_VAL;
}
#endif
}