Merge commit 'refs/pull/500/head' of https://github.com/coelckers/gzdoom

This commit is contained in:
Rachael Alexanderson 2018-06-03 15:21:26 -04:00
commit eb1fe23fbd
49 changed files with 1067 additions and 2762 deletions

View file

@ -310,6 +310,7 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
set( CMAKE_CXX_FLAGS "${SANITIZER_FLAG} ${CMAKE_CXX_FLAGS}" )
set( CMAKE_C_FLAGS "${SANITIZER_FLAG} ${CMAKE_C_FLAGS}" )
set( CMAKE_EXE_LINKER_FLAGS "${SANITIZER_FLAG} ${CMAKE_EXE_LINKER_FLAGS}" )
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.5")
set( CMAKE_C_FLAGS "-Wno-unused-result ${CMAKE_C_FLAGS}" )

View file

@ -401,6 +401,7 @@ enum ActorFlag8
{
MF8_FRIGHTENING = 0x00000001, // for those moments when halloween just won't do
MF8_INSCROLLSEC = 0x00000002, // actor is partially inside a scrolling sector
MF8_BLOCKASPLAYER = 0x00000004, // actor is blocked by player-blocking lines even if not a player
};
// --- mobj.renderflags ---

View file

@ -64,6 +64,7 @@
#include "v_text.h"
#include "backend/vmbuilder.h"
#include "types.h"
#include "m_argv.h"
// [SO] Just the way Randy said to do it :)
// [RH] Made this CVAR_SERVERINFO
@ -813,6 +814,16 @@ void SetDehParams(FState *state, int codepointer)
sfunc->ImplicitArgs = numargs;
state->SetAction(sfunc);
sfunc->PrintableName.Format("Dehacked.%s.%d.%d", MBFCodePointers[codepointer].name.GetChars(), value1, value2);
if (Args->CheckParm("-dumpdisasm"))
{
FILE *dump = fopen("disasm.txt", "a");
if (dump != nullptr)
{
DumpFunction(dump, sfunc, sfunc->PrintableName.GetChars(), (int)sfunc->PrintableName.Len());
}
fclose(dump);
}
}
}
@ -2103,12 +2114,15 @@ static int PatchCodePtrs (int dummy)
symname.Format("A_%s", Line2);
// Let's consider as aliases some redundant MBF pointer
bool ismbfcp = false;
for (unsigned int i = 0; i < MBFCodePointers.Size(); i++)
{
if (!symname.CompareNoCase(MBFCodePointers[i].alias))
{
symname = MBFCodePointers[i].name;
DPrintf(DMSG_SPAMMY, "%s --> %s\n", MBFCodePointers[i].alias, MBFCodePointers[i].name.GetChars());
ismbfcp = true;
break;
}
}
@ -2119,7 +2133,7 @@ static int PatchCodePtrs (int dummy)
{
Printf(TEXTCOLOR_RED "Frame %d: Unknown code pointer '%s'\n", frame, Line2);
}
else
else if (!ismbfcp) // MBF special code pointers will produce errors here because they will receive some args and won't match the conditions here.
{
TArray<uint32_t> &args = sym->Variants[0].ArgFlags;
unsigned numargs = sym->GetImplicitArgs();

View file

@ -82,9 +82,6 @@
static FRandom pr_dmspawn ("DMSpawn");
static FRandom pr_pspawn ("PlayerSpawn");
const int SAVEPICWIDTH = 216;
const int SAVEPICHEIGHT = 162;
bool G_CheckDemoStatus (void);
void G_ReadDemoTiccmd (ticcmd_t *cmd, int player);
void G_WriteDemoTiccmd (ticcmd_t *cmd, int player, int buf);

View file

@ -102,5 +102,7 @@ class AInventory;
extern const AInventory *SendItemUse, *SendItemDrop;
extern int SendItemDropAmount;
const int SAVEPICWIDTH = 216;
const int SAVEPICHEIGHT = 162;
#endif

View file

@ -54,7 +54,7 @@ VSMatrix FGLModelRenderer::GetViewToWorldMatrix()
return objectToWorldMatrix;
}
void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix)
void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored)
{
glDepthFunc(GL_LEQUAL);
gl_RenderState.EnableTexture(true);
@ -65,7 +65,7 @@ void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, con
if (!(actor->RenderStyle == LegacyRenderStyles[STYLE_Normal]) && !(smf->flags & MDL_DONTCULLBACKFACES))
{
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
glFrontFace((mirrored ^ GLPortal::isMirrored()) ? GL_CCW : GL_CW);
}
gl_RenderState.mModelMatrix = objectToWorldMatrix;
@ -81,7 +81,7 @@ void FGLModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
glDisable(GL_CULL_FACE);
}
void FGLModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix)
void FGLModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored)
{
glDepthFunc(GL_LEQUAL);
@ -91,7 +91,7 @@ void FGLModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectTo
if (!(actor->RenderStyle == LegacyRenderStyles[STYLE_Normal]))
{
glEnable(GL_CULL_FACE);
glFrontFace(GLPortal::isMirrored()? GL_CW : GL_CCW);
glFrontFace((mirrored ^ GLPortal::isMirrored()) ? GL_CW : GL_CCW);
}
gl_RenderState.mModelMatrix = objectToWorldMatrix;

View file

@ -37,13 +37,13 @@ public:
FGLModelRenderer(int mli) : modellightindex(mli)
{}
ModelRendererType GetType() const override { return GLModelRendererType; }
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;
void SetVertexBuffer(IModelVertexBuffer *buffer) override;
void ResetVertexBuffer() override;
VSMatrix GetViewToWorldMatrix() override;
void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) override;
void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored) override;
void EndDrawHUDModel(AActor *actor) override;
void SetInterpolation(double interpolation) override;
void SetMaterial(FTexture *skin, bool clampNoFilter, int translation) override;

View file

@ -35,6 +35,7 @@
#include "p_effect.h"
#include "d_player.h"
#include "a_dynlight.h"
#include "g_game.h"
#include "swrenderer/r_swscene.h"
#include "hwrenderer/utility/hw_clock.h"
@ -96,6 +97,8 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mLights = nullptr;
mTonemapPalette = nullptr;
mBuffers = nullptr;
mScreenBuffers = nullptr;
mSaveBuffers = nullptr;
mPresentShader = nullptr;
mPresent3dCheckerShader = nullptr;
mPresent3dColumnShader = nullptr;
@ -122,7 +125,9 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
void FGLRenderer::Initialize(int width, int height)
{
mBuffers = new FGLRenderBuffers();
mScreenBuffers = new FGLRenderBuffers();
mSaveBuffers = new FGLRenderBuffers();
mBuffers = mScreenBuffers;
mLinearDepthShader = new FLinearDepthShader();
mDepthBlurShader = new FDepthBlurShader();
mSSAOShader = new FSSAOShader();
@ -400,7 +405,9 @@ void FGLRenderer::WriteSavePic(player_t *player, FileWriter *file, int width, in
void FGLRenderer::BeginFrame()
{
buffersActive = GLRenderer->mBuffers->Setup(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height);
buffersActive = GLRenderer->mScreenBuffers->Setup(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height);
if (buffersActive)
buffersActive = GLRenderer->mSaveBuffers->Setup(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT);
}
//===========================================================================

View file

@ -100,6 +100,8 @@ public:
int mOldFBID;
FGLRenderBuffers *mBuffers;
FGLRenderBuffers *mScreenBuffers;
FGLRenderBuffers *mSaveBuffers;
FLinearDepthShader *mLinearDepthShader;
FSSAOShader *mSSAOShader;
FDepthBlurShader *mDepthBlurShader;

View file

@ -395,7 +395,6 @@ void GLSceneDrawer::RenderTranslucent(FDrawInfo *di)
{
RenderAll.Clock();
glDepthMask(false);
gl_RenderState.SetCameraPos(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z);
// final pass: translucent stuff
@ -404,6 +403,7 @@ void GLSceneDrawer::RenderTranslucent(FDrawInfo *di)
gl_RenderState.EnableBrightmap(true);
di->drawlists[GLDL_TRANSLUCENTBORDER].Draw(di, GLPASS_TRANSLUCENT);
glDepthMask(false);
di->DrawSorted(GLDL_TRANSLUCENT);
gl_RenderState.EnableBrightmap(false);
@ -656,7 +656,7 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, IntRect * bounds, fl
SetFixedColormap(camera->player); // reiterate color map for each eye, so night vision goggles work in both eyes
const s3d::EyePose * eye = stereo3dMode.getEyePose(eye_ix);
eye->SetUp();
screen->SetOutputViewport(bounds);
screen->SetViewportRects(bounds);
Set3DViewport(mainview);
GLRenderer->mDrawingScene2D = true;
GLRenderer->mCurrentFoV = fov;
@ -713,20 +713,24 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, IntRect * bounds, fl
void GLSceneDrawer::WriteSavePic (player_t *player, FileWriter *file, int width, int height)
{
IntRect bounds;
bounds.left = 0;
bounds.top = 0;
bounds.width = width;
bounds.height = height;
// if GLRenderer->mVBO is persistently mapped we must be sure the GPU finished reading from it before we fill it with new data.
glFinish();
// Switch to render buffers dimensioned for the savepic
GLRenderer->mBuffers = GLRenderer->mSaveBuffers;
P_FindParticleSubsectors(); // make sure that all recently spawned particles have a valid subsector.
bounds.left=0;
bounds.top=0;
bounds.width=width;
bounds.height=height;
glFlush();
SetFixedColormap(player);
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
GLRenderer->mVBO->Reset();
if (!gl.legacyMode) GLRenderer->mLights->Clear();
sector_t *viewsector = RenderViewpoint(players[consoleplayer].camera, &bounds,
r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false);
sector_t *viewsector = RenderViewpoint(players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false);
glDisable(GL_STENCIL_TEST);
gl_RenderState.SetFixedColormap(CM_DEFAULT);
gl_RenderState.SetSoftLightLevel(-1);
@ -737,12 +741,16 @@ void GLSceneDrawer::WriteSavePic (player_t *player, FileWriter *file, int width,
screen->Draw2D();
}
GLRenderer->CopyToBackbuffer(&bounds, false);
glFlush();
screen->SetOutputViewport(nullptr);
// strictly speaking not needed as the glReadPixels should block until the scene is rendered, but this is to safeguard against shitty drivers
glFinish();
uint8_t * scr = (uint8_t *)M_Malloc(width * height * 3);
glReadPixels(0,0,width, height,GL_RGB,GL_UNSIGNED_BYTE,scr);
M_CreatePNG (file, scr + ((height-1) * width * 3), NULL, SS_RGB, width, height, -width * 3, Gamma);
M_Free(scr);
// Switch back the screen render buffers
screen->SetViewportRects(nullptr);
GLRenderer->mBuffers = GLRenderer->mScreenBuffers;
}

View file

@ -136,7 +136,7 @@ void OpenGLFrameBuffer::InitializeState()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLRenderer->Initialize(GetWidth(), GetHeight());
SetOutputViewport(nullptr);
SetViewportRects(nullptr);
}
//==========================================================================
@ -164,14 +164,11 @@ void OpenGLFrameBuffer::Update()
int clientHeight = ViewportScaledHeight(initialWidth, initialHeight);
if (clientWidth > 0 && clientHeight > 0 && (Width != clientWidth || Height != clientHeight))
{
// Do not call Resize here because it's only for software canvases
Width = clientWidth;
Height = clientHeight;
V_OutputResized(Width, Height);
GLRenderer->mVBO->OutputResized(Width, Height);
}
SetOutputViewport(nullptr);
}
//===========================================================================
@ -392,10 +389,11 @@ bool OpenGLFrameBuffer::RenderBuffersEnabled()
return FGLRenderBuffers::IsEnabled();
}
void OpenGLFrameBuffer::SetOutputViewport(IntRect *bounds)
void OpenGLFrameBuffer::SetViewportRects(IntRect *bounds)
{
Super::SetOutputViewport(bounds);
s3d::Stereo3DMode::getCurrentMode().AdjustViewports();
Super::SetViewportRects(bounds);
if (!bounds)
s3d::Stereo3DMode::getCurrentMode().AdjustViewports();
}
@ -431,6 +429,7 @@ void OpenGLFrameBuffer::SetClearColor(int color)
void OpenGLFrameBuffer::BeginFrame()
{
SetViewportRects(nullptr);
if (GLRenderer != nullptr)
GLRenderer->BeginFrame();
}

View file

@ -42,7 +42,7 @@ public:
void ResetFixedColormap() override;
void BeginFrame() override;
bool RenderBuffersEnabled() override;
void SetOutputViewport(IntRect *bounds) override;
void SetViewportRects(IntRect *bounds) override;
void BlurScene(float amount) override;
// Retrieves a buffer containing image data for a screenshot.

View file

@ -55,13 +55,14 @@ struct FMemArena::Block
//
// RoundPointer
//
// Rounds a pointer up to a pointer-sized boundary.
// Rounds a pointer up to the size of the largest integral type.
//
//==========================================================================
static inline void *RoundPointer(void *ptr)
{
return (void *)(((size_t)ptr + sizeof(void*) - 1) & ~(sizeof(void*) - 1));
const auto roundsize = std::max(sizeof(void*), sizeof(double));
return (void *)(((size_t)ptr + roundsize - 1) & ~(roundsize - 1));
}
//==========================================================================

View file

@ -1997,7 +1997,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CustomPunch)
angle = self->Angles.Yaw + pr_cwpunch.Random2() * (5.625 / 256);
if (range == 0) range = DEFMELEERANGE;
pitch = P_AimLineAttack (self, angle, range, &t);
pitch = P_AimLineAttack (self, angle, range, &t, 0., ALF_CHECK3D);
// only use ammo when actually hitting something!
if ((flags & CPF_USEAMMO) && t.linetarget && weapon && ACTION_CALL_FROM_PSPRITE())

