gzdoom-gles/src/swrenderer/plane/r_slopeplane.cpp

237 lines
8.2 KiB
C++
Raw Normal View History

//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2016 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
//
#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 "cmdlib.h"
#include "d_net.h"
#include "g_level.h"
#include "g_levellocals.h"
#include "swrenderer/scene/r_opaque_pass.h"
#include "r_slopeplane.h"
2016-12-31 11:45:07 +00:00
#include "swrenderer/scene/r_3dfloors.h"
#include "v_palette.h"
#include "r_data/colormaps.h"
#include "swrenderer/drawers/r_draw_rgba.h"
#include "a_dynlight.h"
2016-12-31 11:45:07 +00:00
#include "swrenderer/segments/r_clipsegment.h"
#include "swrenderer/segments/r_drawsegment.h"
#include "swrenderer/scene/r_portal.h"
#include "swrenderer/scene/r_scene.h"
#include "swrenderer/scene/r_light.h"
#include "swrenderer/viewport/r_viewport.h"
2017-01-11 22:27:35 +00:00
#include "swrenderer/plane/r_visibleplane.h"
#include "swrenderer/r_memory.h"
#include "swrenderer/r_renderthread.h"
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
namespace swrenderer
{
RenderSlopePlane::RenderSlopePlane(RenderThread *thread)
{
Thread = thread;
}
void RenderSlopePlane::Render(VisiblePlane *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked, FDynamicColormap *colormap, FTexture *texture)
{
static const float ifloatpow2[16] =
{
// ifloatpow2[i] = 1 / (1 << i)
64.f, 32.f, 16.f, 8.f, 4.f, 2.f, 1.f, 0.5f,
0.25f, 0.125f, 0.0625f, 0.03125f, 0.015625f, 0.0078125f,
0.00390625f, 0.001953125f
/*, 0.0009765625f, 0.00048828125f, 0.000244140625f,
1.220703125e-4f, 6.103515625e-5, 3.0517578125e-5*/
};
double lxscale, lyscale;
double xscale, yscale;
FVector3 p, m, n;
double ang, planeang, cosine, sine;
double zeroheight;
if (alpha <= 0)
{
return;
}
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);
lxscale = _xscale * ifloatpow2[drawerargs.TextureWidthBits()];
lyscale = _yscale * ifloatpow2[drawerargs.TextureHeightBits()];
xscale = 64.f / lxscale;
yscale = 64.f / lyscale;
zeroheight = pl->height.ZatPoint(Thread->Viewport->viewpoint.Pos);
pviewx = xs_ToFixed(32 - drawerargs.TextureWidthBits(), pl->xform.xOffs * pl->xform.xScale);
pviewy = xs_ToFixed(32 - drawerargs.TextureHeightBits(), pl->xform.yOffs * pl->xform.yScale);
planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians();
// p is the texture origin in view space
// Don't add in the offsets at this stage, because doing so can result in
// errors if the flat is rotated.
ang = M_PI * 3 / 2 - Thread->Viewport->viewpoint.Angles.Yaw.Radians();
cosine = cos(ang), sine = sin(ang);
p[0] = Thread->Viewport->viewpoint.Pos.X * cosine - Thread->Viewport->viewpoint.Pos.Y * sine;
p[2] = Thread->Viewport->viewpoint.Pos.X * sine + Thread->Viewport->viewpoint.Pos.Y * cosine;
p[1] = pl->height.ZatPoint(0.0, 0.0) - Thread->Viewport->viewpoint.Pos.Z;
// m is the v direction vector in view space
ang = ang - M_PI / 2 - planeang;
cosine = cos(ang), sine = sin(ang);
m[0] = yscale * cosine;
m[2] = yscale * sine;
// m[1] = pl->height.ZatPointF (0, iyscale) - pl->height.ZatPointF (0,0));
// VectorScale2 (m, 64.f/VectorLength(m));
// n is the u direction vector in view space
#if 0
//let's use the sin/cosine we already know instead of computing new ones
ang += M_PI / 2
n[0] = -xscale * cos(ang);
n[2] = -xscale * sin(ang);
#else
n[0] = xscale * sine;
n[2] = -xscale * cosine;
#endif
// n[1] = pl->height.ZatPointF (ixscale, 0) - pl->height.ZatPointF (0,0));
// VectorScale2 (n, 64.f/VectorLength(n));
// This code keeps the texture coordinates constant across the x,y plane no matter
// how much you slope the surface. Use the commented-out code above instead to keep
// the textures a constant size across the surface's plane instead.
cosine = cos(planeang), sine = sin(planeang);
m[1] = pl->height.ZatPoint(Thread->Viewport->viewpoint.Pos.X + yscale * sine, Thread->Viewport->viewpoint.Pos.Y + yscale * cosine) - zeroheight;
n[1] = -(pl->height.ZatPoint(Thread->Viewport->viewpoint.Pos.X - xscale * cosine, Thread->Viewport->viewpoint.Pos.Y + xscale * sine) - zeroheight);
plane_su = p ^ m;
plane_sv = p ^ n;
plane_sz = m ^ n;
2017-02-01 15:02:21 +00:00
plane_su.Z *= viewport->FocalLengthX;
plane_sv.Z *= viewport->FocalLengthX;
plane_sz.Z *= viewport->FocalLengthX;
2017-02-01 15:02:21 +00:00
plane_su.Y *= viewport->IYaspectMul;
plane_sv.Y *= viewport->IYaspectMul;
plane_sz.Y *= viewport->IYaspectMul;
// Premultiply the texture vectors with the scale factors
plane_su *= 4294967296.f;
plane_sv *= 4294967296.f;
RenderPortal *renderportal = Thread->Portal.get();
2017-01-05 03:55:26 +00:00
if (renderportal->MirrorFlags & RF_XFLIP)
{
plane_su[0] = -plane_su[0];
plane_sv[0] = -plane_sv[0];
plane_sz[0] = -plane_sz[0];
}
// [RH] set foggy flag
basecolormap = colormap;
bool foggy = level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE);;
2017-03-12 19:40:00 +00:00
planelightfloat = (Thread->Light->SlopePlaneGlobVis(foggy) * lxscale * lyscale) / (fabs(pl->height.ZatPoint(Thread->Viewport->viewpoint.Pos) - Thread->Viewport->viewpoint.Pos.Z)) / 65536.f;
if (pl->height.fC() > 0)
planelightfloat = -planelightfloat;
2017-01-12 20:29:19 +00:00
2017-01-26 09:22:54 +00:00
CameraLight *cameraLight = CameraLight::Instance();
2017-02-03 08:00:46 +00:00
if (cameraLight->FixedLightLevel() >= 0)
{
2017-03-06 22:27:02 +00:00
drawerargs.SetLight(basecolormap, 0, cameraLight->FixedLightLevelShade());
plane_shade = false;
}
2017-02-03 08:00:46 +00:00
else if (cameraLight->FixedColormap())
{
2017-02-03 08:00:46 +00:00
drawerargs.SetLight(cameraLight->FixedColormap(), 0, 0);
plane_shade = false;
}
else
{
2017-02-02 10:16:18 +00:00
drawerargs.SetLight(basecolormap, 0, 0);
plane_shade = true;
2017-03-06 22:27:02 +00:00
planeshade = LightVisibility::LightLevelToShade(pl->lightlevel, foggy);
}
// Hack in support for 1 x Z and Z x 1 texture sizes
if (drawerargs.TextureHeightBits() == 0)
{
plane_sv[2] = plane_sv[1] = plane_sv[0] = 0;
}
if (drawerargs.TextureWidthBits() == 0)
{
plane_su[2] = plane_su[1] = plane_su[0] = 0;
}
RenderLines(pl);
}
void RenderSlopePlane::RenderLine(int y, int x1, int x2)
{
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);
}
}