- better handling for Duke's scrolling cloudy skies.

* Using the Doom-style dome here because it looks better.
* this necessitated changes to the backend to allow both types of sky domes at the same time
* do not clamp panning fields for cloudy sky with the new renderer because this makes the texture jump.
This commit is contained in:
Christoph Oelckers 2021-04-04 20:35:38 +02:00
parent 39c457bbf2
commit c303884274
9 changed files with 113 additions and 36 deletions

View file

@ -3,7 +3,7 @@
//ceilingstat/floorstat:
// bit 0: 1 = parallaxing, 0 = not "P"
// bit 1: 1 = groudraw, 0 = not
// bit 1: 1 = sloped, 0 = not
// bit 2: 1 = swap x&y, 0 = not "F"
// bit 3: 1 = double smooshiness "E"
// bit 4: 1 = x-flip "F"
@ -17,7 +17,8 @@
// bit 9: 1 = blocking ceiling/floor
// bit 10: 1 = YAX'ed ceiling/floor
// bit 11: 1 = hitscan-sensitive ceiling/floor
// bits 12-15: reserved
// bits 12-14: reserved
// bit 15: SW: block FAF hitscans
//////////////////// Version 7 map format ////////////////////
enum
@ -32,6 +33,8 @@ enum
CSTAT_SECTOR_TRANS = 128,
CSTAT_SECTOR_TRANS_INVERT = 256,
CSTAT_SECTOR_METHOD = 384,
SECTOREX_CLOUDSCROLL = 1,
};
enum
@ -67,6 +70,7 @@ struct sectortype
int16_t extra;
uint8_t dirty;
uint8_t exflags;
float ceilingxpan_, ceilingypan_, floorxpan_, floorypan_;
uint8_t portalflags;
int8_t portalnum;

View file