View file

@ -930,7 +930,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST)
|| ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY)));
if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE)))
if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE | ML_BLOCK_PLAYERS)))
{
if (ld->flags & ML_RAILING)
{
@ -938,7 +938,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
}
else if ((ld->flags & (ML_BLOCKING | ML_BLOCKEVERYTHING)) || // explicitly blocking everything
(!(NotBlocked) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
(tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
((tm.thing->player != NULL) || (tm.thing->flags8 & MF8_BLOCKASPLAYER) && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
((tm.thing->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))) // block floaters
{
@ -3100,7 +3100,7 @@ void FSlide::SlideTraverse(const DVector2 &start, const DVector2 &end)
{
goto isblocking;
}
if (li->flags & ML_BLOCK_PLAYERS && slidemo->player != NULL)
if (li->flags & ML_BLOCK_PLAYERS && ((slidemo->player != NULL) || (slidemo->flags8 & MF8_BLOCKASPLAYER)))
{
goto isblocking;
}
@ -3998,6 +3998,70 @@ struct aim_t
SetResult(thing_other, newtrace.thing_other);
}
//============================================================================
//
// Finds where the trace exits an actor to check for hits from above/below
//
//============================================================================
double ExitPoint(AActor *thing)
{
// The added check at the exit point only has some value if a 3D distance check is involved
if (!(flags & ALF_CHECK3D)) return -1;
divline_t trace = { startpos.X, startpos.Y, aimtrace.X, aimtrace.Y };
divline_t line;
for (int i = 0; i < 4; ++i)
{
switch (i)
{
case 0: // Top edge
line.y = thing->Y() + thing->radius;
if (trace.y > line.y) continue;
line.x = thing->X() + thing->radius;
line.dx = -thing->radius * 2;
line.dy = 0;
break;
case 1: // Right edge
line.x = thing->X() + thing->radius;
if (trace.x > line.x) continue;
line.y = thing->Y() - thing->radius;
line.dx = 0;
line.dy = thing->radius * 2;
break;
case 2: // Bottom edge
line.y = thing->Y() - thing->radius;
if (trace.y < line.y) continue;
line.x = thing->X() - thing->radius;
line.dx = thing->radius * 2;
line.dy = 0;
break;
case 3: // Left edge
line.x = thing->X() - thing->radius;
if (trace.x < line.x) continue;
line.y = thing->Y() + thing->radius;
line.dx = 0;
line.dy = thing->radius * -2;
break;
}
// If it is, see if the trace crosses it
if (P_PointOnDivlineSide(line.x, line.y, &trace) !=
P_PointOnDivlineSide(line.x + line.dx, line.y + line.dy, &trace))
{
// It's a hit
double frac = P_InterceptVector(&trace, &line);
if (frac > 1.) frac = 1.;
return frac;
}
}
return -1.;
}
//============================================================================
//
@ -4047,9 +4111,7 @@ struct aim_t
intercept_t *in;
if (aimdebug)
Printf("Start AimTraverse, start = %f,%f,%f, vect = %f,%f\n",
startpos.X / 65536., startpos.Y / 65536., startpos.Z / 65536.,
aimtrace.X / 65536., aimtrace.Y / 65536.);
Printf("Start AimTraverse, start = %f,%f,%f, vect = %f,%f\n", startpos.X, startpos.Y, startpos.Z, aimtrace.X, aimtrace.Y);
while ((in = it.Next()))
{
@ -4195,12 +4257,38 @@ struct aim_t
thingtoppitch = -VecToAngle(dist, th->Top() - shootz);
if (thingtoppitch > bottompitch)
continue; // shot over the thing
{
// Check for a hit from above
if (shootz > th->Top())
{
double exitfrac = ExitPoint(th);
if (exitfrac > 0.)
{
double exitdist = attackrange * exitfrac;
thingtoppitch = -VecToAngle(exitdist, th->Top() - shootz);
if (thingtoppitch > bottompitch) continue;
}
}
else continue; // shot over the thing
}
thingbottompitch = -VecToAngle(dist, th->Z() - shootz);
if (thingbottompitch < toppitch)
{
// Check for a hit from below
if (shootz < th->Z())
{
double exitfrac = ExitPoint(th);
if (exitfrac > 0.)
{
double exitdist = attackrange * exitfrac;
thingbottompitch = -VecToAngle(exitdist, th->Z() - shootz);
if (thingbottompitch < toppitch) continue;
}
}
continue; // shot under the thing
}
if (crossedffloors)
{

View file

@ -6504,9 +6504,6 @@ DEFINE_ACTION_FUNCTION(AActor, GetFloorTerrain)
bool P_HitWater (AActor * thing, sector_t * sec, const DVector3 &pos, bool checkabove, bool alert, bool force)
{
if (thing->flags3 & MF3_DONTSPLASH)
return false;
if (thing->player && (thing->player->cheats & CF_PREDICTING))
return false;
@ -6595,48 +6592,51 @@ foundone:
if (thing->Mass < 10)
smallsplash = true;
if (smallsplash && splash->SmallSplash)
if (!(thing->flags3 & MF3_DONTSPLASH))
{
mo = Spawn (splash->SmallSplash, pos, ALLOW_REPLACE);
if (mo) mo->Floorclip += splash->SmallSplashClip;
}
else
{
if (splash->SplashChunk)
if (smallsplash && splash->SmallSplash)
{
mo = Spawn (splash->SplashChunk, pos, ALLOW_REPLACE);
mo->target = thing;
if (splash->ChunkXVelShift != 255)
mo = Spawn(splash->SmallSplash, pos, ALLOW_REPLACE);
if (mo) mo->Floorclip += splash->SmallSplashClip;
}
else
{
if (splash->SplashChunk)
{
mo->Vel.X = (pr_chunk.Random2() << splash->ChunkXVelShift) / 65536.;
mo = Spawn(splash->SplashChunk, pos, ALLOW_REPLACE);
mo->target = thing;
if (splash->ChunkXVelShift != 255)
{
mo->Vel.X = (pr_chunk.Random2() << splash->ChunkXVelShift) / 65536.;
}
if (splash->ChunkYVelShift != 255)
{
mo->Vel.Y = (pr_chunk.Random2() << splash->ChunkYVelShift) / 65536.;
}
mo->Vel.Z = splash->ChunkBaseZVel + (pr_chunk() << splash->ChunkZVelShift) / 65536.;
}
if (splash->ChunkYVelShift != 255)
if (splash->SplashBase)
{
mo->Vel.Y = (pr_chunk.Random2() << splash->ChunkYVelShift) / 65536.;
mo = Spawn(splash->SplashBase, pos, ALLOW_REPLACE);
}
if (thing->player && !splash->NoAlert && alert)
{
P_NoiseAlert(thing, thing, true);
}
mo->Vel.Z = splash->ChunkBaseZVel + (pr_chunk() << splash->ChunkZVelShift) / 65536.;
}
if (splash->SplashBase)
if (mo)
{
mo = Spawn (splash->SplashBase, pos, ALLOW_REPLACE);
S_Sound(mo, CHAN_ITEM, smallsplash ?
splash->SmallSplashSound : splash->NormalSplashSound,
1, ATTN_IDLE);
}
if (thing->player && !splash->NoAlert && alert)
else
{
P_NoiseAlert (thing, thing, true);
S_Sound(pos, CHAN_ITEM, smallsplash ?
splash->SmallSplashSound : splash->NormalSplashSound,
1, ATTN_IDLE);
}
}
if (mo)
{
S_Sound (mo, CHAN_ITEM, smallsplash ?
splash->SmallSplashSound : splash->NormalSplashSound,
1, ATTN_IDLE);
}
else
{
S_Sound (pos, CHAN_ITEM, smallsplash ?
splash->SmallSplashSound : splash->NormalSplashSound,
1, ATTN_IDLE);
}
// Don't let deep water eat missiles
return plane == &sec->floorplane ? Terrains[terrainnum].IsLiquid : false;
@ -6676,9 +6676,6 @@ bool P_HitFloor (AActor *thing)
return false;
}
if (thing->flags3 & MF3_DONTSPLASH)
return false;
// don't splash if landing on the edge above water/lava/etc....
DVector3 pos;
for (m = thing->touching_sectorlist; m; m = m->m_tnext)

View file

@ -1157,7 +1157,7 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd)
// [TN] Check wether this actor gets blocked by the line.
if (ld->backsector != NULL &&
!(ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING))
&& !(ld->flags & ML_BLOCK_PLAYERS && mobj->player)
&& !(ld->flags & ML_BLOCK_PLAYERS && (mobj->player || (mobj->flags8 & MF8_BLOCKASPLAYER)))
&& !(ld->flags & ML_BLOCKMONSTERS && mobj->flags3 & MF3_ISMONSTER)
&& !((mobj->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))
&& (!(ld->flags & ML_3DMIDTEX) ||

View file

@ -48,8 +48,7 @@ void PolyZBuffer::Resize(int newwidth, int newheight)
{
width = newwidth;
height = newheight;
int count = BlockWidth() * BlockHeight();
values.resize(count * 64);
values.resize(width * height);
}
/////////////////////////////////////////////////////////////////////////////
@ -64,14 +63,6 @@ void PolyStencilBuffer::Clear(int newwidth, int newheight, uint8_t stencil_value
{
width = newwidth;
height = newheight;
int count = BlockWidth() * BlockHeight();
values.resize(count * 64);
masks.resize(count);
uint8_t *v = Values();
uint32_t *m = Masks();
for (int i = 0; i < count; i++)
{
m[i] = 0xffffff00 | stencil_value;
}
values.resize(width * height);
memset(Values(), stencil_value, width * height);
}

View file

@ -33,8 +33,6 @@ public:
void Resize(int newwidth, int newheight);
int Width() const { return width; }
int Height() const { return height; }
int BlockWidth() const { return (width + 7) / 8; }
int BlockHeight() const { return (height + 7) / 8; }
float *Values() { return values.data(); }
private:
@ -50,16 +48,10 @@ public:
void Clear(int newwidth, int newheight, uint8_t stencil_value = 0);
int Width() const { return width; }
int Height() const { return height; }
int BlockWidth() const { return (width + 7) / 8; }
int BlockHeight() const { return (height + 7) / 8; }
uint8_t *Values() { return values.data(); }
uint32_t *Masks() { return masks.data(); }
private:
int width;
int height;
// 8x8 blocks of stencil values, plus a mask for each block indicating if values are the same for early out stencil testing
std::vector<uint8_t> values;
std::vector<uint32_t> masks;
};

View file

@ -226,6 +226,7 @@ void RectDrawArgs::SetTexture(FTexture *texture, FRenderStyle style)
void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style)
{
// Alphatexture overrides translations.
if (translationID != 0xffffffff && translationID != 0 && !(style.Flags & STYLEF_RedIsAlpha))
{
FRemapTable *table = TranslationToTable(translationID);
@ -299,61 +300,63 @@ void RectDrawArgs::Draw(PolyRenderThread *thread, double x0, double x1, double y
thread->DrawQueue->Push<DrawRectCommand>(*this);
}
void RectDrawArgs::SetStyle(FRenderStyle renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright)
void RectDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright)
{
SetTexture(tex, translationID, renderstyle);
SetColor(0xff000000 | fillcolor, fillcolor >> 24);
if (renderstyle == LegacyRenderStyles[STYLE_Normal] || (r_drawfuzz == 0 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy]))
{
SetStyle(Translation() ? RectBlendMode::TranslatedAdd : RectBlendMode::TextureAdd, 1.0, 0.0);
SetStyle(Translation() ? TriBlendMode::NormalTranslated : TriBlendMode::Normal, alpha);
}
else if (renderstyle == LegacyRenderStyles[STYLE_Add] && fullbright && alpha == 1.0 && !Translation())
{
SetStyle(RectBlendMode::TextureAddSrcColor, 1.0, 1.0);
}
else if (renderstyle == LegacyRenderStyles[STYLE_Add])
{
SetStyle(Translation() ? RectBlendMode::TranslatedAdd : RectBlendMode::TextureAdd, alpha, 1.0);
}
else if (renderstyle == LegacyRenderStyles[STYLE_Subtract])
{
SetStyle(Translation() ? RectBlendMode::TranslatedRevSub : RectBlendMode::TextureRevSub, alpha, 1.0);
SetStyle(TriBlendMode::SrcColor, alpha);
}
else if (renderstyle == LegacyRenderStyles[STYLE_SoulTrans])
{
SetStyle(Translation() ? RectBlendMode::TranslatedAdd : RectBlendMode::TextureAdd, transsouls, 1.0 - transsouls);
SetStyle(Translation() ? TriBlendMode::AddTranslated : TriBlendMode::Add, transsouls);
}
else if (renderstyle == LegacyRenderStyles[STYLE_Fuzzy] || (r_drawfuzz == 1 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy]))
{
SetColor(0xff000000, 0);
SetStyle(RectBlendMode::Fuzz);
SetStyle(TriBlendMode::Fuzzy);
}
else if (renderstyle == LegacyRenderStyles[STYLE_Shadow] || (r_drawfuzz == 2 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy]))
{
SetStyle(Translation() ? RectBlendMode::TranslatedAdd : RectBlendMode::TextureAdd, 0.0, 160 / 255.0);
SetColor(0xff000000, 0);
SetStyle(Translation() ? TriBlendMode::TranslucentStencilTranslated : TriBlendMode::TranslucentStencil, 1.0 - 160 / 255.0);
}
else if (renderstyle == LegacyRenderStyles[STYLE_TranslucentStencil])
else if (renderstyle == LegacyRenderStyles[STYLE_Stencil])
{
SetColor(0xff000000 | fillcolor, fillcolor >> 24);
SetStyle(RectBlendMode::Stencil, alpha, 1.0 - alpha);
SetStyle(Translation() ? TriBlendMode::StencilTranslated : TriBlendMode::Stencil, alpha);
}
else if (renderstyle == LegacyRenderStyles[STYLE_AddStencil])
else if (renderstyle == LegacyRenderStyles[STYLE_Translucent])
{
SetColor(0xff000000 | fillcolor, fillcolor >> 24);
SetStyle(RectBlendMode::AddStencil, alpha, 1.0);
SetStyle(Translation() ? TriBlendMode::TranslucentTranslated : TriBlendMode::Translucent, alpha);
}
else if (renderstyle == LegacyRenderStyles[STYLE_Add])
{
SetStyle(Translation() ? TriBlendMode::AddTranslated : TriBlendMode::Add, alpha);
}
else if (renderstyle == LegacyRenderStyles[STYLE_Shaded])
{
SetColor(0xff000000 | fillcolor, fillcolor >> 24);
SetStyle(RectBlendMode::Shaded, alpha, 1.0 - alpha);
SetStyle(Translation() ? TriBlendMode::ShadedTranslated : TriBlendMode::Shaded, alpha);
}
else if (renderstyle == LegacyRenderStyles[STYLE_TranslucentStencil])
{
SetStyle(Translation() ? TriBlendMode::TranslucentStencilTranslated : TriBlendMode::TranslucentStencil, alpha);
}
else if (renderstyle == LegacyRenderStyles[STYLE_Subtract])
{
SetStyle(Translation() ? TriBlendMode::SubtractTranslated : TriBlendMode::Subtract, alpha);
}
else if (renderstyle == LegacyRenderStyles[STYLE_AddStencil])
{
SetStyle(Translation() ? TriBlendMode::AddStencilTranslated : TriBlendMode::AddStencil, alpha);
}
else if (renderstyle == LegacyRenderStyles[STYLE_AddShaded])
{
SetColor(0xff000000 | fillcolor, fillcolor >> 24);
SetStyle(RectBlendMode::AddShaded, alpha, 1.0);
}
else
{
SetStyle(Translation() ? RectBlendMode::TranslatedAdd : RectBlendMode::TextureAdd, alpha, 1.0 - alpha);
SetStyle(Translation() ? TriBlendMode::AddShadedTranslated : TriBlendMode::AddShaded, alpha);
}
}

View file

@ -180,8 +180,8 @@ public:
void SetTexture(FTexture *texture, FRenderStyle style);
void SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style);
void SetLight(FSWColormap *basecolormap, uint32_t lightlevel);
void SetStyle(RectBlendMode blendmode, double srcalpha = 1.0, double destalpha = 1.0) { mBlendMode = blendmode; mSrcAlpha = (uint32_t)(srcalpha * 256.0 + 0.5); mDestAlpha = (uint32_t)(destalpha * 256.0 + 0.5); }
void SetStyle(FRenderStyle renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright);
void SetStyle(TriBlendMode blendmode, double alpha = 1.0) { mBlendMode = blendmode; mAlpha = (uint32_t)(alpha * 256.0 + 0.5); }
void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright);
void SetColor(uint32_t bgra, uint8_t palindex);
void Draw(PolyRenderThread *thread, double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1);
@ -191,10 +191,9 @@ public:
int TextureHeight() const { return mTextureHeight; }
const uint8_t *Translation() const { return mTranslation; }
RectBlendMode BlendMode() const { return mBlendMode; }
TriBlendMode BlendMode() const { return mBlendMode; }
uint32_t Color() const { return mColor; }
uint32_t SrcAlpha() const { return mSrcAlpha; }
uint32_t DestAlpha() const { return mDestAlpha; }
uint32_t Alpha() const { return mAlpha; }
uint32_t Light() const { return mLight; }
const uint8_t *BaseColormap() const { return mColormaps; }
@ -225,11 +224,10 @@ private:
int mTextureHeight = 0;
const uint8_t *mTranslation = nullptr;
const uint8_t *mColormaps = nullptr;
RectBlendMode mBlendMode = RectBlendMode::FillOpaque;
TriBlendMode mBlendMode = TriBlendMode::Fill;
uint32_t mLight = 0;
uint32_t mColor = 0;
uint32_t mSrcAlpha = 0;
uint32_t mDestAlpha = 0;
uint32_t mAlpha = 0;
uint16_t mLightAlpha = 0;
uint16_t mLightRed = 0;
uint16_t mLightGreen = 0;

View file

@ -1,476 +0,0 @@
/*
** Polygon Doom software renderer
** 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.
**
*/
#pragma once
#include "screen_triangle.h"
namespace TriScreenDrawerModes
{
namespace
{
struct BgraColor
{
uint32_t b, g, r, a;
BgraColor() { }
BgraColor(uint32_t c) : b(BPART(c)), g(GPART(c)), r(RPART(c)), a(APART(c)) { }
BgraColor &operator=(uint32_t c) { b = BPART(c); g = GPART(c); r = RPART(c); a = APART(c); return *this; }
operator uint32_t() const { return MAKEARGB(a, r, g, b); }
};
}
template<typename SamplerT, typename FilterModeT>
FORCEINLINE unsigned int Sample32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, uint32_t oneU, uint32_t oneV, uint32_t color, const uint32_t *translation)
{
uint32_t texel;
if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill || SamplerT::Mode == (int)Samplers::Fuzz || SamplerT::Mode == (int)Samplers::FogBoundary)
{
return color;
}
else if (SamplerT::Mode == (int)Samplers::Translated)
{
const uint8_t *texpal = (const uint8_t *)texPixels;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
return translation[texpal[texelX * texHeight + texelY]];
}
else if (FilterModeT::Mode == (int)FilterModes::Nearest)
{
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
texel = texPixels[texelX * texHeight + texelY];
}
else
{
u -= oneU >> 1;
v -= oneV >> 1;
unsigned int frac_x0 = (((uint32_t)u << 8) >> FRACBITS) * texWidth;
unsigned int frac_x1 = ((((uint32_t)u << 8) + oneU) >> FRACBITS) * texWidth;
unsigned int frac_y0 = (((uint32_t)v << 8) >> FRACBITS) * texHeight;
unsigned int frac_y1 = ((((uint32_t)v << 8) + oneV) >> FRACBITS) * texHeight;
unsigned int x0 = frac_x0 >> FRACBITS;
unsigned int x1 = frac_x1 >> FRACBITS;
unsigned int y0 = frac_y0 >> FRACBITS;
unsigned int y1 = frac_y1 >> FRACBITS;
unsigned int p00 = texPixels[x0 * texHeight + y0];
unsigned int p01 = texPixels[x0 * texHeight + y1];
unsigned int p10 = texPixels[x1 * texHeight + y0];
unsigned int p11 = texPixels[x1 * texHeight + y1];
unsigned int inv_a = (frac_x1 >> (FRACBITS - 4)) & 15;
unsigned int inv_b = (frac_y1 >> (FRACBITS - 4)) & 15;
unsigned int a = 16 - inv_a;
unsigned int b = 16 - inv_b;
unsigned int sred = (RPART(p00) * (a * b) + RPART(p01) * (inv_a * b) + RPART(p10) * (a * inv_b) + RPART(p11) * (inv_a * inv_b) + 127) >> 8;
unsigned int sgreen = (GPART(p00) * (a * b) + GPART(p01) * (inv_a * b) + GPART(p10) * (a * inv_b) + GPART(p11) * (inv_a * inv_b) + 127) >> 8;
unsigned int sblue = (BPART(p00) * (a * b) + BPART(p01) * (inv_a * b) + BPART(p10) * (a * inv_b) + BPART(p11) * (inv_a * inv_b) + 127) >> 8;
unsigned int salpha = (APART(p00) * (a * b) + APART(p01) * (inv_a * b) + APART(p10) * (a * inv_b) + APART(p11) * (inv_a * inv_b) + 127) >> 8;
texel = (salpha << 24) | (sred << 16) | (sgreen << 8) | sblue;
}
if (SamplerT::Mode == (int)Samplers::Skycap)
{
int start_fade = 2; // How fast it should fade out
int alpha_top = clamp(v >> (16 - start_fade), 0, 256);
int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256);
int a = MIN(alpha_top, alpha_bottom);
int inv_a = 256 - a;
uint32_t r = RPART(texel);
uint32_t g = GPART(texel);
uint32_t b = BPART(texel);
uint32_t fg_a = APART(texel);
uint32_t bg_red = RPART(color);
uint32_t bg_green = GPART(color);
uint32_t bg_blue = BPART(color);
r = (r * a + bg_red * inv_a + 127) >> 8;
g = (g * a + bg_green * inv_a + 127) >> 8;
b = (b * a + bg_blue * inv_a + 127) >> 8;
return MAKEARGB(fg_a, r, g, b);
}
else
{
return texel;
}
}
template<typename SamplerT>
FORCEINLINE unsigned int SampleShade32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, int x, int y)
{
if (SamplerT::Mode == (int)Samplers::Shaded)
{
const uint8_t *texpal = (const uint8_t *)texPixels;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = texpal[texelX * texHeight + texelY];
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
return sampleshadeout;
}
else if (SamplerT::Mode == (int)Samplers::Stencil)
{
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]);
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
return sampleshadeout;
}
else if (SamplerT::Mode == (int)Samplers::Fuzz)
{
using namespace swrenderer;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]);
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
fixed_t fuzzscale = (200 << FRACBITS) / viewheight;
int scaled_x = (x * fuzzscale) >> FRACBITS;
int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + fuzzpos;
fixed_t fuzzcount = FUZZTABLE << FRACBITS;
fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount;
unsigned int alpha = fuzzoffset[fuzz >> FRACBITS];
sampleshadeout = (sampleshadeout * alpha) >> 5;
return sampleshadeout;
}
else
{
return 0;
}
}
FORCEINLINE BgraColor VECTORCALL AddLights(BgraColor material, BgraColor fgcolor, BgraColor dynlight)
{
fgcolor.r = MIN(fgcolor.r + ((material.r * dynlight.r) >> 8), (uint32_t)255);
fgcolor.g = MIN(fgcolor.g + ((material.g * dynlight.g) >> 8), (uint32_t)255);
fgcolor.b = MIN(fgcolor.b + ((material.b * dynlight.b) >> 8), (uint32_t)255);
return fgcolor;
}
FORCEINLINE BgraColor VECTORCALL CalcDynamicLight(const PolyLight *lights, int num_lights, FVector3 worldpos, FVector3 worldnormal, uint32_t dynlightcolor)
{
BgraColor lit = dynlightcolor;
for (int i = 0; i != num_lights; i++)
{
FVector3 lightpos = { lights[i].x, lights[i].y, lights[i].z };
float light_radius = lights[i].radius;
bool is_attenuated = light_radius < 0.0f;
if (is_attenuated)
light_radius = -light_radius;
// L = light-pos
// dist = sqrt(dot(L, L))
// distance_attenuation = 1 - MIN(dist * (1/radius), 1)
FVector3 L = lightpos - worldpos;
float dist2 = L | L;
float rcp_dist = 1.0f / sqrt(dist2);
float dist = dist2 * rcp_dist;
float distance_attenuation = 256.0f - MIN(dist * light_radius, 256.0f);
// The simple light type
float simple_attenuation = distance_attenuation;
// The point light type
// diffuse = max(dot(N,normalize(L)),0) * attenuation
float dotNL = worldnormal | (L * rcp_dist);
float point_attenuation = MAX(dotNL, 0.0f) * distance_attenuation;
uint32_t attenuation = (uint32_t)(is_attenuated ? (int32_t)point_attenuation : (int32_t)simple_attenuation);
BgraColor light_color = lights[i].color;
lit.r += (light_color.r * attenuation) >> 8;
lit.g += (light_color.g * attenuation) >> 8;
lit.b += (light_color.b * attenuation) >> 8;
}
lit.r = MIN(lit.r, (uint32_t)256);
lit.g = MIN(lit.g, (uint32_t)256);
lit.b = MIN(lit.b, (uint32_t)256);
return lit;
}
template<typename ShadeModeT>
FORCEINLINE BgraColor Shade32(BgraColor fgcolor, BgraColor mlight, uint32_t desaturate, uint32_t inv_desaturate, BgraColor shade_fade, BgraColor shade_light, BgraColor dynlight)
{
BgraColor material = fgcolor;
if (ShadeModeT::Mode == (int)ShadeMode::Simple)
{
fgcolor.r = (fgcolor.r * mlight.r) >> 8;
fgcolor.g = (fgcolor.g * mlight.g) >> 8;
fgcolor.b = (fgcolor.b * mlight.b) >> 8;
}
else if (ShadeModeT::Mode == (int)ShadeMode::Advanced)
{
uint32_t intensity = ((fgcolor.r * 77 + fgcolor.g * 143 + fgcolor.b * 37) >> 8) * desaturate;
fgcolor.r = (((shade_fade.r + ((fgcolor.r * inv_desaturate + intensity) >> 8) * mlight.r) >> 8) * shade_light.r) >> 8;
fgcolor.g = (((shade_fade.g + ((fgcolor.g * inv_desaturate + intensity) >> 8) * mlight.g) >> 8) * shade_light.g) >> 8;
fgcolor.b = (((shade_fade.b + ((fgcolor.b * inv_desaturate + intensity) >> 8) * mlight.b) >> 8) * shade_light.b) >> 8;
}
return AddLights(material, fgcolor, dynlight);
}
template<typename BlendT>
FORCEINLINE BgraColor Blend32(BgraColor fgcolor, BgraColor bgcolor, uint32_t ifgcolor, uint32_t ifgshade, uint32_t srcalpha, uint32_t destalpha)
{
if (BlendT::Mode == (int)BlendModes::Opaque)
{
fgcolor.a = 255;
return fgcolor;
}
else if (BlendT::Mode == (int)BlendModes::Masked)
{
return (ifgcolor == 0) ? bgcolor : fgcolor;
}
else if (BlendT::Mode == (int)BlendModes::AddSrcColorOneMinusSrcColor)
{
uint32_t srcred = fgcolor.r + (fgcolor.r >> 7);
uint32_t srcgreen = fgcolor.g + (fgcolor.g >> 7);
uint32_t srcblue = fgcolor.b + (fgcolor.b >> 7);
uint32_t inv_srcred = 256 - srcred;
uint32_t inv_srcgreen = 256 - srcgreen;
uint32_t inv_srcblue = 256 - srcblue;
BgraColor outcolor;
outcolor.r = (fgcolor.r * srcred + bgcolor.r * inv_srcred) >> 8;
outcolor.g = (fgcolor.g * srcgreen + bgcolor.g * inv_srcgreen) >> 8;
outcolor.b = (fgcolor.b * srcblue + bgcolor.b * inv_srcblue) >> 8;
outcolor.a = 255;
return outcolor;
}
else if (BlendT::Mode == (int)BlendModes::Shaded)
{
uint32_t alpha = ifgshade;
uint32_t inv_alpha = 256 - alpha;
BgraColor outcolor;
outcolor.r = (fgcolor.r * alpha + bgcolor.r * inv_alpha) >> 8;
outcolor.g = (fgcolor.g * alpha + bgcolor.g * inv_alpha) >> 8;
outcolor.b = (fgcolor.b * alpha + bgcolor.b * inv_alpha) >> 8;
outcolor.a = 255;
return outcolor;
}
else if (BlendT::Mode == (int)BlendModes::AddClampShaded)
{
uint32_t alpha = ifgshade;
BgraColor outcolor;
outcolor.r = ((fgcolor.r * alpha) >> 8) + bgcolor.r;
outcolor.g = ((fgcolor.g * alpha) >> 8) + bgcolor.g;
outcolor.b = ((fgcolor.b * alpha) >> 8) + bgcolor.b;
outcolor.a = 255;
return outcolor;
}
else
{
uint32_t alpha = APART(ifgcolor);
alpha += alpha >> 7; // 255->256
uint32_t inv_alpha = 256 - alpha;
uint32_t bgalpha = (destalpha * alpha + (inv_alpha << 8) + 128) >> 8;
uint32_t fgalpha = (srcalpha * alpha + 128) >> 8;
fgcolor.r *= fgalpha;
fgcolor.g *= fgalpha;
fgcolor.b *= fgalpha;
bgcolor.r *= bgalpha;
bgcolor.g *= bgalpha;
bgcolor.b *= bgalpha;
BgraColor outcolor;
if (BlendT::Mode == (int)BlendModes::AddClamp)
{
outcolor.r = MIN<uint32_t>((fgcolor.r + bgcolor.r) >> 8, 255);
outcolor.g = MIN<uint32_t>((fgcolor.g + bgcolor.g) >> 8, 255);
outcolor.b = MIN<uint32_t>((fgcolor.b + bgcolor.b) >> 8, 255);
}
else if (BlendT::Mode == (int)BlendModes::SubClamp)
{
outcolor.r = MAX(int32_t(fgcolor.r - bgcolor.r) >> 8, 0);
outcolor.g = MAX(int32_t(fgcolor.g - bgcolor.g) >> 8, 0);
outcolor.b = MAX(int32_t(fgcolor.b - bgcolor.b) >> 8, 0);
}
else if (BlendT::Mode == (int)BlendModes::RevSubClamp)
{
outcolor.r = MAX(int32_t(bgcolor.r - fgcolor.r) >> 8, 0);
outcolor.g = MAX(int32_t(bgcolor.g - fgcolor.g) >> 8, 0);
outcolor.b = MAX(int32_t(bgcolor.b - fgcolor.b) >> 8, 0);
}
outcolor.a = 255;
return outcolor;
}
}
}
template<typename BlendT, typename SamplerT>
class RectScreenDrawer32
{
public:
static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
if (SamplerT::Mode == (int)Samplers::Fuzz)
{
Loop<NoShade, NearestFilter>(destOrg, destWidth, destHeight, destPitch, args, thread);
}
else if (args->SimpleShade())
{
Loop<SimpleShade, NearestFilter>(destOrg, destWidth, destHeight, destPitch, args, thread);
}
else
{
Loop<AdvancedShade, NearestFilter>(destOrg, destWidth, destHeight, destPitch, args, thread);
}
}
private:
template<typename ShadeModeT, typename FilterModeT>
FORCEINLINE static void Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
int x0 = clamp((int)(args->X0() + 0.5f), 0, destWidth);
int x1 = clamp((int)(args->X1() + 0.5f), 0, destWidth);
int y0 = clamp((int)(args->Y0() + 0.5f), 0, destHeight);
int y1 = clamp((int)(args->Y1() + 0.5f), 0, destHeight);
if (x1 <= x0 || y1 <= y0)
return;
uint32_t srcalpha = args->SrcAlpha();
uint32_t destalpha = args->DestAlpha();
// Setup step variables
float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0());
float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0());
uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000);
uint32_t startV = (int32_t)((args->V0() + (y0 + 0.5f - args->Y0()) * fstepV) * 0x1000000);
uint32_t stepU = (int32_t)(fstepU * 0x1000000);
uint32_t stepV = (int32_t)(fstepV * 0x1000000);
// Sampling stuff
uint32_t color = args->Color();
const uint32_t * RESTRICT translation = (const uint32_t *)args->Translation();
const uint32_t * RESTRICT texPixels = (const uint32_t *)args->TexturePixels();
uint32_t texWidth = args->TextureWidth();
uint32_t texHeight = args->TextureHeight();
uint32_t oneU, oneV;
if (SamplerT::Mode != (int)Samplers::Fill)
{
oneU = ((0x800000 + texWidth - 1) / texWidth) * 2 + 1;
oneV = ((0x800000 + texHeight - 1) / texHeight) * 2 + 1;
}
else
{
oneU = 0;
oneV = 0;
}
// Setup light
uint32_t lightpos = args->Light();
lightpos += lightpos >> 7; // 255 -> 256
BgraColor mlight;
BgraColor dynlight = 0;
// Shade constants
int inv_desaturate;
BgraColor shade_fade_lit, shade_light;
int desaturate;
if (ShadeModeT::Mode == (int)ShadeMode::Advanced)
{
uint32_t inv_light = 256 - lightpos;
shade_fade_lit.r = args->ShadeFadeRed() * inv_light;
shade_fade_lit.g = args->ShadeFadeGreen() * inv_light;
shade_fade_lit.b = args->ShadeFadeBlue() * inv_light;
shade_light.r = args->ShadeLightRed();
shade_light.g = args->ShadeLightGreen();
shade_light.b = args->ShadeLightBlue();
desaturate = args->ShadeDesaturate();
inv_desaturate = 256 - desaturate;
mlight.r = lightpos;
mlight.g = lightpos;
mlight.b = lightpos;
}
else
{
inv_desaturate = 0;
shade_fade_lit.r = 0;
shade_fade_lit.g = 0;
shade_fade_lit.b = 0;
shade_light.r = 0;
shade_light.g = 0;
shade_light.b = 0;
desaturate = 0;
mlight.r = lightpos;
mlight.g = lightpos;
mlight.b = lightpos;
}
int count = x1 - x0;
uint32_t posV = startV;
for (int y = y0; y < y1; y++, posV += stepV)
{
int coreBlock = y / 8;
if (coreBlock % thread->num_cores != thread->core)
{
continue;
}
uint32_t *dest = ((uint32_t*)destOrg) + y * destPitch + x0;
uint32_t posU = startU;
for (int i = 0; i < count; i++)
{
// Load bgcolor
BgraColor bgcolor;
if (BlendT::Mode != (int)BlendModes::Opaque)
bgcolor = *dest;
else
bgcolor = 0;
// Sample fgcolor
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = *dest;
unsigned int ifgcolor = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
unsigned int ifgshade = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, x0 + i, y);
posU += stepU;
// Shade and blend
BgraColor fgcolor = Shade32<ShadeModeT>(ifgcolor, mlight, desaturate, inv_desaturate, shade_fade_lit, shade_light, dynlight);
BgraColor outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor, ifgshade, srcalpha, destalpha);
// Store result
*dest = outcolor;
dest++;
}
}
}
};

