2017-01-09 12:53:02 +00:00
|
|
|
//
|
|
|
|
// 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 <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <algorithm>
|
|
|
|
#include "p_lnspec.h"
|
|
|
|
#include "templates.h"
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "m_swap.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "w_wad.h"
|
|
|
|
#include "swrenderer/things/r_wallsprite.h"
|
|
|
|
#include "c_console.h"
|
|
|
|
#include "c_cvars.h"
|
|
|
|
#include "c_dispatch.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "v_video.h"
|
|
|
|
#include "sc_man.h"
|
|
|
|
#include "s_sound.h"
|
|
|
|
#include "sbar.h"
|
|
|
|
#include "gi.h"
|
|
|
|
#include "r_sky.h"
|
|
|
|
#include "cmdlib.h"
|
|
|
|
#include "g_level.h"
|
|
|
|
#include "d_net.h"
|
|
|
|
#include "colormatcher.h"
|
|
|
|
#include "d_netinf.h"
|
|
|
|
#include "p_effect.h"
|
2017-01-11 19:42:39 +00:00
|
|
|
#include "swrenderer/scene/r_opaque_pass.h"
|
2017-01-09 12:53:02 +00:00
|
|
|
#include "swrenderer/scene/r_3dfloors.h"
|
2017-01-11 19:42:39 +00:00
|
|
|
#include "swrenderer/scene/r_translucent_pass.h"
|
2017-01-09 12:53:02 +00:00
|
|
|
#include "swrenderer/drawers/r_draw_rgba.h"
|
|
|
|
#include "swrenderer/drawers/r_draw_pal.h"
|
|
|
|
#include "v_palette.h"
|
|
|
|
#include "r_data/r_translate.h"
|
|
|
|
#include "r_data/colormaps.h"
|
|
|
|
#include "r_data/voxels.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
#include "r_voxel.h"
|
|
|
|
#include "swrenderer/segments/r_drawsegment.h"
|
|
|
|
#include "swrenderer/scene/r_portal.h"
|
2017-01-12 15:21:46 +00:00
|
|
|
#include "swrenderer/scene/r_scene.h"
|
|
|
|
#include "swrenderer/scene/r_light.h"
|
2017-01-09 12:53:02 +00:00
|
|
|
#include "swrenderer/things/r_sprite.h"
|
2017-02-02 14:10:06 +00:00
|
|
|
#include "swrenderer/viewport/r_viewport.h"
|
2017-01-09 12:53:02 +00:00
|
|
|
#include "swrenderer/r_memory.h"
|
2017-02-03 23:25:37 +00:00
|
|
|
#include "swrenderer/r_renderthread.h"
|
2017-02-14 05:37:06 +00:00
|
|
|
#include "gl/dynlights/gl_dynlight.h"
|
2017-01-09 12:53:02 +00:00
|
|
|
|
2017-01-28 22:37:57 +00:00
|
|
|
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
|
2017-02-23 08:27:00 +00:00
|
|
|
EXTERN_CVAR(Bool, gl_light_sprites)
|
2017-01-28 22:37:57 +00:00
|
|
|
|
2017-01-09 12:53:02 +00:00
|
|
|
namespace swrenderer
|
|
|
|
{
|
2017-02-03 23:25:37 +00:00
|
|
|
void RenderSprite::Project(RenderThread *thread, AActor *thing, const DVector3 &pos, FTexture *tex, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap)
|
2017-01-11 14:02:36 +00:00
|
|
|
{
|
|
|
|
// transform the origin point
|
2017-03-12 17:54:39 +00:00
|
|
|
double tr_x = pos.X - thread->Viewport->viewpoint.Pos.X;
|
|
|
|
double tr_y = pos.Y - thread->Viewport->viewpoint.Pos.Y;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
double tz = tr_x * thread->Viewport->viewpoint.TanCos + tr_y * thread->Viewport->viewpoint.TanSin;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
|
|
|
// thing is behind view plane?
|
2017-01-11 16:59:29 +00:00
|
|
|
if (tz < MINZ)
|
2017-01-11 14:02:36 +00:00
|
|
|
return;
|
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
double tx = tr_x * thread->Viewport->viewpoint.Sin - tr_y * thread->Viewport->viewpoint.Cos;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
|
|
|
// [RH] Flip for mirrors
|
2017-02-03 23:25:37 +00:00
|
|
|
RenderPortal *renderportal = thread->Portal.get();
|
2017-01-11 14:02:36 +00:00
|
|
|
if (renderportal->MirrorFlags & RF_XFLIP)
|
|
|
|
{
|
|
|
|
tx = -tx;
|
|
|
|
}
|
|
|
|
//tx2 = tx >> 4;
|
|
|
|
|
|
|
|
// too far off the side?
|
2017-01-11 16:59:29 +00:00
|
|
|
if (fabs(tx / 64) > fabs(tz))
|
2017-01-11 14:02:36 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
// [RH] Added scaling
|
|
|
|
int scaled_to = tex->GetScaledTopOffset();
|
|
|
|
int scaled_bo = scaled_to - tex->GetScaledHeight();
|
|
|
|
double gzt = pos.Z + spriteScale.Y * scaled_to;
|
|
|
|
double gzb = pos.Z + spriteScale.Y * scaled_bo;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
|
|
|
// killough 3/27/98: exclude things totally separated
|
|
|
|
// from the viewer, by either water or fake ceilings
|
|
|
|
// killough 4/11/98: improve sprite clipping for underwater/fake ceilings
|
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
sector_t *heightsec = thing->Sector->GetHeightSec();
|
2017-01-11 14:02:36 +00:00
|
|
|
|
|
|
|
if (heightsec != nullptr) // only clip things which are in special sectors
|
|
|
|
{
|
|
|
|
if (fakeside == WaterFakeSide::AboveCeiling)
|
|
|
|
{
|
|
|
|
if (gzt < heightsec->ceilingplane.ZatPoint(pos))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (fakeside == WaterFakeSide::BelowFloor)
|
|
|
|
{
|
|
|
|
if (gzb >= heightsec->floorplane.ZatPoint(pos))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (gzt < heightsec->floorplane.ZatPoint(pos))
|
|
|
|
return;
|
|
|
|
if (!(heightsec->MoreFlags & SECF_FAKEFLOORONLY) && gzb >= heightsec->ceilingplane.ZatPoint(pos))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2017-02-01 15:02:21 +00:00
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
auto viewport = thread->Viewport.get();
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-02-01 15:02:21 +00:00
|
|
|
double xscale = viewport->CenterX / tz;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
// [RH] Reject sprites that are off the top or bottom of the screen
|
2017-03-12 17:54:39 +00:00
|
|
|
if (viewport->globaluclip * tz > viewport->viewpoint.Pos.Z - gzb || viewport->globaldclip * tz < viewport->viewpoint.Pos.Z - gzt)
|
2017-01-11 16:59:29 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
// [RH] Flip for mirrors
|
|
|
|
renderflags ^= renderportal->MirrorFlags & RF_XFLIP;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
// calculate edges of the shape
|
|
|
|
const double thingxscalemul = spriteScale.X / tex->Scale.X;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
tx -= ((renderflags & RF_XFLIP) ? (tex->GetWidth() - tex->LeftOffset - 1) : tex->LeftOffset) * thingxscalemul;
|
|
|
|
double dtx1 = tx * xscale;
|
2017-03-12 17:54:39 +00:00
|
|
|
int x1 = viewport->viewwindow.centerx + xs_RoundToInt(dtx1);
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
// off the right side?
|
|
|
|
if (x1 >= renderportal->WindowRight)
|
|
|
|
return;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
tx += tex->GetWidth() * thingxscalemul;
|
2017-03-12 17:54:39 +00:00
|
|
|
int x2 = viewport->viewwindow.centerx + xs_RoundToInt(tx * xscale);
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
// off the left side or too small?
|
|
|
|
if ((x2 < renderportal->WindowLeft || x2 <= x1))
|
|
|
|
return;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
xscale = spriteScale.X * xscale / tex->Scale.X;
|
|
|
|
fixed_t iscale = (fixed_t)(FRACUNIT / xscale); // Round towards zero to avoid wrapping in edge cases
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
double yscale = spriteScale.Y / tex->Scale.Y;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
// store information in a vissprite
|
2017-02-04 01:50:52 +00:00
|
|
|
RenderSprite *vis = thread->FrameMemory->NewObject<RenderSprite>();
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
vis->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
|
|
|
vis->xscale = FLOAT2FIXED(xscale);
|
2017-02-01 15:02:21 +00:00
|
|
|
vis->yscale = float(viewport->InvZtoScale * yscale / tz);
|
2017-01-11 16:59:29 +00:00
|
|
|
vis->idepth = float(1 / tz);
|
|
|
|
vis->floorclip = thing->Floorclip / yscale;
|
2017-03-12 17:54:39 +00:00
|
|
|
vis->texturemid = tex->TopOffset - (viewport->viewpoint.Pos.Z - pos.Z + thing->Floorclip) / yscale;
|
2017-01-11 16:59:29 +00:00
|
|
|
vis->x1 = x1 < renderportal->WindowLeft ? renderportal->WindowLeft : x1;
|
|
|
|
vis->x2 = x2 > renderportal->WindowRight ? renderportal->WindowRight : x2;
|
2017-01-16 04:26:22 +00:00
|
|
|
//vis->Angle = thing->Angles.Yaw;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
if (renderflags & RF_XFLIP)
|
|
|
|
{
|
|
|
|
vis->startfrac = (tex->GetWidth() << FRACBITS) - 1;
|
|
|
|
vis->xiscale = -iscale;
|
2017-01-11 14:02:36 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-01-11 16:59:29 +00:00
|
|
|
vis->startfrac = 0;
|
|
|
|
vis->xiscale = iscale;
|
2017-01-11 14:02:36 +00:00
|
|
|
}
|
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
vis->startfrac += (fixed_t)(vis->xiscale * (vis->x1 - viewport->viewwindow.centerx + 0.5 - dtx1));
|
2017-01-11 16:59:29 +00:00
|
|
|
|
2017-01-11 14:02:36 +00:00
|
|
|
// killough 3/27/98: save sector for special clipping later
|
|
|
|
vis->heightsec = heightsec;
|
|
|
|
vis->sector = thing->Sector;
|
|
|
|
|
|
|
|
vis->depth = (float)tz;
|
|
|
|
vis->gpos = { (float)pos.X, (float)pos.Y, (float)pos.Z };
|
|
|
|
vis->gzb = (float)gzb; // [RH] use gzb, not thing->z
|
|
|
|
vis->gzt = (float)gzt; // killough 3/27/98
|
2017-03-12 17:54:39 +00:00
|
|
|
vis->deltax = float(pos.X - viewport->viewpoint.Pos.X);
|
|
|
|
vis->deltay = float(pos.Y - viewport->viewpoint.Pos.Y);
|
2017-01-11 14:02:36 +00:00
|
|
|
vis->renderflags = renderflags;
|
|
|
|
if (thing->flags5 & MF5_BRIGHT)
|
|
|
|
vis->renderflags |= RF_FULLBRIGHT; // kg3D
|
2017-01-16 15:23:02 +00:00
|
|
|
vis->RenderStyle = thing->RenderStyle;
|
2017-01-11 14:02:36 +00:00
|
|
|
vis->FillColor = thing->fillcolor;
|
|
|
|
vis->Translation = thing->Translation; // [RH] thing translation table
|
|
|
|
vis->FakeFlatStat = fakeside;
|
2017-01-16 15:23:02 +00:00
|
|
|
vis->Alpha = float(thing->Alpha);
|
2017-01-11 14:02:36 +00:00
|
|
|
vis->fakefloor = fakefloor;
|
|
|
|
vis->fakeceiling = fakeceiling;
|
2017-01-16 04:26:22 +00:00
|
|
|
//vis->bInMirror = renderportal->MirrorFlags & RF_XFLIP;
|
|
|
|
//vis->bSplitSprite = false;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-11 16:59:29 +00:00
|
|
|
vis->pic = tex;
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-01-12 19:13:21 +00:00
|
|
|
vis->foggy = foggy;
|
|
|
|
|
2017-01-11 14:02:36 +00:00
|
|
|
// The software renderer cannot invert the source without inverting the overlay
|
|
|
|
// too. That means if the source is inverted, we need to do the reverse of what
|
|
|
|
// the invert overlay flag says to do.
|
2017-01-17 00:30:12 +00:00
|
|
|
bool invertcolormap = (vis->RenderStyle.Flags & STYLEF_InvertOverlay) != 0;
|
2017-01-16 15:23:02 +00:00
|
|
|
if (vis->RenderStyle.Flags & STYLEF_InvertSource)
|
2017-01-11 14:02:36 +00:00
|
|
|
invertcolormap = !invertcolormap;
|
|
|
|
|
2017-01-17 00:43:45 +00:00
|
|
|
if (vis->RenderStyle == LegacyRenderStyles[STYLE_Add] && basecolormap->Fade != 0)
|
2017-01-11 14:02:36 +00:00
|
|
|
{
|
2017-01-17 00:43:45 +00:00
|
|
|
basecolormap = GetSpecialLights(basecolormap->Color, 0, basecolormap->Desaturate);
|
2017-01-11 14:02:36 +00:00
|
|
|
}
|
|
|
|
|
2017-01-17 00:30:12 +00:00
|
|
|
bool fullbright = !vis->foggy && ((renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT));
|
|
|
|
bool fadeToBlack = (vis->RenderStyle.Flags & STYLEF_FadeToBlack) != 0;
|
2017-02-14 05:37:06 +00:00
|
|
|
|
2017-02-23 08:27:00 +00:00
|
|
|
if (r_dynlights && gl_light_sprites)
|
2017-02-14 05:37:06 +00:00
|
|
|
{
|
|
|
|
float lit_red = 0;
|
|
|
|
float lit_green = 0;
|
|
|
|
float lit_blue = 0;
|
|
|
|
auto node = vis->sector->lighthead;
|
|
|
|
while (node != nullptr)
|
|
|
|
{
|
|
|
|
ADynamicLight *light = node->lightsource;
|
|
|
|
if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->flags4&MF4_DONTLIGHTSELF) || light->target != thing))
|
|
|
|
{
|
2017-02-23 08:27:00 +00:00
|
|
|
float lx = (float)(light->X() - thing->X());
|
|
|
|
float ly = (float)(light->Y() - thing->Y());
|
|
|
|
float lz = (float)(light->Z() - thing->Center());
|
2017-02-14 05:37:06 +00:00
|
|
|
float LdotL = lx * lx + ly * ly + lz * lz;
|
|
|
|
float radius = node->lightsource->GetRadius();
|
2017-02-23 06:05:21 +00:00
|
|
|
if (radius * radius >= LdotL)
|
2017-02-14 05:37:06 +00:00
|
|
|
{
|
|
|
|
float distance = sqrt(LdotL);
|
2017-02-23 06:05:21 +00:00
|
|
|
float attenuation = 1.0f - distance / radius;
|
2017-02-23 05:01:01 +00:00
|
|
|
if (attenuation > 0.0f)
|
|
|
|
{
|
|
|
|
float red = light->GetRed() * (1.0f / 255.0f);
|
|
|
|
float green = light->GetGreen() * (1.0f / 255.0f);
|
|
|
|
float blue = light->GetBlue() * (1.0f / 255.0f);
|
|
|
|
/*if (light->IsSubtractive())
|
|
|
|
{
|
|
|
|
float bright = FVector3(lr, lg, lb).Length();
|
|
|
|
FVector3 lightColor(lr, lg, lb);
|
|
|
|
red = (bright - lr) * -1;
|
|
|
|
green = (bright - lg) * -1;
|
|
|
|
blue = (bright - lb) * -1;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
lit_red += red * attenuation;
|
|
|
|
lit_green += green * attenuation;
|
|
|
|
lit_blue += blue * attenuation;
|
|
|
|
}
|
2017-02-14 05:37:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
node = node->nextLight;
|
|
|
|
}
|
2017-02-23 05:01:01 +00:00
|
|
|
lit_red = clamp(lit_red * 255.0f, 0.0f, 255.0f);
|
|
|
|
lit_green = clamp(lit_green * 255.0f, 0.0f, 255.0f);
|
|
|
|
lit_blue = clamp(lit_blue * 255.0f, 0.0f, 255.0f);
|
2017-02-14 05:37:06 +00:00
|
|
|
vis->dynlightcolor = (((uint32_t)lit_red) << 16) | (((uint32_t)lit_green) << 8) | ((uint32_t)lit_blue);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vis->dynlightcolor = 0;
|
|
|
|
}
|
2017-01-11 14:02:36 +00:00
|
|
|
|
2017-03-12 19:40:00 +00:00
|
|
|
vis->Light.SetColormap(thread->Light->SpriteGlobVis(foggy) / MAX(tz, MINZ), spriteshade, basecolormap, fullbright, invertcolormap, fadeToBlack);
|
2017-01-16 02:46:05 +00:00
|
|
|
|
2017-02-03 23:25:37 +00:00
|
|
|
thread->SpriteList->Push(vis);
|
2017-01-11 14:02:36 +00:00
|
|
|
}
|
|
|
|
|
2017-02-03 23:25:37 +00:00
|
|
|
void RenderSprite::Render(RenderThread *thread, short *mfloorclip, short *mceilingclip, int, int)
|
2017-01-09 12:53:02 +00:00
|
|
|
{
|
2017-01-16 04:26:22 +00:00
|
|
|
auto vis = this;
|
|
|
|
|
2017-01-09 12:53:02 +00:00
|
|
|
fixed_t frac;
|
|
|
|
FTexture *tex;
|
|
|
|
int x2;
|
|
|
|
fixed_t xiscale;
|
|
|
|
|
|
|
|
double spryscale, sprtopscreen;
|
|
|
|
bool sprflipvert;
|
|
|
|
|
|
|
|
if (vis->xscale == 0 || fabs(vis->yscale) < (1.0f / 32000.0f))
|
|
|
|
{ // scaled to 0; can't see
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-30 10:27:58 +00:00
|
|
|
SpriteDrawerArgs drawerargs;
|
2017-02-02 10:16:18 +00:00
|
|
|
drawerargs.SetLight(vis->Light.BaseColormap, 0, vis->Light.ColormapNum << FRACBITS);
|
2017-02-14 05:37:06 +00:00
|
|
|
drawerargs.SetDynamicLight(dynlightcolor);
|
2017-01-09 12:53:02 +00:00
|
|
|
|
2017-01-24 03:15:54 +00:00
|
|
|
FDynamicColormap *basecolormap = static_cast<FDynamicColormap*>(vis->Light.BaseColormap);
|
2017-01-12 20:29:19 +00:00
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
bool visible = drawerargs.SetStyle(thread->Viewport.get(), vis->RenderStyle, vis->Alpha, vis->Translation, vis->FillColor, basecolormap, vis->Light.ColormapNum << FRACBITS);
|
2017-01-09 12:53:02 +00:00
|
|
|
|
|
|
|
if (visible)
|
|
|
|
{
|
|
|
|
tex = vis->pic;
|
|
|
|
spryscale = vis->yscale;
|
|
|
|
sprflipvert = false;
|
|
|
|
fixed_t iscale = FLOAT2FIXED(1 / vis->yscale);
|
|
|
|
frac = vis->startfrac;
|
|
|
|
xiscale = vis->xiscale;
|
2017-01-12 21:52:17 +00:00
|
|
|
double texturemid = vis->texturemid;
|
2017-01-09 12:53:02 +00:00
|
|
|
|
2017-03-12 17:54:39 +00:00
|
|
|
auto viewport = thread->Viewport.get();
|
2017-02-01 15:02:21 +00:00
|
|
|
|
2017-01-09 12:53:02 +00:00
|
|
|
if (vis->renderflags & RF_YFLIP)
|
|
|
|
{
|
|
|
|
sprflipvert = true;
|
|
|
|
spryscale = -spryscale;
|
|
|
|
iscale = -iscale;
|
2017-01-12 21:52:17 +00:00
|
|
|
texturemid -= vis->pic->GetHeight();
|
2017-02-01 15:02:21 +00:00
|
|
|
sprtopscreen = viewport->CenterY + texturemid * spryscale;
|
2017-01-09 12:53:02 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprflipvert = false;
|
2017-02-01 15:02:21 +00:00
|
|
|
sprtopscreen = viewport->CenterY - texturemid * spryscale;
|
2017-01-09 12:53:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int x = vis->x1;
|
|
|
|
x2 = vis->x2;
|
|
|
|
|
|
|
|
if (x < x2)
|
|
|
|
{
|
2017-02-03 23:25:37 +00:00
|
|
|
RenderTranslucentPass *translucentPass = thread->TranslucentPass.get();
|
2017-01-26 07:36:28 +00:00
|
|
|
|
2017-03-15 01:59:33 +00:00
|
|
|
thread->PrepareTexture(tex);
|
2017-01-09 12:53:02 +00:00
|
|
|
while (x < x2)
|
|
|
|
{
|
2017-01-26 07:36:28 +00:00
|
|
|
if (!translucentPass->ClipSpriteColumnWithPortals(x, vis))
|
2017-02-04 11:38:05 +00:00
|
|
|
drawerargs.DrawMaskedColumn(thread, x, iscale, tex, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, false);
|
2017-01-09 12:53:02 +00:00
|
|
|
x++;
|
|
|
|
frac += xiscale;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-04 18:13:56 +00:00
|
|
|
if (thread->MainThread)
|
|
|
|
NetUpdate();
|
2017-01-09 12:53:02 +00:00
|
|
|
}
|
|
|
|
}
|