@ -140,11 +140,11 @@ FSkyVertexBuffer::~FSkyVertexBuffer()
//-----------------------------------------------------------------------------
//
// todo: make both available at the same time.
//
//
//-----------------------------------------------------------------------------
#ifndef BUILD_SKY
void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
void FSkyVertexBuffer::SkyVertexDoom(int r, int c, bool zflip)
{
static const FAngle maxSideAngle = 60.f;
static const float scale = 10000.;
@ -180,8 +180,14 @@ void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
mVertices.Push(vert);
}
#else
void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::SkyVertexBuild(int r, int c, bool zflip)
{
static const FAngle maxSideAngle = 60.f;
static const float scale = 10000.;
@ -206,34 +212,65 @@ void FSkyVertexBuffer::SkyVertex(int r, int c, bool zflip)
mVertices.Push(vert);
}
#endif
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::CreateSkyHemisphere(int hemi)
void FSkyVertexBuffer::CreateSkyHemisphereDoom(int hemi)
{
int r, c;
bool zflip = !!(hemi & SKYHEMI_LOWER);
mPrimStart.Push(mVertices.Size());
mPrimStartDoom.Push(mVertices.Size());
for (c = 0; c < mColumns; c++)
{
SkyVertex(1, c, zflip);
SkyVertexDoom(1, c, zflip);
}
// The total number of triangles per hemisphere can be calculated
// as follows: rows * columns * 2 + 2 (for the top cap).
for (r = 0; r < mRows; r++)
{
mPrimStart.Push(mVertices.Size());
mPrimStartDoom.Push(mVertices.Size());
for (c = 0; c <= mColumns; c++)
{
SkyVertex(r + zflip, c, zflip);
SkyVertex(r + 1 - zflip, c, zflip);
SkyVertexDoom(r + zflip, c, zflip);
SkyVertexDoom(r + 1 - zflip, c, zflip);
}
}
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::CreateSkyHemisphereBuild(int hemi)
{
int r, c;
bool zflip = !!(hemi & SKYHEMI_LOWER);
mPrimStartBuild.Push(mVertices.Size());
for (c = 0; c < mColumns; c++)
{
SkyVertexBuild(1, c, zflip);
}
// The total number of triangles per hemisphere can be calculated
// as follows: rows * columns * 2 + 2 (for the top cap).
for (r = 0; r < mRows; r++)
{
mPrimStartBuild.Push(mVertices.Size());
for (c = 0; c <= mColumns; c++)
{
SkyVertexBuild(r + zflip, c, zflip);
SkyVertexBuild(r + 1 - zflip, c, zflip);
}
}
}
@ -267,9 +304,13 @@ void FSkyVertexBuffer::CreateDome()
mColumns = 128;
mRows = 4;
CreateSkyHemisphere(SKYHEMI_UPPER);
CreateSkyHemisphere(SKYHEMI_LOWER);
mPrimStart.Push(mVertices.Size());
CreateSkyHemisphereDoom(SKYHEMI_UPPER);
CreateSkyHemisphereDoom(SKYHEMI_LOWER);
mPrimStartDoom.Push(mVertices.Size());
CreateSkyHemisphereBuild(SKYHEMI_UPPER);
CreateSkyHemisphereBuild(SKYHEMI_LOWER);
mPrimStartBuild.Push(mVertices.Size());
mSideStart = mVertices.Size();
mFaceStart[0] = mSideStart + 10;
@ -401,7 +442,7 @@ void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::RenderRow(FRenderState& state, EDrawType prim, int row, bool apply)
void FSkyVertexBuffer::RenderRow(FRenderState& state, EDrawType prim, int row, TArray<unsigned int>& mPrimStart, bool apply)
{
state.Draw(prim, mPrimStart[row], mPrimStart[row + 1] - mPrimStart[row]);
}
@ -412,8 +453,9 @@ void FSkyVertexBuffer::RenderRow(FRenderState& state, EDrawType prim, int row, b
//
//-----------------------------------------------------------------------------
void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, int mode)
void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which)
{
auto& primStart = which ? mPrimStartBuild : mPrimStartDoom;
if (tex && tex->isValid())
{
state.SetMaterial(tex, UF_Texture, 0, CLAMP_NONE, 0, -1);
@ -429,17 +471,17 @@ void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, int mo
auto& col = R_GetSkyCapColor(tex);
state.SetObjectColor(col.first);
state.EnableTexture(false);
RenderRow(state, DT_TriangleFan, 0);
RenderRow(state, DT_TriangleFan, 0, primStart);
state.SetObjectColor(col.second);
RenderRow(state, DT_TriangleFan, rc);
RenderRow(state, DT_TriangleFan, rc, primStart);
state.EnableTexture(true);
}
state.SetObjectColor(0xffffffff);
for (int i = 1; i <= mRows; i++)
{
RenderRow(state, DT_TriangleStrip, i, i == 1);
RenderRow(state, DT_TriangleStrip, rc + i, false);
RenderRow(state, DT_TriangleStrip, i, primStart, i == 1);
RenderRow(state, DT_TriangleStrip, rc + i, primStart, false);
}
state.EnableTextureMatrix(false);
@ -449,7 +491,7 @@ void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, int mo
//-----------------------------------------------------------------------------
//
//
// This is only for Doom-style skies.
//
//-----------------------------------------------------------------------------
@ -459,7 +501,7 @@ void FSkyVertexBuffer::RenderDome(FRenderState& state, FGameTexture* tex, float
{
SetupMatrices(tex, x_offset, y_offset, mirror, mode, state.mModelMatrix, state.mTextureMatrix, tiled, xscale, yscale);
}
RenderDome(state, tex, mode);
RenderDome(state, tex, mode, false);
}

View file

@ -61,7 +61,8 @@ public:
IVertexBuffer *mVertexBuffer;
TArray<FSkyVertex> mVertices;
TArray<unsigned int> mPrimStart;
TArray<unsigned int> mPrimStartDoom;
TArray<unsigned int> mPrimStartBuild;
int mRows, mColumns;
@ -69,8 +70,10 @@ public:
int mFaceStart[7];
int mSideStart;
void SkyVertex(int r, int c, bool yflip);
void CreateSkyHemisphere(int hemi);
void SkyVertexDoom(int r, int c, bool yflip);
void SkyVertexBuild(int r, int c, bool yflip);
void CreateSkyHemisphereDoom(int hemi);
void CreateSkyHemisphereBuild(int hemi);
void CreateDome();
public:
@ -89,8 +92,8 @@ public:
else return mSideStart;
}
void RenderRow(FRenderState& state, EDrawType prim, int row, bool apply = true);
void RenderDome(FRenderState& state, FGameTexture* tex, int mode);
void RenderRow(FRenderState& state, EDrawType prim, int row, TArray<unsigned int>& mPrimStart, bool apply = true);
void RenderDome(FRenderState& state, FGameTexture* tex, int mode, bool which);
void RenderDome(FRenderState& state, FGameTexture* tex, float x_offset, float y_offset, bool mirror, int mode, bool tiled, float xscale = 0, float yscale = 0);
void RenderBox(FRenderState& state, FSkyBox* tex, float x_offset, bool sky2, float stretch, const FVector3& skyrotatevector, const FVector3& skyrotatevector2);