View file

@ -1,518 +0,0 @@
/*
** Polygon Doom software renderer
** 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.
**
*/
#pragma once
#include "screen_triangle.h"
namespace TriScreenDrawerModes
{
template<typename SamplerT, typename FilterModeT>
FORCEINLINE unsigned int VECTORCALL Sample32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, uint32_t oneU, uint32_t oneV, uint32_t color, const uint32_t *translation)
{
uint32_t texel;
if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill || SamplerT::Mode == (int)Samplers::Fuzz || SamplerT::Mode == (int)Samplers::FogBoundary)
{
return color;
}
else if (SamplerT::Mode == (int)Samplers::Translated)
{
const uint8_t *texpal = (const uint8_t *)texPixels;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
return translation[texpal[texelX * texHeight + texelY]];
}
else if (FilterModeT::Mode == (int)FilterModes::Nearest)
{
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
texel = texPixels[texelX * texHeight + texelY];
}
else
{
u -= oneU >> 1;
v -= oneV >> 1;
unsigned int frac_x0 = (((uint32_t)u << 8) >> FRACBITS) * texWidth;
unsigned int frac_x1 = ((((uint32_t)u << 8) + oneU) >> FRACBITS) * texWidth;
unsigned int frac_y0 = (((uint32_t)v << 8) >> FRACBITS) * texHeight;
unsigned int frac_y1 = ((((uint32_t)v << 8) + oneV) >> FRACBITS) * texHeight;
unsigned int x0 = frac_x0 >> FRACBITS;
unsigned int x1 = frac_x1 >> FRACBITS;
unsigned int y0 = frac_y0 >> FRACBITS;
unsigned int y1 = frac_y1 >> FRACBITS;
unsigned int p00 = texPixels[x0 * texHeight + y0];
unsigned int p01 = texPixels[x0 * texHeight + y1];
unsigned int p10 = texPixels[x1 * texHeight + y0];
unsigned int p11 = texPixels[x1 * texHeight + y1];
unsigned int inv_a = (frac_x1 >> (FRACBITS - 4)) & 15;
unsigned int inv_b = (frac_y1 >> (FRACBITS - 4)) & 15;
unsigned int a = 16 - inv_a;
unsigned int b = 16 - inv_b;
unsigned int sred = (RPART(p00) * (a * b) + RPART(p01) * (inv_a * b) + RPART(p10) * (a * inv_b) + RPART(p11) * (inv_a * inv_b) + 127) >> 8;
unsigned int sgreen = (GPART(p00) * (a * b) + GPART(p01) * (inv_a * b) + GPART(p10) * (a * inv_b) + GPART(p11) * (inv_a * inv_b) + 127) >> 8;
unsigned int sblue = (BPART(p00) * (a * b) + BPART(p01) * (inv_a * b) + BPART(p10) * (a * inv_b) + BPART(p11) * (inv_a * inv_b) + 127) >> 8;
unsigned int salpha = (APART(p00) * (a * b) + APART(p01) * (inv_a * b) + APART(p10) * (a * inv_b) + APART(p11) * (inv_a * inv_b) + 127) >> 8;
texel = (salpha << 24) | (sred << 16) | (sgreen << 8) | sblue;
}
if (SamplerT::Mode == (int)Samplers::Skycap)
{
int start_fade = 2; // How fast it should fade out
int alpha_top = clamp(v >> (16 - start_fade), 0, 256);
int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256);
int a = MIN(alpha_top, alpha_bottom);
int inv_a = 256 - a;
uint32_t r = RPART(texel);
uint32_t g = GPART(texel);
uint32_t b = BPART(texel);
uint32_t fg_a = APART(texel);
uint32_t bg_red = RPART(color);
uint32_t bg_green = GPART(color);
uint32_t bg_blue = BPART(color);
r = (r * a + bg_red * inv_a + 127) >> 8;
g = (g * a + bg_green * inv_a + 127) >> 8;
b = (b * a + bg_blue * inv_a + 127) >> 8;
return MAKEARGB(fg_a, r, g, b);
}
else
{
return texel;
}
}
template<typename SamplerT>
FORCEINLINE unsigned int VECTORCALL SampleShade32(int32_t u, int32_t v, const uint32_t *texPixels, int texWidth, int texHeight, int x, int y)
{
if (SamplerT::Mode == (int)Samplers::Shaded)
{
const uint8_t *texpal = (const uint8_t *)texPixels;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = texpal[texelX * texHeight + texelY];
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
return sampleshadeout;
}
else if (SamplerT::Mode == (int)Samplers::Stencil)
{
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]);
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
return sampleshadeout;
}
else if (SamplerT::Mode == (int)Samplers::Fuzz)
{
using namespace swrenderer;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]);
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
fixed_t fuzzscale = (200 << FRACBITS) / viewheight;
int scaled_x = (x * fuzzscale) >> FRACBITS;
int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + fuzzpos;
fixed_t fuzzcount = FUZZTABLE << FRACBITS;
fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount;
unsigned int alpha = fuzzoffset[fuzz >> FRACBITS];
sampleshadeout = (sampleshadeout * alpha) >> 5;
return sampleshadeout;
}
else
{
return 0;
}
}
FORCEINLINE __m128i VECTORCALL AddLights(__m128i material, __m128i fgcolor, __m128i dynlight)
{
fgcolor = _mm_add_epi16(fgcolor, _mm_srli_epi16(_mm_mullo_epi16(material, dynlight), 8));
fgcolor = _mm_min_epi16(fgcolor, _mm_set1_epi16(255));
return fgcolor;
}
FORCEINLINE __m128i VECTORCALL CalcDynamicLight(const PolyLight *lights, int num_lights, __m128 worldpos, __m128 worldnormal, uint32_t dynlightcolor)
{
__m128i lit = _mm_unpacklo_epi8(_mm_cvtsi32_si128(dynlightcolor), _mm_setzero_si128());
lit = _mm_shuffle_epi32(lit, _MM_SHUFFLE(1, 0, 1, 0));
for (int i = 0; i != num_lights; i++)
{
__m128 m256 = _mm_set1_ps(256.0f);
__m128 mSignBit = _mm_set1_ps(-0.0f);
__m128 lightpos = _mm_loadu_ps(&lights[i].x);
__m128 light_radius = _mm_load_ss(&lights[i].radius);
__m128 is_attenuated = _mm_cmpge_ss(light_radius, _mm_setzero_ps());
is_attenuated = _mm_shuffle_ps(is_attenuated, is_attenuated, _MM_SHUFFLE(0, 0, 0, 0));
light_radius = _mm_andnot_ps(mSignBit, light_radius);
// L = light-pos
// dist = sqrt(dot(L, L))
// distance_attenuation = 1 - MIN(dist * (1/radius), 1)
__m128 L = _mm_sub_ps(lightpos, worldpos);
__m128 dist2 = _mm_mul_ps(L, L);
dist2 = _mm_add_ss(dist2, _mm_add_ss(_mm_shuffle_ps(dist2, dist2, _MM_SHUFFLE(0, 0, 0, 1)), _mm_shuffle_ps(dist2, dist2, _MM_SHUFFLE(0, 0, 0, 2))));
__m128 rcp_dist = _mm_rsqrt_ss(dist2);
__m128 dist = _mm_mul_ss(dist2, rcp_dist);
__m128 distance_attenuation = _mm_sub_ss(m256, _mm_min_ss(_mm_mul_ss(dist, light_radius), m256));
distance_attenuation = _mm_shuffle_ps(distance_attenuation, distance_attenuation, _MM_SHUFFLE(0, 0, 0, 0));
// The simple light type
__m128 simple_attenuation = distance_attenuation;
// The point light type
// diffuse = max(dot(N,normalize(L)),0) * attenuation
__m128 dotNL = _mm_mul_ps(worldnormal, _mm_mul_ps(L, _mm_shuffle_ps(rcp_dist, rcp_dist, _MM_SHUFFLE(0, 0, 0, 0))));
dotNL = _mm_add_ss(dotNL, _mm_add_ss(_mm_shuffle_ps(dotNL, dotNL, _MM_SHUFFLE(0, 0, 0, 1)), _mm_shuffle_ps(dotNL, dotNL, _MM_SHUFFLE(0, 0, 0, 2))));
dotNL = _mm_max_ss(dotNL, _mm_setzero_ps());
__m128 point_attenuation = _mm_mul_ss(dotNL, distance_attenuation);
point_attenuation = _mm_shuffle_ps(point_attenuation, point_attenuation, _MM_SHUFFLE(0, 0, 0, 0));
__m128i attenuation = _mm_cvtps_epi32(_mm_or_ps(_mm_and_ps(is_attenuated, simple_attenuation), _mm_andnot_ps(is_attenuated, point_attenuation)));
attenuation = _mm_packs_epi32(_mm_shuffle_epi32(attenuation, _MM_SHUFFLE(0, 0, 0, 0)), _mm_shuffle_epi32(attenuation, _MM_SHUFFLE(1, 1, 1, 1)));
__m128i light_color = _mm_cvtsi32_si128(lights[i].color);
light_color = _mm_unpacklo_epi8(light_color, _mm_setzero_si128());
light_color = _mm_shuffle_epi32(light_color, _MM_SHUFFLE(1, 0, 1, 0));
lit = _mm_add_epi16(lit, _mm_srli_epi16(_mm_mullo_epi16(light_color, attenuation), 8));
}
return _mm_min_epi16(lit, _mm_set1_epi16(256));
}
template<typename ShadeModeT>
FORCEINLINE __m128i VECTORCALL Shade32(__m128i fgcolor, __m128i mlight, unsigned int ifgcolor0, unsigned int ifgcolor1, int desaturate, __m128i inv_desaturate, __m128i shade_fade, __m128i shade_light, __m128i dynlight)
{
__m128i material = fgcolor;
if (ShadeModeT::Mode == (int)ShadeMode::Simple)
{
fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, mlight), 8);
}
else if (ShadeModeT::Mode == (int)ShadeMode::Advanced)
{
int blue0 = BPART(ifgcolor0);
int green0 = GPART(ifgcolor0);
int red0 = RPART(ifgcolor0);
int intensity0 = ((red0 * 77 + green0 * 143 + blue0 * 37) >> 8) * desaturate;
int blue1 = BPART(ifgcolor1);
int green1 = GPART(ifgcolor1);
int red1 = RPART(ifgcolor1);
int intensity1 = ((red1 * 77 + green1 * 143 + blue1 * 37) >> 8) * desaturate;
__m128i intensity = _mm_set_epi16(0, intensity1, intensity1, intensity1, 0, intensity0, intensity0, intensity0);
fgcolor = _mm_srli_epi16(_mm_add_epi16(_mm_mullo_epi16(fgcolor, inv_desaturate), intensity), 8);
fgcolor = _mm_mullo_epi16(fgcolor, mlight);
fgcolor = _mm_srli_epi16(_mm_add_epi16(shade_fade, fgcolor), 8);
fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, shade_light), 8);
}
return AddLights(material, fgcolor, dynlight);
}
template<typename BlendT>
FORCEINLINE __m128i VECTORCALL Blend32(__m128i fgcolor, __m128i bgcolor, unsigned int ifgcolor0, unsigned int ifgcolor1, unsigned int ifgshade0, unsigned int ifgshade1, uint32_t srcalpha, uint32_t destalpha)
{
if (BlendT::Mode == (int)BlendModes::Opaque)
{
__m128i outcolor = fgcolor;
outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128());
outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000));
return outcolor;
}
else if (BlendT::Mode == (int)BlendModes::Masked)
{
__m128i mask = _mm_cmpeq_epi32(_mm_packus_epi16(fgcolor, _mm_setzero_si128()), _mm_setzero_si128());
mask = _mm_unpacklo_epi8(mask, _mm_setzero_si128());
__m128i outcolor = _mm_or_si128(_mm_and_si128(mask, bgcolor), _mm_andnot_si128(mask, fgcolor));
outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128());
outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000));
return outcolor;
}
else if (BlendT::Mode == (int)BlendModes::AddSrcColorOneMinusSrcColor)
{
__m128i inv_srccolor = _mm_sub_epi16(_mm_set1_epi16(256), _mm_add_epi16(fgcolor, _mm_srli_epi16(fgcolor, 7)));
__m128i outcolor = _mm_add_epi16(fgcolor, _mm_srli_epi16(_mm_mullo_epi16(bgcolor, inv_srccolor), 8));
outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128());
return outcolor;
}
else if (BlendT::Mode == (int)BlendModes::Shaded)
{
ifgshade0 = (ifgshade0 * srcalpha + 128) >> 8;
ifgshade1 = (ifgshade1 * srcalpha + 128) >> 8;
__m128i alpha = _mm_set_epi16(ifgshade1, ifgshade1, ifgshade1, ifgshade1, ifgshade0, ifgshade0, ifgshade0, ifgshade0);
__m128i inv_alpha = _mm_sub_epi16(_mm_set1_epi16(256), alpha);
fgcolor = _mm_mullo_epi16(fgcolor, alpha);
bgcolor = _mm_mullo_epi16(bgcolor, inv_alpha);
__m128i outcolor = _mm_srli_epi16(_mm_add_epi16(fgcolor, bgcolor), 8);
outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128());
outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000));
return outcolor;
}
else if (BlendT::Mode == (int)BlendModes::AddClampShaded)
{
ifgshade0 = (ifgshade0 * srcalpha + 128) >> 8;
ifgshade1 = (ifgshade1 * srcalpha + 128) >> 8;
__m128i alpha = _mm_set_epi16(ifgshade1, ifgshade1, ifgshade1, ifgshade1, ifgshade0, ifgshade0, ifgshade0, ifgshade0);
fgcolor = _mm_srli_epi16(_mm_mullo_epi16(fgcolor, alpha), 8);
__m128i outcolor = _mm_add_epi16(fgcolor, bgcolor);
outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128());
outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000));
return outcolor;
}
else
{
uint32_t alpha0 = APART(ifgcolor0);
uint32_t alpha1 = APART(ifgcolor1);
alpha0 += alpha0 >> 7; // 255->256
alpha1 += alpha1 >> 7; // 255->256
uint32_t inv_alpha0 = 256 - alpha0;
uint32_t inv_alpha1 = 256 - alpha1;
uint32_t bgalpha0 = (destalpha * alpha0 + (inv_alpha0 << 8) + 128) >> 8;
uint32_t bgalpha1 = (destalpha * alpha1 + (inv_alpha1 << 8) + 128) >> 8;
uint32_t fgalpha0 = (srcalpha * alpha0 + 128) >> 8;
uint32_t fgalpha1 = (srcalpha * alpha1 + 128) >> 8;
__m128i bgalpha = _mm_set_epi16(bgalpha1, bgalpha1, bgalpha1, bgalpha1, bgalpha0, bgalpha0, bgalpha0, bgalpha0);
__m128i fgalpha = _mm_set_epi16(fgalpha1, fgalpha1, fgalpha1, fgalpha1, fgalpha0, fgalpha0, fgalpha0, fgalpha0);
fgcolor = _mm_mullo_epi16(fgcolor, fgalpha);
bgcolor = _mm_mullo_epi16(bgcolor, bgalpha);
__m128i fg_lo = _mm_unpacklo_epi16(fgcolor, _mm_setzero_si128());
__m128i bg_lo = _mm_unpacklo_epi16(bgcolor, _mm_setzero_si128());
__m128i fg_hi = _mm_unpackhi_epi16(fgcolor, _mm_setzero_si128());
__m128i bg_hi = _mm_unpackhi_epi16(bgcolor, _mm_setzero_si128());
__m128i out_lo, out_hi;
if (BlendT::Mode == (int)BlendModes::AddClamp)
{
out_lo = _mm_add_epi32(fg_lo, bg_lo);
out_hi = _mm_add_epi32(fg_hi, bg_hi);
}
else if (BlendT::Mode == (int)BlendModes::SubClamp)
{
out_lo = _mm_sub_epi32(fg_lo, bg_lo);
out_hi = _mm_sub_epi32(fg_hi, bg_hi);
}
else if (BlendT::Mode == (int)BlendModes::RevSubClamp)
{
out_lo = _mm_sub_epi32(bg_lo, fg_lo);
out_hi = _mm_sub_epi32(bg_hi, fg_hi);
}
out_lo = _mm_srai_epi32(out_lo, 8);
out_hi = _mm_srai_epi32(out_hi, 8);
__m128i outcolor = _mm_packs_epi32(out_lo, out_hi);
outcolor = _mm_packus_epi16(outcolor, _mm_setzero_si128());
outcolor = _mm_or_si128(outcolor, _mm_set1_epi32(0xff000000));
return outcolor;
}
}
}
template<typename BlendT, typename SamplerT>
class RectScreenDrawer32
{
public:
static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
if (args->SimpleShade())
{
Loop<SimpleShade, NearestFilter>(destOrg, destWidth, destHeight, destPitch, args, thread);
}
else
{
Loop<AdvancedShade, NearestFilter>(destOrg, destWidth, destHeight, destPitch, args, thread);
}
}
private:
template<typename ShadeModeT, typename FilterModeT>
FORCEINLINE static void VECTORCALL Loop(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
int x0 = clamp((int)(args->X0() + 0.5f), 0, destWidth);
int x1 = clamp((int)(args->X1() + 0.5f), 0, destWidth);
int y0 = clamp((int)(args->Y0() + 0.5f), 0, destHeight);
int y1 = clamp((int)(args->Y1() + 0.5f), 0, destHeight);
if (x1 <= x0 || y1 <= y0)
return;
uint32_t srcalpha = args->SrcAlpha();
uint32_t destalpha = args->DestAlpha();
// Setup step variables
float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0());
float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0());
uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000);
uint32_t startV = (int32_t)((args->V0() + (y0 + 0.5f - args->Y0()) * fstepV) * 0x1000000);
uint32_t stepU = (int32_t)(fstepU * 0x1000000);
uint32_t stepV = (int32_t)(fstepV * 0x1000000);
// Sampling stuff
uint32_t color = args->Color();
const uint32_t * RESTRICT translation = (const uint32_t *)args->Translation();
const uint32_t * RESTRICT texPixels = (const uint32_t *)args->TexturePixels();
uint32_t texWidth = args->TextureWidth();
uint32_t texHeight = args->TextureHeight();
uint32_t oneU, oneV;
if (SamplerT::Mode != (int)Samplers::Fill)
{
oneU = ((0x800000 + texWidth - 1) / texWidth) * 2 + 1;
oneV = ((0x800000 + texHeight - 1) / texHeight) * 2 + 1;
}
else
{
oneU = 0;
oneV = 0;
}
// Shade constants
__m128i inv_desaturate, shade_fade, shade_light;
int desaturate;
if (ShadeModeT::Mode == (int)ShadeMode::Advanced)
{
inv_desaturate = _mm_setr_epi16(256, 256 - args->ShadeDesaturate(), 256 - args->ShadeDesaturate(), 256 - args->ShadeDesaturate(), 256, 256 - args->ShadeDesaturate(), 256 - args->ShadeDesaturate(), 256 - args->ShadeDesaturate());
shade_fade = _mm_set_epi16(args->ShadeFadeAlpha(), args->ShadeFadeRed(), args->ShadeFadeGreen(), args->ShadeFadeBlue(), args->ShadeFadeAlpha(), args->ShadeFadeRed(), args->ShadeFadeGreen(), args->ShadeFadeBlue());
shade_light = _mm_set_epi16(args->ShadeLightAlpha(), args->ShadeLightRed(), args->ShadeLightGreen(), args->ShadeLightBlue(), args->ShadeLightAlpha(), args->ShadeLightRed(), args->ShadeLightGreen(), args->ShadeLightBlue());
desaturate = args->ShadeDesaturate();
}
else
{
inv_desaturate = _mm_setzero_si128();
shade_fade = _mm_setzero_si128();
shade_light = _mm_setzero_si128();
desaturate = 0;
}
// Setup light
uint32_t lightpos = args->Light();
lightpos += lightpos >> 7; // 255 -> 256
__m128i mlight = _mm_set_epi16(256, lightpos, lightpos, lightpos, 256, lightpos, lightpos, lightpos);
__m128i shade_fade_lit;
if (ShadeModeT::Mode == (int)ShadeMode::Advanced)
{
__m128i inv_light = _mm_sub_epi16(_mm_set_epi16(0, 256, 256, 256, 0, 256, 256, 256), mlight);
shade_fade_lit = _mm_mullo_epi16(shade_fade, inv_light);
}
else
{
shade_fade_lit = _mm_setzero_si128();
}
int count = x1 - x0;
int sseCount = count / 2;
uint32_t posV = startV;
for (int y = y0; y < y1; y++, posV += stepV)
{
int coreBlock = y / 8;
if (coreBlock % thread->num_cores != thread->core)
{
continue;
}
uint32_t *dest = ((uint32_t*)destOrg) + y * destPitch + x0;
uint32_t posU = startU;
for (int i = 0; i < sseCount; i++)
{
// Load bgcolor
__m128i bgcolor;
if (BlendT::Mode != (int)BlendModes::Opaque)
bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)dest), _mm_setzero_si128());
else
bgcolor = _mm_setzero_si128();
// Sample fgcolor
unsigned int ifgcolor[2], ifgshade[2];
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = dest[0];
ifgcolor[0] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, x0 + i * 2, y);
posU += stepU;
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = dest[1];
ifgcolor[1] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[1] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, x0 + i * 2 + 1, y);
posU += stepU;
// Shade and blend
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128());
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, _mm_setzero_si128());
__m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
// Store result
_mm_storel_epi64((__m128i*)dest, outcolor);
dest += 2;
}
if (sseCount * 2 != count)
{
// Load bgcolor
__m128i bgcolor;
if (BlendT::Mode != (int)BlendModes::Opaque)
bgcolor = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*dest), _mm_setzero_si128());
else
bgcolor = _mm_setzero_si128();
// Sample fgcolor
unsigned int ifgcolor[2], ifgshade[2];
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = *dest;
ifgcolor[0] = Sample32<SamplerT, FilterModeT>(posU, posV, texPixels, texWidth, texHeight, oneU, oneV, color, translation);
ifgshade[0] = SampleShade32<SamplerT>(posU, posV, texPixels, texWidth, texHeight, x0 + sseCount * 2, y);
ifgcolor[1] = 0;
ifgshade[1] = 0;
posU += stepU;
// Shade and blend
__m128i fgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)ifgcolor), _mm_setzero_si128());
fgcolor = Shade32<ShadeModeT>(fgcolor, mlight, ifgcolor[0], ifgcolor[1], desaturate, inv_desaturate, shade_fade_lit, shade_light, _mm_setzero_si128());
__m128i outcolor = Blend32<BlendT>(fgcolor, bgcolor, ifgcolor[0], ifgcolor[1], ifgshade[0], ifgshade[1], srcalpha, destalpha);
// Store result
*dest = _mm_cvtsi128_si32(outcolor);
}
}
}
};

