2016-03-01 15:47:10 +00:00
|
|
|
// Emacs style mode select -*- C++ -*-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// $Id:$
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// $Log:$
|
|
|
|
//
|
|
|
|
// DESCRIPTION:
|
|
|
|
// Rendering main loop and setup functions,
|
|
|
|
// utility functions (BSP, geometry, trigonometry).
|
|
|
|
// See tables.c, too.
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// HEADER FILES ------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include "templates.h"
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "d_net.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "m_bbox.h"
|
2016-12-28 00:56:37 +00:00
|
|
|
#include "r_main.h"
|
|
|
|
#include "scene/r_things.h"
|
|
|
|
#include "drawers/r_draw.h"
|
2016-12-27 05:31:55 +00:00
|
|
|
#include "scene/r_plane.h"
|
|
|
|
#include "scene/r_bsp.h"
|
2016-12-28 06:04:13 +00:00
|
|
|
#include "scene/r_draw_segment.h"
|
|
|
|
#include "scene/r_portal_segment.h"
|
|
|
|
#include "scene/r_clip_segment.h"
|
2016-12-27 05:31:55 +00:00
|
|
|
#include "scene/r_segs.h"
|
|
|
|
#include "scene/r_3dfloors.h"
|
2016-12-30 05:08:47 +00:00
|
|
|
#include "scene/r_portal.h"
|
2016-03-01 15:47:10 +00:00
|
|
|
#include "r_sky.h"
|
2016-12-27 05:31:55 +00:00
|
|
|
#include "drawers/r_draw_rgba.h"
|
2016-03-01 15:47:10 +00:00
|
|
|
#include "st_stuff.h"
|
|
|
|
#include "c_cvars.h"
|
|
|
|
#include "c_dispatch.h"
|
|
|
|
#include "v_video.h"
|
|
|
|
#include "stats.h"
|
|
|
|
#include "i_video.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "a_sharedglobal.h"
|
|
|
|
#include "r_data/r_translate.h"
|
|
|
|
#include "p_3dmidtex.h"
|
|
|
|
#include "r_data/r_interpolate.h"
|
|
|
|
#include "v_palette.h"
|
|
|
|
#include "po_man.h"
|
|
|
|
#include "p_effect.h"
|
|
|
|
#include "st_start.h"
|
|
|
|
#include "v_font.h"
|
|
|
|
#include "r_data/colormaps.h"
|
2016-05-09 21:16:06 +00:00
|
|
|
#include "p_maputl.h"
|
2016-11-07 08:25:12 +00:00
|
|
|
#include "p_setup.h"
|
|
|
|
#include "version.h"
|
2016-09-24 07:36:37 +00:00
|
|
|
|
2016-12-01 01:38:32 +00:00
|
|
|
CVAR (String, r_viewsize, "", CVAR_NOSET)
|
|
|
|
CVAR (Bool, r_shadercolormaps, true, CVAR_ARCHIVE)
|
|
|
|
|
|
|
|
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
|
|
|
|
|
2016-12-22 04:20:53 +00:00
|
|
|
namespace swrenderer
|
2016-12-01 01:38:32 +00:00
|
|
|
{
|
|
|
|
|
2016-03-01 15:47:10 +00:00
|
|
|
// MACROS ------------------------------------------------------------------
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
#define TEST_X 32343794
|
|
|
|
#define TEST_Y 111387517
|
|
|
|
#define TEST_Z 2164524
|
|
|
|
#define TEST_ANGLE 2468347904
|
|
|
|
#endif
|
|
|
|
|
2016-04-01 10:22:16 +00:00
|
|
|
|
2016-03-01 15:47:10 +00:00
|
|
|
// TYPES -------------------------------------------------------------------
|
|
|
|
|
|
|
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
|
|
|
|
|
|
|
void R_SpanInitData ();
|
|
|
|
void R_DeinitSprites();
|
|
|
|
|
|
|
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
|
|
|
|
|
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
|
|
|
|
|
|
|
static void R_ShutdownRenderer();
|
|
|
|
|
|
|
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
|
|
|
|
|
|
|
extern short *openings;
|
|
|
|
extern bool r_fakingunderwater;
|
2016-12-06 04:07:37 +00:00
|
|
|
extern int fuzzviewheight;
|
2016-03-08 11:27:01 +00:00
|
|
|
extern subsector_t *InSubsector;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
// PRIVATE DATA DECLARATIONS -----------------------------------------------
|
|
|
|
|
2016-04-14 22:18:17 +00:00
|
|
|
static double CurrentVisibility = 8.f;
|
|
|
|
static double MaxVisForWall;
|
|
|
|
static double MaxVisForFloor;
|
2016-03-01 15:47:10 +00:00
|
|
|
bool r_dontmaplines;
|
|
|
|
|
|
|
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
|
|
|
|
2016-05-31 07:36:18 +00:00
|
|
|
bool r_swtruecolor;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-14 22:18:17 +00:00
|
|
|
double r_BaseVisibility;
|
|
|
|
double r_WallVisibility;
|
|
|
|
double r_FloorVisibility;
|
2016-03-01 15:47:10 +00:00
|
|
|
float r_TiltVisibility;
|
2016-04-14 22:18:17 +00:00
|
|
|
double r_SpriteVisibility;
|
|
|
|
double r_ParticleVisibility;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-14 22:18:17 +00:00
|
|
|
double GlobVis;
|
2016-03-01 15:47:10 +00:00
|
|
|
fixed_t viewingrangerecip;
|
2016-04-14 17:40:14 +00:00
|
|
|
double FocalLengthX;
|
|
|
|
double FocalLengthY;
|
2016-03-01 15:47:10 +00:00
|
|
|
FDynamicColormap*basecolormap; // [RH] colormap currently drawing with
|
|
|
|
int fixedlightlev;
|
2016-09-14 08:03:39 +00:00
|
|
|
FSWColormap *fixedcolormap;
|
2016-03-01 15:47:10 +00:00
|
|
|
FSpecialColormap *realfixedcolormap;
|
2016-04-14 17:40:14 +00:00
|
|
|
double WallTMapScale2;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
bool bRenderingToCanvas; // [RH] True if rendering to a special canvas
|
2016-04-14 17:40:14 +00:00
|
|
|
double globaluclip, globaldclip;
|
|
|
|
double CenterX, CenterY;
|
|
|
|
double YaspectMul;
|
|
|
|
double BaseYaspectMul; // yaspectmul without a forced aspect ratio
|
|
|
|
double IYaspectMul;
|
|
|
|
double InvZtoScale;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
// just for profiling purposes
|
|
|
|
int linecount;
|
|
|
|
int loopcount;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// precalculated math tables
|
|
|
|
//
|
|
|
|
|
|
|
|
// The xtoviewangleangle[] table maps a screen pixel
|
|
|
|
// to the lowest viewangle that maps back to x ranges
|
|
|
|
// from clipangle to -clipangle.
|
|
|
|
angle_t xtoviewangle[MAXWIDTH+1];
|
|
|
|
|
|
|
|
bool foggy; // [RH] ignore extralight and fullbright?
|
|
|
|
int r_actualextralight;
|
|
|
|
|
|
|
|
cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
|
|
|
|
|
|
|
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
|
|
|
|
|
|
|
static int lastcenteryfrac;
|
|
|
|
|
|
|
|
// CODE --------------------------------------------------------------------
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_InitTextureMapping
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void R_InitTextureMapping ()
|
|
|
|
{
|
2016-04-28 14:27:28 +00:00
|
|
|
int i;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-28 14:27:28 +00:00
|
|
|
// Calc focallength so FieldOfView angles cover viewwidth.
|
2016-04-14 17:40:14 +00:00
|
|
|
FocalLengthX = CenterX / FocalTangent;
|
|
|
|
FocalLengthY = FocalLengthX * YaspectMul;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
// This is 1/FocalTangent before the widescreen extension of FOV.
|
2016-04-28 11:59:06 +00:00
|
|
|
viewingrangerecip = FLOAT2FIXED(1. / tan(FieldOfView.Radians() / 2));
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-28 14:27:28 +00:00
|
|
|
|
|
|
|
// Now generate xtoviewangle for sky texture mapping.
|
2016-03-01 15:47:10 +00:00
|
|
|
// [RH] Do not generate viewangletox, because texture mapping is no
|
|
|
|
// longer done with trig, so it's not needed.
|
2016-04-28 14:27:28 +00:00
|
|
|
const double slopestep = FocalTangent / centerx;
|
|
|
|
double slope;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-28 14:27:28 +00:00
|
|
|
for (i = centerx, slope = 0; i <= viewwidth; i++, slope += slopestep)
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
2016-04-28 14:27:28 +00:00
|
|
|
xtoviewangle[i] = angle_t((2 * M_PI - atan(slope)) * (ANGLE_180 / M_PI));
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
2016-04-28 14:27:28 +00:00
|
|
|
for (i = 0; i < centerx; i++)
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
2016-04-28 14:27:28 +00:00
|
|
|
xtoviewangle[i] = 0 - xtoviewangle[viewwidth - i - 1];
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_SetVisibility
|
|
|
|
//
|
|
|
|
// Changes how rapidly things get dark with distance
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2016-04-14 22:18:17 +00:00
|
|
|
void R_SetVisibility(double vis)
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
|
|
|
// Allow negative visibilities, just for novelty's sake
|
2016-04-14 22:18:17 +00:00
|
|
|
vis = clamp(vis, -204.7, 204.7); // (205 and larger do not work in 5:4 aspect ratio)
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
CurrentVisibility = vis;
|
|
|
|
|
|
|
|
if (FocalTangent == 0 || FocalLengthY == 0)
|
|
|
|
{ // If r_visibility is called before the renderer is all set up, don't
|
|
|
|
// divide by zero. This will be called again later, and the proper
|
|
|
|
// values can be initialized then.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-04-14 22:18:17 +00:00
|
|
|
r_BaseVisibility = vis;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
// Prevent overflow on walls
|
|
|
|
if (r_BaseVisibility < 0 && r_BaseVisibility < -MaxVisForWall)
|
|
|
|
r_WallVisibility = -MaxVisForWall;
|
|
|
|
else if (r_BaseVisibility > 0 && r_BaseVisibility > MaxVisForWall)
|
|
|
|
r_WallVisibility = MaxVisForWall;
|
|
|
|
else
|
|
|
|
r_WallVisibility = r_BaseVisibility;
|
|
|
|
|
2016-09-12 13:51:50 +00:00
|
|
|
r_WallVisibility = (InvZtoScale * SCREENWIDTH*AspectBaseHeight(WidescreenRatio) /
|
2016-04-14 22:18:17 +00:00
|
|
|
(viewwidth*SCREENHEIGHT*3)) * (r_WallVisibility * FocalTangent);
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
// Prevent overflow on floors/ceilings. Note that the calculation of
|
|
|
|
// MaxVisForFloor means that planes less than two units from the player's
|
|
|
|
// view could still overflow, but there is no way to totally eliminate
|
|
|
|
// that while still using fixed point math.
|
|
|
|
if (r_BaseVisibility < 0 && r_BaseVisibility < -MaxVisForFloor)
|
|
|
|
r_FloorVisibility = -MaxVisForFloor;
|
|
|
|
else if (r_BaseVisibility > 0 && r_BaseVisibility > MaxVisForFloor)
|
|
|
|
r_FloorVisibility = MaxVisForFloor;
|
|
|
|
else
|
|
|
|
r_FloorVisibility = r_BaseVisibility;
|
|
|
|
|
2016-04-14 22:18:17 +00:00
|
|
|
r_FloorVisibility = 160.0 * r_FloorVisibility / FocalLengthY;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-14 22:18:17 +00:00
|
|
|
r_TiltVisibility = float(vis * FocalTangent * (16.f * 320.f) / viewwidth);
|
2016-03-01 15:47:10 +00:00
|
|
|
r_SpriteVisibility = r_WallVisibility;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_GetVisibility
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2016-04-14 22:18:17 +00:00
|
|
|
double R_GetVisibility()
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
|
|
|
return CurrentVisibility;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// CCMD r_visibility
|
|
|
|
//
|
|
|
|
// Controls how quickly light ramps across a 1/z range. Set this, and it
|
|
|
|
// sets all the r_*Visibility variables (except r_SkyVisibilily, which is
|
|
|
|
// currently unused).
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD (r_visibility)
|
|
|
|
{
|
|
|
|
if (argv.argc() < 2)
|
|
|
|
{
|
|
|
|
Printf ("Visibility is %g\n", R_GetVisibility());
|
|
|
|
}
|
|
|
|
else if (!netgame)
|
|
|
|
{
|
2016-04-14 22:18:17 +00:00
|
|
|
R_SetVisibility(atof(argv[1]));
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Printf ("Visibility cannot be changed in net games.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_SetWindow
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2016-09-12 13:51:50 +00:00
|
|
|
void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio)
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
|
|
|
int virtheight, virtwidth, virtwidth2, virtheight2;
|
|
|
|
|
|
|
|
if (!bRenderingToCanvas)
|
|
|
|
{ // Set r_viewsize cvar to reflect the current view size
|
|
|
|
UCVarValue value;
|
|
|
|
char temp[16];
|
|
|
|
|
|
|
|
mysnprintf (temp, countof(temp), "%d x %d", viewwidth, viewheight);
|
|
|
|
value.String = temp;
|
|
|
|
r_viewsize.ForceSet (value, CVAR_String);
|
|
|
|
}
|
|
|
|
|
|
|
|
fuzzviewheight = viewheight - 2; // Maximum row the fuzzer can draw to
|
|
|
|
|
|
|
|
lastcenteryfrac = 1<<30;
|
2016-04-14 17:40:14 +00:00
|
|
|
CenterX = centerx;
|
|
|
|
CenterY = centery;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
virtwidth = virtwidth2 = fullWidth;
|
|
|
|
virtheight = virtheight2 = fullHeight;
|
|
|
|
|
2016-09-13 21:26:30 +00:00
|
|
|
if (AspectTallerThanWide(trueratio))
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
2016-09-12 13:51:50 +00:00
|
|
|
virtheight2 = virtheight2 * AspectMultiplier(trueratio) / 48;
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-09-12 13:51:50 +00:00
|
|
|
virtwidth2 = virtwidth2 * AspectMultiplier(trueratio) / 48;
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
|
2016-09-13 21:26:30 +00:00
|
|
|
if (AspectTallerThanWide(WidescreenRatio))
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
2016-09-12 13:51:50 +00:00
|
|
|
virtheight = virtheight * AspectMultiplier(WidescreenRatio) / 48;
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-09-12 13:51:50 +00:00
|
|
|
virtwidth = virtwidth * AspectMultiplier(WidescreenRatio) / 48;
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
|
2016-04-14 17:40:14 +00:00
|
|
|
BaseYaspectMul = 320.0 * virtheight2 / (r_Yaspect * virtwidth2);
|
|
|
|
YaspectMul = 320.0 * virtheight / (r_Yaspect * virtwidth);
|
|
|
|
IYaspectMul = (double)virtwidth * r_Yaspect / 320.0 / virtheight;
|
|
|
|
InvZtoScale = YaspectMul * CenterX;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-23 03:54:04 +00:00
|
|
|
WallTMapScale2 = IYaspectMul / CenterX;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
// psprite scales
|
2016-04-15 01:09:38 +00:00
|
|
|
pspritexscale = centerxwide / 160.0;
|
|
|
|
pspriteyscale = pspritexscale * YaspectMul;
|
|
|
|
pspritexiscale = 1 / pspritexscale;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
// thing clipping
|
2016-12-09 12:04:53 +00:00
|
|
|
fillshort (screenheightarray, viewwidth, (short)viewheight);
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
R_InitTextureMapping ();
|
|
|
|
|
2016-04-14 22:18:17 +00:00
|
|
|
MaxVisForWall = (InvZtoScale * (SCREENWIDTH*r_Yaspect) /
|
|
|
|
(viewwidth*SCREENHEIGHT * FocalTangent));
|
|
|
|
MaxVisForWall = 32767.0 / MaxVisForWall;
|
2016-11-02 05:07:57 +00:00
|
|
|
MaxVisForFloor = 32767.0 / (viewheight >> 2) * FocalLengthY / 160;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
// Reset r_*Visibility vars
|
2016-04-14 22:18:17 +00:00
|
|
|
R_SetVisibility(R_GetVisibility());
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_Init
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void R_InitRenderer()
|
|
|
|
{
|
|
|
|
atterm(R_ShutdownRenderer);
|
|
|
|
// viewwidth / viewheight are set by the defaults
|
2016-12-09 12:04:53 +00:00
|
|
|
fillshort (zeroarray, MAXWIDTH, 0);
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
R_InitShadeMaps();
|
|
|
|
R_InitColumnDrawers ();
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_ShutdownRenderer
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void R_ShutdownRenderer()
|
|
|
|
{
|
|
|
|
R_DeinitSprites();
|
|
|
|
R_DeinitPlanes();
|
2016-12-30 05:42:20 +00:00
|
|
|
fakeActive = 0;
|
2016-03-01 15:47:10 +00:00
|
|
|
// Free openings
|
|
|
|
if (openings != NULL)
|
|
|
|
{
|
|
|
|
M_Free (openings);
|
|
|
|
openings = NULL;
|
|
|
|
}
|
|
|
|
|
2016-12-30 04:01:42 +00:00
|
|
|
R_FreeDrawSegs();
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_CopyStackedViewParameters
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void R_CopyStackedViewParameters()
|
|
|
|
{
|
2016-04-14 17:40:14 +00:00
|
|
|
stacked_viewpos = ViewPos;
|
|
|
|
stacked_angle = ViewAngle;
|
2016-03-01 15:47:10 +00:00
|
|
|
stacked_extralight = extralight;
|
|
|
|
stacked_visibility = R_GetVisibility();
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_SetupColormap
|
|
|
|
//
|
|
|
|
// Sets up special fixed colormaps
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void R_SetupColormap(player_t *player)
|
|
|
|
{
|
|
|
|
realfixedcolormap = NULL;
|
|
|
|
fixedcolormap = NULL;
|
|
|
|
fixedlightlev = -1;
|
|
|
|
|
|
|
|
if (player != NULL && camera == player->mo)
|
|
|
|
{
|
|
|
|
if (player->fixedcolormap >= 0 && player->fixedcolormap < (int)SpecialColormaps.Size())
|
|
|
|
{
|
|
|
|
realfixedcolormap = &SpecialColormaps[player->fixedcolormap];
|
2016-06-12 20:54:23 +00:00
|
|
|
if (RenderTarget == screen && (r_swtruecolor || ((DFrameBuffer *)screen->Accel2D && r_shadercolormaps)))
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
|
|
|
// Render everything fullbright. The copy to video memory will
|
|
|
|
// apply the special colormap, so it won't be restricted to the
|
|
|
|
// palette.
|
2016-06-05 12:08:03 +00:00
|
|
|
fixedcolormap = &realcolormaps;
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-06-05 12:08:03 +00:00
|
|
|
fixedcolormap = &SpecialColormaps[player->fixedcolormap];
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (player->fixedlightlevel >= 0 && player->fixedlightlevel < NUMCOLORMAPS)
|
|
|
|
{
|
|
|
|
fixedlightlev = player->fixedlightlevel * 256;
|
2016-10-19 06:02:37 +00:00
|
|
|
// [SP] Emulate GZDoom's light-amp goggles.
|
|
|
|
if (r_fullbrightignoresectorcolor && fixedlightlev >= 0)
|
|
|
|
{
|
|
|
|
fixedcolormap = &FullNormalLight;
|
|
|
|
}
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// [RH] Inverse light for shooting the Sigil
|
|
|
|
if (fixedcolormap == NULL && extralight == INT_MIN)
|
|
|
|
{
|
2016-06-05 12:08:03 +00:00
|
|
|
fixedcolormap = &SpecialColormaps[INVERSECOLORMAP];
|
2016-03-01 15:47:10 +00:00
|
|
|
extralight = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_SetupFreelook
|
|
|
|
//
|
|
|
|
// [RH] freelook stuff
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void R_SetupFreelook()
|
|
|
|
{
|
2016-04-29 02:07:58 +00:00
|
|
|
double dy;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-29 02:07:58 +00:00
|
|
|
if (camera != NULL)
|
|
|
|
{
|
|
|
|
dy = FocalLengthY * (-ViewPitch).Tan();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dy = 0;
|
|
|
|
}
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-29 02:07:58 +00:00
|
|
|
CenterY = (viewheight / 2.0) + dy;
|
|
|
|
centery = xs_ToInt(CenterY);
|
|
|
|
globaluclip = -CenterY / InvZtoScale;
|
|
|
|
globaldclip = (viewheight - CenterY) / InvZtoScale;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-29 02:07:58 +00:00
|
|
|
//centeryfrac &= 0xffff0000;
|
|
|
|
int e, i;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
2016-04-29 02:07:58 +00:00
|
|
|
i = 0;
|
|
|
|
e = viewheight;
|
|
|
|
float focus = float(FocalLengthY);
|
|
|
|
float den;
|
|
|
|
float cy = float(CenterY);
|
|
|
|
if (i < centery)
|
|
|
|
{
|
|
|
|
den = cy - i - 0.5f;
|
|
|
|
if (e <= centery)
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
2016-04-29 02:07:58 +00:00
|
|
|
do {
|
|
|
|
yslope[i] = focus / den;
|
|
|
|
den -= 1;
|
|
|
|
} while (++i < e);
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-04-29 02:07:58 +00:00
|
|
|
do {
|
|
|
|
yslope[i] = focus / den;
|
|
|
|
den -= 1;
|
|
|
|
} while (++i < centery);
|
2016-04-14 17:40:14 +00:00
|
|
|
den = i - cy + 0.5f;
|
2016-03-01 15:47:10 +00:00
|
|
|
do {
|
2016-04-29 02:07:58 +00:00
|
|
|
yslope[i] = focus / den;
|
2016-04-14 17:40:14 +00:00
|
|
|
den += 1;
|
2016-03-01 15:47:10 +00:00
|
|
|
} while (++i < e);
|
|
|
|
}
|
|
|
|
}
|
2016-04-29 02:07:58 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
den = i - cy + 0.5f;
|
|
|
|
do {
|
|
|
|
yslope[i] = focus / den;
|
|
|
|
den += 1;
|
|
|
|
} while (++i < e);
|
|
|
|
}
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_SetupBuffer
|
|
|
|
//
|
|
|
|
// Precalculate all row offsets and fuzz table.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void R_SetupBuffer ()
|
|
|
|
{
|
2016-12-05 07:22:04 +00:00
|
|
|
using namespace drawerargs;
|
|
|
|
|
2016-05-31 03:31:32 +00:00
|
|
|
static BYTE *lastbuff = NULL;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
int pitch = RenderTarget->GetPitch();
|
2016-05-31 03:31:32 +00:00
|
|
|
int pixelsize = r_swtruecolor ? 4 : 1;
|
|
|
|
BYTE *lineptr = RenderTarget->GetBuffer() + (viewwindowy*pitch + viewwindowx) * pixelsize;
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
if (dc_pitch != pitch || lineptr != lastbuff)
|
|
|
|
{
|
|
|
|
if (dc_pitch != pitch)
|
|
|
|
{
|
|
|
|
dc_pitch = pitch;
|
|
|
|
R_InitFuzzTable (pitch);
|
|
|
|
}
|
|
|
|
dc_destorg = lineptr;
|
2016-10-17 10:36:01 +00:00
|
|
|
dc_destheight = RenderTarget->GetHeight() - viewwindowy;
|
2016-03-01 15:47:10 +00:00
|
|
|
for (int i = 0; i < RenderTarget->GetHeight(); i++)
|
|
|
|
{
|
|
|
|
ylookup[i] = i * pitch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_RenderActorView
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void R_RenderActorView (AActor *actor, bool dontmaplines)
|
|
|
|
{
|
|
|
|
WallCycles.Reset();
|
|
|
|
PlaneCycles.Reset();
|
|
|
|
MaskedCycles.Reset();
|
|
|
|
WallScanCycles.Reset();
|
|
|
|
|
|
|
|
fakeActive = 0; // kg3D - reset fake floor indicator
|
|
|
|
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
|
|
|
|
|
|
|
R_SetupBuffer ();
|
|
|
|
R_SetupFrame (actor);
|
|
|
|
|
|
|
|
// Clear buffers.
|
|
|
|
R_ClearClipSegs (0, viewwidth);
|
|
|
|
R_ClearDrawSegs ();
|
|
|
|
R_ClearPlanes (true);
|
|
|
|
R_ClearSprites ();
|
|
|
|
|
|
|
|
NetUpdate ();
|
|
|
|
|
|
|
|
// [RH] Show off segs if r_drawflat is 1
|
|
|
|
if (r_drawflat)
|
|
|
|
{
|
2016-12-27 22:53:47 +00:00
|
|
|
colfunc = &SWPixelFormatDrawers::FillColumn;
|
|
|
|
spanfunc = &SWPixelFormatDrawers::FillSpan;
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
colfunc = basecolfunc;
|
2016-12-27 22:53:47 +00:00
|
|
|
spanfunc = &SWPixelFormatDrawers::DrawSpan;
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WindowLeft = 0;
|
|
|
|
WindowRight = viewwidth;
|
|
|
|
MirrorFlags = 0;
|
|
|
|
CurrentPortal = NULL;
|
|
|
|
CurrentPortalUniq = 0;
|
|
|
|
|
|
|
|
r_dontmaplines = dontmaplines;
|
|
|
|
|
|
|
|
// [RH] Hack to make windows into underwater areas possible
|
|
|
|
r_fakingunderwater = false;
|
|
|
|
|
|
|
|
// [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();
|
2016-03-08 11:27:01 +00:00
|
|
|
InSubsector = NULL;
|
2016-11-30 23:42:14 +00:00
|
|
|
R_RenderBSPNode(nodes + numnodes - 1); // The head node is the last node output.
|
2016-03-01 15:47:10 +00:00
|
|
|
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
|
|
|
camera->renderflags = savedflags;
|
|
|
|
WallCycles.Unclock();
|
|
|
|
|
|
|
|
NetUpdate ();
|
|
|
|
|
|
|
|
if (viewactive)
|
|
|
|
{
|
|
|
|
PlaneCycles.Clock();
|
2016-11-30 23:42:14 +00:00
|
|
|
R_DrawPlanes();
|
|
|
|
R_DrawPortals();
|
2016-03-01 15:47:10 +00:00
|
|
|
PlaneCycles.Unclock();
|
|
|
|
|
2016-12-30 05:08:47 +00:00
|
|
|
R_DrawWallPortals();
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
NetUpdate ();
|
|
|
|
|
|
|
|
MaskedCycles.Clock();
|
2016-11-30 23:42:14 +00:00
|
|
|
R_DrawMasked ();
|
2016-03-01 15:47:10 +00:00
|
|
|
MaskedCycles.Unclock();
|
|
|
|
|
|
|
|
NetUpdate ();
|
|
|
|
}
|
|
|
|
WallPortals.Clear ();
|
|
|
|
interpolator.RestoreInterpolations ();
|
|
|
|
R_SetupBuffer ();
|
|
|
|
|
|
|
|
// If we don't want shadered colormaps, NULL it now so that the
|
|
|
|
// copy to the screen does not use a special colormap shader.
|
2016-06-12 20:54:23 +00:00
|
|
|
if (!r_shadercolormaps && !r_swtruecolor)
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
|
|
|
realfixedcolormap = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_RenderViewToCanvas
|
|
|
|
//
|
|
|
|
// Pre: Canvas is already locked.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void R_RenderViewToCanvas (AActor *actor, DCanvas *canvas,
|
|
|
|
int x, int y, int width, int height, bool dontmaplines)
|
|
|
|
{
|
|
|
|
const bool savedviewactive = viewactive;
|
2016-05-31 07:36:18 +00:00
|
|
|
const bool savedoutputformat = r_swtruecolor;
|
|
|
|
|
|
|
|
if (r_swtruecolor != canvas->IsBgra())
|
|
|
|
{
|
|
|
|
r_swtruecolor = canvas->IsBgra();
|
|
|
|
R_InitColumnDrawers();
|
|
|
|
}
|
2016-06-10 16:43:49 +00:00
|
|
|
|
|
|
|
R_BeginDrawerCommands();
|
2016-03-01 15:47:10 +00:00
|
|
|
|
|
|
|
viewwidth = width;
|
|
|
|
RenderTarget = canvas;
|
|
|
|
bRenderingToCanvas = true;
|
|
|
|
|
2016-09-13 21:26:30 +00:00
|
|
|
R_SetWindow (12, width, height, height, true);
|
2016-03-01 15:47:10 +00:00
|
|
|
viewwindowx = x;
|
|
|
|
viewwindowy = y;
|
|
|
|
viewactive = true;
|
|
|
|
|
|
|
|
R_RenderActorView (actor, dontmaplines);
|
|
|
|
|
2016-06-13 01:16:48 +00:00
|
|
|
R_EndDrawerCommands();
|
|
|
|
|
2016-03-01 15:47:10 +00:00
|
|
|
RenderTarget = screen;
|
|
|
|
bRenderingToCanvas = false;
|
|
|
|
R_ExecuteSetViewSize ();
|
|
|
|
screen->Lock (true);
|
|
|
|
R_SetupBuffer ();
|
|
|
|
screen->Unlock ();
|
2016-05-31 07:36:18 +00:00
|
|
|
|
2016-03-01 15:47:10 +00:00
|
|
|
viewactive = savedviewactive;
|
2016-05-31 07:36:18 +00:00
|
|
|
r_swtruecolor = savedoutputformat;
|
|
|
|
|
|
|
|
if (r_swtruecolor != canvas->IsBgra())
|
|
|
|
{
|
|
|
|
R_InitColumnDrawers();
|
|
|
|
}
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// R_MultiresInit
|
|
|
|
//
|
|
|
|
// Called from V_SetResolution()
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void R_MultiresInit ()
|
|
|
|
{
|
|
|
|
R_PlaneInitData ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// STAT fps
|
|
|
|
//
|
|
|
|
// Displays statistics about rendering times
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// STAT wallcycles
|
|
|
|
//
|
|
|
|
// Displays the minimum number of cycles spent drawing walls
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
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
|
|
|
|
//
|
|
|
|
// Resets the count of minimum wall drawing cycles
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD (clearwallcycles)
|
|
|
|
{
|
|
|
|
bestwallcycles = HUGE_VAL;
|
|
|
|
}
|
|
|
|
|
2016-12-09 13:25:51 +00:00
|
|
|
#if 0
|
|
|
|
// The replacement code for Build's wallscan doesn't have any timing calls so this does not work anymore.
|
2016-03-01 15:47:10 +00:00
|
|
|
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
|
2016-12-01 01:38:32 +00:00
|
|
|
|
|
|
|
}
|