View file

@ -483,6 +483,7 @@ void setWallSectors()
for (int i = 0; i < numsectors; i++)
{
sector[i].dirty = 255;
sector[i].exflags = 0;
for (int w = 0; w < sector[i].wallnum; w++)
{
wall[sector[i].wallptr + w].sector = i;

View file

@ -23,6 +23,7 @@ struct HWSkyInfo
float y_offset;
float y_scale;
int shade;
bool cloudy;
FGameTexture * texture;
PalEntry fadecolor;

View file

@ -63,11 +63,21 @@ void initSkyInfo(HWDrawInfo *di, HWSkyInfo* sky, sectortype* sector, int plane,
}
float xpanning = plane == plane_ceiling ? sector->ceilingxpan_ : sector->floorxpan_;
float ypanning = plane == plane_ceiling ? sector->ceilingypan_ : sector->floorypan_;
// dapyscale is not relvant for a sky dome.
sky->y_scale = FixedToFloat(daptileyscale);
sky->y_offset = dapyoffs*1.5;
sky->x_offset = xpanning / (1 << (realskybits - dapskybits));
sky->cloudy = !!(sector->exflags & SECTOREX_CLOUDSCROLL);
if (!sky->cloudy)
{
sky->y_offset = dapyoffs * 1.5;
sky->x_offset = xpanning / (1 << (realskybits - dapskybits));
}
else
{
sky->y_offset = ypanning;
sky->x_offset = 2 * xpanning / (1 << (realskybits - dapskybits));
}
sky->fadecolor = FadeColor;
sky->shade = 0;// clamp(plane == plane_ceiling ? sector->ceilingshade : sector->floorshade, 0, numshades - 1);
sky->texture = skytex;

View file

@ -58,7 +58,7 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
{
vertexBuffer->RenderBox(state, skybox, origin->x_offset, false, /*di->Level->info->pixelstretch*/1, { 0, 0, 1 }, { 0, 0, 1 });
}
else
else if (!origin->cloudy)
{
auto tex = origin->texture;
float texw = tex->GetDisplayWidth();
@ -81,9 +81,13 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
textureMatrix.loadIdentity();
state.EnableTextureMatrix(true);
textureMatrix.scale(1.f, repeat_fac, 1.f);
vertexBuffer->RenderDome(state, origin->texture, FSkyVertexBuffer::SKYMODE_MAINLAYER);
vertexBuffer->RenderDome(state, origin->texture, FSkyVertexBuffer::SKYMODE_MAINLAYER, true);
state.EnableTextureMatrix(false);
}
else
{
vertexBuffer->RenderDome(state, origin->texture, -origin->x_offset, origin->y_offset, false, FSkyVertexBuffer::SKYMODE_MAINLAYER, true);
}
state.SetTextureMode(TM_NORMAL);
if (origin->fadecolor & 0xffffff)
{

View file

@ -660,6 +660,8 @@ void dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, shor
pSector->floorypan_ = load.floorypanning;
pSector->visibility = load.visibility;
qsector_filler[i] = load.fogpal;
pSector->dirty = 255;
pSector->exflags = 0;
pSector->fogpal = 0;
if (sector[i].extra > 0)

View file

@ -1271,8 +1271,18 @@ void moveclouds(double smoothratio)
cloudy += ps[screenpeek].angle.ang.fsin() * 0.5f;
for (int i = 0; i < numclouds; i++)
{
sector[clouds[i]].setceilingxpan(cloudx);
sector[clouds[i]].setceilingypan(cloudy);
if (!testnewrenderer)
{
sector[clouds[i]].setceilingxpan(cloudx);
sector[clouds[i]].setceilingypan(cloudy);
}
else
{
// no clamping here!
sector[clouds[i]].ceilingxpan_ = cloudx;
sector[clouds[i]].ceilingypan_ = cloudy;
}
sector[clouds[i]].exflags |= SECTOREX_CLOUDSCROLL;
}
}
}