View file

@ -1,295 +0,0 @@
/*
** Polygon Doom software renderer
** 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.
**
*/
#pragma once
#include "screen_triangle.h"
namespace TriScreenDrawerModes
{
template<typename SamplerT>
FORCEINLINE unsigned int Sample8(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight, uint32_t color, const uint8_t *translation)
{
uint8_t texel;
if (SamplerT::Mode == (int)Samplers::Shaded || SamplerT::Mode == (int)Samplers::Stencil || SamplerT::Mode == (int)Samplers::Fill || SamplerT::Mode == (int)Samplers::Fuzz || SamplerT::Mode == (int)Samplers::FogBoundary)
{
return color;
}
else if (SamplerT::Mode == (int)Samplers::Translated)
{
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
return translation[texPixels[texelX * texHeight + texelY]];
}
else
{
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
texel = texPixels[texelX * texHeight + texelY];
}
if (SamplerT::Mode == (int)Samplers::Skycap)
{
int start_fade = 2; // How fast it should fade out
int alpha_top = clamp(v >> (16 - start_fade), 0, 256);
int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256);
int a = MIN(alpha_top, alpha_bottom);
int inv_a = 256 - a;
if (a == 256)
return texel;
uint32_t capcolor = GPalette.BaseColors[color].d;
uint32_t texelrgb = GPalette.BaseColors[texel].d;
uint32_t r = RPART(texelrgb);
uint32_t g = GPART(texelrgb);
uint32_t b = BPART(texelrgb);
uint32_t capcolor_red = RPART(capcolor);
uint32_t capcolor_green = GPART(capcolor);
uint32_t capcolor_blue = BPART(capcolor);
r = (r * a + capcolor_red * inv_a + 127) >> 8;
g = (g * a + capcolor_green * inv_a + 127) >> 8;
b = (b * a + capcolor_blue * inv_a + 127) >> 8;
return RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)];
}
else
{
return texel;
}
}
template<typename SamplerT>
FORCEINLINE unsigned int SampleShade8(int32_t u, int32_t v, const uint8_t *texPixels, int texWidth, int texHeight, int x, int y)
{
if (SamplerT::Mode == (int)Samplers::Shaded)
{
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = texPixels[texelX * texHeight + texelY];
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
return sampleshadeout;
}
else if (SamplerT::Mode == (int)Samplers::Stencil)
{
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
return texPixels[texelX * texHeight + texelY] != 0 ? 256 : 0;
}
else if (SamplerT::Mode == (int)Samplers::Fuzz)
{
using namespace swrenderer;
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = (texPixels[texelX * texHeight + texelY] != 0) ? 256 : 0;
fixed_t fuzzscale = (200 << FRACBITS) / viewheight;
int scaled_x = (x * fuzzscale) >> FRACBITS;
int fuzz_x = fuzz_random_x_offset[scaled_x % FUZZ_RANDOM_X_SIZE] + fuzzpos;
fixed_t fuzzcount = FUZZTABLE << FRACBITS;
fixed_t fuzz = ((fuzz_x << FRACBITS) + y * fuzzscale) % fuzzcount;
unsigned int alpha = fuzzoffset[fuzz >> FRACBITS];
sampleshadeout = (sampleshadeout * alpha) >> 5;
return sampleshadeout;
}
else
{
return 0;
}
}
template<typename BlendT>
FORCEINLINE uint8_t ShadeAndBlend8(uint8_t fgcolor, uint8_t bgcolor, uint32_t fgshade, uint32_t lightshade, const uint8_t *colormaps, uint32_t srcalpha, uint32_t destalpha)
{
lightshade = ((256 - lightshade) * NUMCOLORMAPS) & 0xffffff00;
uint8_t shadedfg = colormaps[lightshade + fgcolor];
if (BlendT::Mode == (int)BlendModes::Opaque)
{
return shadedfg;
}
else if (BlendT::Mode == (int)BlendModes::Masked)
{
return (fgcolor != 0) ? shadedfg : bgcolor;
}
else if (BlendT::Mode == (int)BlendModes::AddSrcColorOneMinusSrcColor)
{
int32_t fg_r = GPalette.BaseColors[shadedfg].r;
int32_t fg_g = GPalette.BaseColors[shadedfg].g;
int32_t fg_b = GPalette.BaseColors[shadedfg].b;
int32_t bg_r = GPalette.BaseColors[bgcolor].r;
int32_t bg_g = GPalette.BaseColors[bgcolor].g;
int32_t bg_b = GPalette.BaseColors[bgcolor].b;
int32_t inv_fg_r = 256 - (fg_r + (fg_r >> 7));
int32_t inv_fg_g = 256 - (fg_g + (fg_g >> 7));
int32_t inv_fg_b = 256 - (fg_b + (fg_b >> 7));
fg_r = MIN<int32_t>(fg_r + ((bg_r * inv_fg_r + 127) >> 8), 255);
fg_g = MIN<int32_t>(fg_g + ((bg_g * inv_fg_g + 127) >> 8), 255);
fg_b = MIN<int32_t>(fg_b + ((bg_b * inv_fg_b + 127) >> 8), 255);
shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)];
return (fgcolor != 0) ? shadedfg : bgcolor;
}
else if (BlendT::Mode == (int)BlendModes::Shaded)
{
fgshade = (fgshade * srcalpha + 128) >> 8;
uint32_t alpha = fgshade;
uint32_t inv_alpha = 256 - fgshade;
int32_t fg_r = GPalette.BaseColors[shadedfg].r;
int32_t fg_g = GPalette.BaseColors[shadedfg].g;
int32_t fg_b = GPalette.BaseColors[shadedfg].b;
int32_t bg_r = GPalette.BaseColors[bgcolor].r;
int32_t bg_g = GPalette.BaseColors[bgcolor].g;
int32_t bg_b = GPalette.BaseColors[bgcolor].b;
fg_r = (fg_r * alpha + bg_r * inv_alpha + 127) >> 8;
fg_g = (fg_g * alpha + bg_g * inv_alpha + 127) >> 8;
fg_b = (fg_b * alpha + bg_b * inv_alpha + 127) >> 8;
shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)];
return (alpha != 0) ? shadedfg : bgcolor;
}
else if (BlendT::Mode == (int)BlendModes::AddClampShaded)
{
fgshade = (fgshade * srcalpha + 128) >> 8;
uint32_t alpha = fgshade;
int32_t fg_r = GPalette.BaseColors[shadedfg].r;
int32_t fg_g = GPalette.BaseColors[shadedfg].g;
int32_t fg_b = GPalette.BaseColors[shadedfg].b;
int32_t bg_r = GPalette.BaseColors[bgcolor].r;
int32_t bg_g = GPalette.BaseColors[bgcolor].g;
int32_t bg_b = GPalette.BaseColors[bgcolor].b;
fg_r = MIN<int32_t>(bg_r + ((fg_r * alpha + 127) >> 8), 255);
fg_g = MIN<int32_t>(bg_g + ((fg_g * alpha + 127) >> 8), 255);
fg_b = MIN<int32_t>(bg_b + ((fg_b * alpha + 127) >> 8), 255);
shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)];
return (alpha != 0) ? shadedfg : bgcolor;
}
else
{
int32_t fg_r = GPalette.BaseColors[shadedfg].r;
int32_t fg_g = GPalette.BaseColors[shadedfg].g;
int32_t fg_b = GPalette.BaseColors[shadedfg].b;
int32_t bg_r = GPalette.BaseColors[bgcolor].r;
int32_t bg_g = GPalette.BaseColors[bgcolor].g;
int32_t bg_b = GPalette.BaseColors[bgcolor].b;
if (BlendT::Mode == (int)BlendModes::AddClamp)
{
fg_r = MIN(int32_t(fg_r * srcalpha + bg_r * destalpha + 127) >> 8, 255);
fg_g = MIN(int32_t(fg_g * srcalpha + bg_g * destalpha + 127) >> 8, 255);
fg_b = MIN(int32_t(fg_b * srcalpha + bg_b * destalpha + 127) >> 8, 255);
}
else if (BlendT::Mode == (int)BlendModes::SubClamp)
{
fg_r = MAX(int32_t(fg_r * srcalpha - bg_r * destalpha + 127) >> 8, 0);
fg_g = MAX(int32_t(fg_g * srcalpha - bg_g * destalpha + 127) >> 8, 0);
fg_b = MAX(int32_t(fg_b * srcalpha - bg_b * destalpha + 127) >> 8, 0);
}
else if (BlendT::Mode == (int)BlendModes::RevSubClamp)
{
fg_r = MAX(int32_t(bg_r * srcalpha - fg_r * destalpha + 127) >> 8, 0);
fg_g = MAX(int32_t(bg_g * srcalpha - fg_g * destalpha + 127) >> 8, 0);
fg_b = MAX(int32_t(bg_b * srcalpha - fg_b * destalpha + 127) >> 8, 0);
}
shadedfg = RGB256k.All[((fg_r >> 2) << 12) | ((fg_g >> 2) << 6) | (fg_b >> 2)];
return (fgcolor != 0) ? shadedfg : bgcolor;
}
}
}
template<typename BlendT, typename SamplerT>
class RectScreenDrawer8
{
public:
static void Execute(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
{
using namespace TriScreenDrawerModes;
int x0 = clamp((int)(args->X0() + 0.5f), 0, destWidth);
int x1 = clamp((int)(args->X1() + 0.5f), 0, destWidth);
int y0 = clamp((int)(args->Y0() + 0.5f), 0, destHeight);
int y1 = clamp((int)(args->Y1() + 0.5f), 0, destHeight);
if (x1 <= x0 || y1 <= y0)
return;
auto colormaps = args->BaseColormap();
uint32_t srcalpha = args->SrcAlpha();
uint32_t destalpha = args->DestAlpha();
// Setup step variables
float fstepU = (args->U1() - args->U0()) / (args->X1() - args->X0());
float fstepV = (args->V1() - args->V0()) / (args->Y1() - args->Y0());
uint32_t startU = (int32_t)((args->U0() + (x0 + 0.5f - args->X0()) * fstepU) * 0x1000000);
uint32_t startV = (int32_t)((args->V0() + (y0 + 0.5f - args->Y0()) * fstepV) * 0x1000000);
uint32_t stepU = (int32_t)(fstepU * 0x1000000);
uint32_t stepV = (int32_t)(fstepV * 0x1000000);
// Sampling stuff
uint32_t color = args->Color();
const uint8_t * RESTRICT translation = args->Translation();
const uint8_t * RESTRICT texPixels = args->TexturePixels();
uint32_t texWidth = args->TextureWidth();
uint32_t texHeight = args->TextureHeight();
// Setup light
uint32_t lightshade = args->Light();
lightshade += lightshade >> 7; // 255 -> 256
if (SamplerT::Mode == (int)Samplers::Fuzz) lightshade = 256;
int count = x1 - x0;
uint32_t posV = startV;
for (int y = y0; y < y1; y++, posV += stepV)
{
int coreBlock = y / 8;
if (coreBlock % thread->num_cores != thread->core)
{
continue;
}
uint8_t *dest = ((uint8_t*)destOrg) + y * destPitch + x0;
uint32_t posU = startU;
for (int i = 0; i < count; i++)
{
uint8_t bgcolor = *dest;
if (SamplerT::Mode == (int)Samplers::FogBoundary) color = bgcolor;
uint8_t fgcolor = Sample8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, color, translation);
uint32_t fgshade = SampleShade8<SamplerT>(posU, posV, texPixels, texWidth, texHeight, x0 + i, y);
*dest = ShadeAndBlend8<BlendT>(fgcolor, bgcolor, fgshade, lightshade, colormaps, srcalpha, destalpha);
posU += stepU;
dest++;
}
}
}
};

View file

@ -52,7 +52,7 @@ bool PolyTriangleDrawer::IsBgra()
return isBgraRenderTarget;
}
void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas, bool span_drawers)
void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas)
{
uint8_t *dest = (uint8_t*)canvas->GetPixels();
int dest_width = canvas->GetWidth();
@ -74,7 +74,7 @@ void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x,
dest_width = clamp(viewport_x + viewport_width, 0, dest_width - offsetx);
dest_height = clamp(viewport_y + viewport_height, 0, dest_height - offsety);
queue->Push<PolySetViewportCommand>(viewport_x, viewport_y, viewport_width, viewport_height, dest, dest_width, dest_height, dest_pitch, dest_bgra, span_drawers);
queue->Push<PolySetViewportCommand>(viewport_x, viewport_y, viewport_width, viewport_height, dest, dest_width, dest_height, dest_pitch, dest_bgra);
}
void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip)
@ -99,7 +99,7 @@ void PolyTriangleDrawer::SetWeaponScene(const DrawerCommandQueuePtr &queue, bool
/////////////////////////////////////////////////////////////////////////////
void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra, bool new_span_drawers)
void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra)
{
viewport_x = x;
viewport_y = y;
@ -110,7 +110,6 @@ void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, ui
dest_height = new_dest_height;
dest_pitch = new_dest_pitch;
dest_bgra = new_dest_bgra;
span_drawers = new_span_drawers;
ccw = true;
weaponScene = false;
}
@ -132,9 +131,7 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs)
args.clipbottom = dest_height;
args.uniforms = &drawargs;
args.destBgra = dest_bgra;
args.stencilPitch = PolyStencilBuffer::Instance()->BlockWidth();
args.stencilValues = PolyStencilBuffer::Instance()->Values();
args.stencilMasks = PolyStencilBuffer::Instance()->Masks();
args.stencilbuffer = PolyStencilBuffer::Instance()->Values();
args.zbuffer = PolyZBuffer::Instance()->Values();
args.depthOffset = weaponScene ? 1.0f : 0.0f;
@ -191,9 +188,7 @@ void PolyTriangleThreadData::DrawArrays(const PolyDrawArgs &drawargs)
args.clipbottom = dest_height;
args.uniforms = &drawargs;
args.destBgra = dest_bgra;
args.stencilPitch = PolyStencilBuffer::Instance()->BlockWidth();
args.stencilValues = PolyStencilBuffer::Instance()->Values();
args.stencilMasks = PolyStencilBuffer::Instance()->Masks();
args.stencilbuffer = PolyStencilBuffer::Instance()->Values();
args.zbuffer = PolyZBuffer::Instance()->Values();
args.depthOffset = weaponScene ? 1.0f : 0.0f;
@ -379,10 +374,7 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *vert, boo
args->v3 = &clippedvert[i - 2];
if (IsFrontfacing(args) == ccw && args->CalculateGradients())
{
if (!span_drawers)
ScreenTriangle::Draw(args, this);
else
ScreenTriangle::DrawSWRender(args, this);
ScreenTriangle::Draw(args, this);
}
}
}
@ -395,10 +387,7 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *vert, boo
args->v3 = &clippedvert[i];
if (IsFrontfacing(args) != ccw && args->CalculateGradients())
{
if (!span_drawers)
ScreenTriangle::Draw(args, this);
else
ScreenTriangle::DrawSWRender(args, this);
ScreenTriangle::Draw(args, this);
}
}
}
@ -631,14 +620,14 @@ void PolySetWeaponSceneCommand::Execute(DrawerThread *thread)
/////////////////////////////////////////////////////////////////////////////
PolySetViewportCommand::PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, bool span_drawers)
: x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra), span_drawers(span_drawers)
PolySetViewportCommand::PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra)
: x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra)
{
}
void PolySetViewportCommand::Execute(DrawerThread *thread)
{
PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra, span_drawers);
PolyTriangleThreadData::Get(thread)->SetViewport(x, y, width, height, dest, dest_width, dest_height, dest_pitch, dest_bgra);
}
/////////////////////////////////////////////////////////////////////////////

View file

@ -33,7 +33,7 @@ class PolyTriangleDrawer
{
public:
static void ClearBuffers(DCanvas *canvas);
static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas, bool span_drawers);
static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas);
static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw);
static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided);
static void SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable);
@ -47,7 +47,7 @@ class PolyTriangleThreadData
public:
PolyTriangleThreadData(int32_t core, int32_t num_cores) : core(core), num_cores(num_cores) { }
void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, bool span_drawers);
void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra);
void SetTransform(const Mat4f *objectToClip);
void SetCullCCW(bool value) { ccw = value; }
void SetTwoSided(bool value) { twosided = value; }
@ -88,7 +88,6 @@ private:
bool twosided = false;
bool weaponScene = false;
const Mat4f *objectToClip = nullptr;
bool span_drawers = false;
enum { max_additional_vertices = 16 };
};
@ -144,7 +143,7 @@ private:
class PolySetViewportCommand : public DrawerCommand
{
public:
PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra, bool span_drawers);
PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra);
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "PolySetViewport"; }
@ -159,7 +158,6 @@ private:
int dest_height;
int dest_pitch;
bool dest_bgra;
bool span_drawers;
};
class DrawPolyTrianglesCommand : public DrawerCommand

File diff suppressed because it is too large Load diff

View file

@ -52,9 +52,7 @@ struct TriDrawTriangleArgs
ShadedTriVertex *v3;
int32_t clipright;
int32_t clipbottom;
uint8_t *stencilValues;
uint32_t *stencilMasks;
int32_t stencilPitch;
uint8_t *stencilbuffer;
float *zbuffer;
const PolyDrawArgs *uniforms;
bool destBgra;
@ -138,39 +136,10 @@ enum class TriBlendMode
AddShadedTranslated
};
enum class RectBlendMode
{
TextureOpaque,
TextureMasked,
TextureAdd,
TextureSub,
TextureRevSub,
TextureAddSrcColor,
TranslatedOpaque,
TranslatedMasked,
TranslatedAdd,
TranslatedSub,
TranslatedRevSub,
TranslatedAddSrcColor,
Shaded,
AddShaded,
Stencil,
AddStencil,
FillOpaque,
FillAdd,
FillSub,
FillRevSub,
FillAddSrcColor,
Skycap,
Fuzz,
FogBoundary
};
class ScreenTriangle
{
public:
static void Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void DrawSWRender(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void(*SpanDrawers8[])(int y, int x0, int x1, const TriDrawTriangleArgs *args);
static void(*SpanDrawers32[])(int y, int x0, int x1, const TriDrawTriangleArgs *args);
@ -222,35 +191,6 @@ namespace TriScreenDrawerModes
struct StyleAddStencilTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; };
struct StyleAddShadedTranslated { static const int BlendOp = STYLEOP_Add, BlendSrc = STYLEALPHA_Src, BlendDest = STYLEALPHA_One, Flags = STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, SWFlags = SWSTYLEF_Translated; };
enum class BlendModes { Opaque, Masked, AddClamp, SubClamp, RevSubClamp, AddSrcColorOneMinusSrcColor, Shaded, AddClampShaded };
struct OpaqueBlend { static const int Mode = (int)BlendModes::Opaque; };
struct MaskedBlend { static const int Mode = (int)BlendModes::Masked; };
struct AddClampBlend { static const int Mode = (int)BlendModes::AddClamp; };
struct SubClampBlend { static const int Mode = (int)BlendModes::SubClamp; };
struct RevSubClampBlend { static const int Mode = (int)BlendModes::RevSubClamp; };
struct AddSrcColorBlend { static const int Mode = (int)BlendModes::AddSrcColorOneMinusSrcColor; };
struct ShadedBlend { static const int Mode = (int)BlendModes::Shaded; };
struct AddClampShadedBlend { static const int Mode = (int)BlendModes::AddClampShaded; };
enum class FilterModes { Nearest, Linear };
struct NearestFilter { static const int Mode = (int)FilterModes::Nearest; };
struct LinearFilter { static const int Mode = (int)FilterModes::Linear; };
enum class ShadeMode { None, Simple, Advanced };
struct NoShade { static const int Mode = (int)ShadeMode::None; };
struct SimpleShade { static const int Mode = (int)ShadeMode::Simple; };
struct AdvancedShade { static const int Mode = (int)ShadeMode::Advanced; };
enum class Samplers { Texture, Fill, Shaded, Stencil, Translated, Skycap, Fuzz, FogBoundary };
struct TextureSampler { static const int Mode = (int)Samplers::Texture; };
struct FillSampler { static const int Mode = (int)Samplers::Fill; };
struct ShadedSampler { static const int Mode = (int)Samplers::Shaded; };
struct StencilSampler { static const int Mode = (int)Samplers::Stencil; };
struct TranslatedSampler { static const int Mode = (int)Samplers::Translated; };
struct SkycapSampler { static const int Mode = (int)Samplers::Skycap; };
struct FuzzSampler { static const int Mode = (int)Samplers::Fuzz; };
struct FogBoundarySampler { static const int Mode = (int)Samplers::FogBoundary; };
enum SWOptFlags
{
SWOPT_DynLights = 1,

View file

@ -201,11 +201,11 @@ void PolyRenderer::SetSceneViewport()
height = (screenblocks*SCREENHEIGHT / 10) & ~7;
int bottom = SCREENHEIGHT - (height + viewwindowy - ((height - viewheight) / 2));
PolyTriangleDrawer::SetViewport(Threads.MainThread()->DrawQueue, viewwindowx, SCREENHEIGHT - bottom - height, viewwidth, height, RenderTarget, false);
PolyTriangleDrawer::SetViewport(Threads.MainThread()->DrawQueue, viewwindowx, SCREENHEIGHT - bottom - height, viewwidth, height, RenderTarget);
}
else // Rendering to camera texture
{
PolyTriangleDrawer::SetViewport(Threads.MainThread()->DrawQueue, 0, 0, RenderTarget->GetWidth(), RenderTarget->GetHeight(), RenderTarget, false);
PolyTriangleDrawer::SetViewport(Threads.MainThread()->DrawQueue, 0, 0, RenderTarget->GetWidth(), RenderTarget->GetHeight(), RenderTarget);
}
}

View file

@ -51,7 +51,7 @@ PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worl
{
}
void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix)
void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored)
{
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.Matrix);
@ -59,12 +59,14 @@ void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, co
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES))
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !mirrored);
}
void PolyModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
{
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES))
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, true);
ModelActor = nullptr;
}
@ -98,7 +100,7 @@ VSMatrix PolyModelRenderer::GetViewToWorldMatrix()
return objectToWorld;
}
void PolyModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix)
void PolyModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored)
{
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.Matrix);
@ -107,6 +109,7 @@ void PolyModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectT
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal])
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, mirrored);
}
void PolyModelRenderer::EndDrawHUDModel(AActor *actor)
@ -116,6 +119,7 @@ void PolyModelRenderer::EndDrawHUDModel(AActor *actor)
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal])
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, true);
}
void PolyModelRenderer::SetInterpolation(double interpolation)

View file

@ -36,13 +36,13 @@ public:
ModelRendererType GetType() const override { return PolyModelRendererType; }
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;
void SetVertexBuffer(IModelVertexBuffer *buffer) override;
void ResetVertexBuffer() override;
VSMatrix GetViewToWorldMatrix() override;
void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) override;
void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored) override;
void EndDrawHUDModel(AActor *actor) override;
void SetInterpolation(double interpolation) override;
void SetMaterial(FTexture *skin, bool clampNoFilter, int translation) override;

View file

@ -37,22 +37,6 @@
#import <AppKit/AppKit.h>
struct RenderBufferOptions
{
float pixelScale;
float shiftX;
float shiftY;
float width;
float height;
bool dirty;
};
extern RenderBufferOptions rbOpts;
// Version of AppKit framework we are interested in
// The following values are needed to build with earlier SDKs

View file

@ -484,11 +484,14 @@ void NSEventToGameMousePosition(NSEvent* inEvent, event_t* outEvent)
const NSPoint viewPos = [view convertPointToBacking:windowRect.origin];
const CGFloat frameHeight = I_GetContentViewSize(window).height;
const CGFloat posX = ( viewPos.x - rbOpts.shiftX) / rbOpts.pixelScale;
const CGFloat posY = (frameHeight - viewPos.y - rbOpts.shiftY) / rbOpts.pixelScale;
outEvent->data1 = static_cast<int16_t>( viewPos.x);
outEvent->data2 = static_cast<int16_t>(frameHeight - viewPos.y);
outEvent->data1 = static_cast<int>(posX);
outEvent->data2 = static_cast<int>(posY);
// Compensate letterbox adjustment done by cross-platform code
// More elegant solution is a bit problematic due to HiDPI/Retina support
outEvent->data2 += (screen->GetTrueHeight() - screen->VideoHeight) / 2;
screen->ScaleCoordsFromWindow(outEvent->data1, outEvent->data2);
}
void ProcessMouseMoveInMenu(NSEvent* theEvent)

View file

@ -115,9 +115,6 @@ CUSTOM_CVAR(Bool, vid_autoswitch, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_
EXTERN_CVAR(Bool, gl_smooth_rendered)
RenderBufferOptions rbOpts;
// ---------------------------------------------------------------------------
@ -544,20 +541,6 @@ void CocoaVideo::SetFullscreenMode(const int width, const int height)
? [screen convertRectToBacking:screenFrame]
: screenFrame;
const float displayWidth = displayRect.size.width;
const float displayHeight = displayRect.size.height;
const float pixelScaleFactorX = displayWidth / static_cast<float>(width );
const float pixelScaleFactorY = displayHeight / static_cast<float>(height);
rbOpts.pixelScale = MIN(pixelScaleFactorX, pixelScaleFactorY);
rbOpts.width = width * rbOpts.pixelScale;
rbOpts.height = height * rbOpts.pixelScale;
rbOpts.shiftX = (displayWidth - rbOpts.width ) / 2.0f;
rbOpts.shiftY = (displayHeight - rbOpts.height) / 2.0f;
if (!m_fullscreen)
{
[m_window setLevel:LEVEL_FULLSCREEN];
@ -571,14 +554,6 @@ void CocoaVideo::SetFullscreenMode(const int width, const int height)
void CocoaVideo::SetWindowedMode(const int width, const int height)
{
rbOpts.pixelScale = 1.0f;
rbOpts.width = static_cast<float>(width );
rbOpts.height = static_cast<float>(height);
rbOpts.shiftX = 0.0f;
rbOpts.shiftY = 0.0f;
const NSSize windowPixelSize = NSMakeSize(width, height);
const NSSize windowSize = vid_hidpi
? [[m_window contentView] convertSizeFromBacking:windowPixelSize]
@ -621,8 +596,6 @@ void CocoaVideo::SetMode(const int width, const int height, const bool fullscree
SetWindowedMode(width, height);
}
rbOpts.dirty = true;
const NSSize viewSize = I_GetContentViewSize(m_window);
glViewport(0, 0, static_cast<GLsizei>(viewSize.width), static_cast<GLsizei>(viewSize.height));

View file

@ -94,7 +94,7 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s
if (smf->flags & MDL_ROTATING)
{
if (smf->rotationSpeed > 0.0000000001)
if (smf->rotationSpeed > 0.0000000001 || smf->rotationSpeed < -0.0000000001)
{
double turns = (I_GetTime() + I_GetTimeFrac()) / (200.0 / smf->rotationSpeed);
turns -= floor(turns);
@ -171,7 +171,9 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s
float stretch = (smf->modelIDs[0] != -1 ? Models[smf->modelIDs[0]]->getAspectFactor() : 1.f) / level.info->pixelstretch;
objectToWorldMatrix.scale(1, stretch, 1);
BeginDrawModel(actor, smf, objectToWorldMatrix);
float orientation = scaleFactorX * scaleFactorY * scaleFactorZ;
BeginDrawModel(actor, smf, objectToWorldMatrix, orientation < 0);
RenderFrameModels(smf, actor->state, actor->tics, actor->GetClass(), translation);
EndDrawModel(actor, smf);
}
@ -207,7 +209,9 @@ void FModelRenderer::RenderHUDModel(DPSprite *psp, float ofsX, float ofsY)
objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1);
objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0);
BeginDrawHUDModel(playermo, objectToWorldMatrix);
float orientation = smf->xscale * smf->yscale * smf->zscale;
BeginDrawHUDModel(playermo, objectToWorldMatrix, orientation < 0);
RenderFrameModels(smf, psp->GetState(), psp->GetTics(), playermo->player->ReadyWeapon->GetClass(), 0);
EndDrawHUDModel(playermo);
}

View file

@ -64,7 +64,7 @@ public:
virtual ModelRendererType GetType() const = 0;
virtual void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) = 0;
virtual void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) = 0;
virtual void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) = 0;
virtual IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) = 0;
@ -74,7 +74,7 @@ public:
virtual VSMatrix GetViewToWorldMatrix() = 0;
virtual void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) = 0;
virtual void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored) = 0;
virtual void EndDrawHUDModel(AActor *actor) = 0;
virtual void SetInterpolation(double interpolation) = 0;

View file

@ -40,6 +40,7 @@
#include "v_text.h"
#include "w_wad.h"
#include "w_zip.h"
#include "i_system.h"
#include "ancientzip.h"
#define BUFREADCOMMENT (0x400)

View file

@ -316,6 +316,7 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF7, FORCEINFIGHTING, AActor, flags7),
DEFINE_FLAG(MF8, FRIGHTENING, AActor, flags8),
DEFINE_FLAG(MF8, BLOCKASPLAYER, AActor, flags8),
// Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),

View file

@ -272,7 +272,7 @@ namespace swrenderer
void Execute(DrawerThread *thread) override
{
auto zbuffer = PolyZBuffer::Instance();
int pitch = PolyStencilBuffer::Instance()->BlockWidth() * 8;
int pitch = PolyStencilBuffer::Instance()->Width();
float *values = zbuffer->Values() + y * pitch + x;
int cnt = count;
@ -316,7 +316,7 @@ namespace swrenderer
return;
auto zbuffer = PolyZBuffer::Instance();
int pitch = PolyStencilBuffer::Instance()->BlockWidth() * 8;
int pitch = PolyStencilBuffer::Instance()->Width();
float *values = zbuffer->Values() + y * pitch;
int end = x2;

View file

@ -259,7 +259,7 @@ namespace swrenderer
thread->OpaquePass->ResetFakingUnderwater(); // [RH] Hack to make windows into underwater areas possible
thread->Portal->SetMainPortal();
PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget, true);
PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget);
// Cull things outside the range seen by this thread
VisibleSegmentRenderer visitor;

View file

@ -82,7 +82,7 @@ namespace swrenderer
{
}
void SWModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix)
void SWModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored)
{
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.Matrix);
@ -123,12 +123,14 @@ namespace swrenderer
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES))
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !mirrored);
}
void SWModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
{
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES))
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, true);
ModelActor = nullptr;
}
@ -181,7 +183,7 @@ namespace swrenderer
return objectToWorld;
}
void SWModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix)
void SWModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored)
{
ModelActor = actor;
const_cast<VSMatrix &>(objectToWorldMatrix).copy(ObjectToWorld.Matrix);
@ -192,6 +194,7 @@ namespace swrenderer
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal])
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, mirrored);
}
void SWModelRenderer::EndDrawHUDModel(AActor *actor)
@ -201,6 +204,7 @@ namespace swrenderer
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal])
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, false);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, true);
}
void SWModelRenderer::SetInterpolation(double interpolation)

View file

@ -56,13 +56,13 @@ namespace swrenderer
ModelRendererType GetType() const override { return SWModelRendererType; }
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;
void SetVertexBuffer(IModelVertexBuffer *buffer) override;
void ResetVertexBuffer() override;
VSMatrix GetViewToWorldMatrix() override;
void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix) override;
void BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored) override;
void EndDrawHUDModel(AActor *actor) override;
void SetInterpolation(double interpolation) override;
void SetMaterial(FTexture *skin, bool clampNoFilter, int translation) override;

View file

@ -323,12 +323,16 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
// Convert a light level into an unbounded colormap index (shade).
// Why the +12? I wish I knew, but experimentation indicates it
// is necessary in order to best reproduce Doom's original lighting.
double map = (NUMCOLORMAPS * 2.) - ((lightlevel + 12) * (NUMCOLORMAPS / 128.));
double fadelevel = clamp((map - 12) / NUMCOLORMAPS, 0.0, 1.0);
// handle the brighter light modes of the hardware renderer.
if (vid_rendermode == 4 && (level.lightmode < 2 || level.lightmode == 4))
double fadelevel;
if (vid_rendermode != 4 || (level.lightmode >= 2 && level.lightmode != 4))
{
fadelevel = pow(fadelevel, 1.3);
double map = (NUMCOLORMAPS * 2.) - ((lightlevel + 12) * (NUMCOLORMAPS / 128.));
fadelevel = clamp((map - 12) / NUMCOLORMAPS, 0.0, 1.0);
}
else
{
fadelevel = 1. - clamp(lightlevel, 0, 255) / 255.f;
}
RenderCommand poly;

View file

@ -1005,7 +1005,7 @@ void DFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int width, i
//
//==========================================================================
void DFrameBuffer::SetOutputViewport(IntRect *bounds)
void DFrameBuffer::SetViewportRects(IntRect *bounds)
{
if (bounds)
{

View file

@ -501,7 +501,7 @@ public:
// Calculate gamma table
void CalcGamma(float gamma, uint8_t gammalookup[256]);
virtual void SetOutputViewport(IntRect *bounds);
virtual void SetViewportRects(IntRect *bounds);
int ScreenToWindowX(int x);
int ScreenToWindowY(int y);

View file

@ -65,7 +65,7 @@ extend class Actor
damage *= 10;
double ang = angle + Random2[Punch]() * (5.625 / 256);
double pitch = AimLineAttack (ang, DEFMELEERANGE);
double pitch = AimLineAttack (ang, DEFMELEERANGE, null, 0., ALF_CHECK3D);
LineAttack (ang, DEFMELEERANGE, pitch, damage, 'Melee', "BulletPuff", LAF_ISMELEEATTACK, t);

View file

@ -66,7 +66,7 @@ class CWeapMace : ClericWeapon
for (int j = 1; j >= -1; j -= 2)
{
double ang = angle + j*i*(45. / 16);
double slope = AimLineAttack(ang, 2 * DEFMELEERANGE, t);
double slope = AimLineAttack(ang, 2 * DEFMELEERANGE, t, 0., ALF_CHECK3D);
if (t.linetarget)
{
LineAttack(ang, 2 * DEFMELEERANGE, slope, damage, 'Melee', "HammerPuff", true, t);
@ -81,7 +81,7 @@ class CWeapMace : ClericWeapon
// didn't find any creatures, so try to strike any walls
weaponspecial = 0;
double slope = AimLineAttack (angle, DEFMELEERANGE);
double slope = AimLineAttack (angle, DEFMELEERANGE, null, 0., ALF_CHECK3D);
LineAttack (angle, DEFMELEERANGE, slope, damage, 'Melee', "HammerPuff");
}
}

View file

@ -245,7 +245,7 @@ class FWeapAxe : FighterWeapon
for (int j = 1; j >= -1; j -= 2)
{
double ang = angle + j*i*(45. / 16);
double slope = AimLineAttack(ang, AXERANGE, t);
double slope = AimLineAttack(ang, AXERANGE, t, 0., ALF_CHECK3D);
if (t.linetarget)
{
LineAttack(ang, AXERANGE, slope, damage, 'Melee', pufftype, true, t);
@ -273,7 +273,7 @@ class FWeapAxe : FighterWeapon
// didn't find any creatures, so try to strike any walls
self.weaponspecial = 0;
double slope = AimLineAttack (angle, DEFMELEERANGE);
double slope = AimLineAttack (angle, DEFMELEERANGE, null, 0., ALF_CHECK3D);
LineAttack (angle, DEFMELEERANGE, slope, damage, 'Melee', pufftype, true);
}
}

View file

@ -56,7 +56,7 @@ class FWeapFist : FighterWeapon
Class<Actor> pufftype;
FTranslatedLineTarget t;
double slope = AimLineAttack (angle, 2*DEFMELEERANGE, t);
double slope = AimLineAttack (angle, 2*DEFMELEERANGE, t, 0., ALF_CHECK3D);
if (t.linetarget != null)
{
if (++weaponspecial >= 3)
@ -117,7 +117,7 @@ class FWeapFist : FighterWeapon
// didn't find any creatures, so try to strike any walls
weaponspecial = 0;
double slope = AimLineAttack (angle, DEFMELEERANGE);
double slope = AimLineAttack (angle, DEFMELEERANGE, null, 0., ALF_CHECK3D);
LineAttack (angle, DEFMELEERANGE, slope, damage, 'Melee', "PunchPuff", true);
}