mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-12-03 08:52:59 +00:00
Cube and dome sky modes
This commit is contained in:
parent
7a9c674f83
commit
cdf8264dc3
1 changed files with 250 additions and 0 deletions
250
src/r_plane.cpp
250
src/r_plane.cpp
|
@ -58,6 +58,7 @@
|
|||
#include "r_3dfloors.h"
|
||||
#include "v_palette.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "r_triangle.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244)
|
||||
|
@ -900,6 +901,245 @@ static const BYTE *R_GetTwoSkyColumns (FTexture *fronttex, int x)
|
|||
return composite;
|
||||
}
|
||||
|
||||
static void R_DrawCubeSky(visplane_t *pl)
|
||||
{
|
||||
int x1 = pl->left;
|
||||
int x2 = pl->right;
|
||||
short *uwal = (short *)pl->top;
|
||||
short *dwal = (short *)pl->bottom;
|
||||
|
||||
static TriVertex cube[6 * 6] =
|
||||
{
|
||||
// Top
|
||||
{ -1.0f, 1.0f, 0.6f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, 1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 0.6f, 1.0f, 0.0f, 0.1f, 1.0f },
|
||||
|
||||
{ 1.0f, -1.0f, 0.6f, 1.0f, 0.0f, 0.1f, 1.0f },
|
||||
{ -1.0f, -1.0f, 0.6f, 1.0f, 1.0f, 0.1f, 1.0f },
|
||||
{ -1.0f, 1.0f, 0.6f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
|
||||
// Bottom
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.9f, 1.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
|
||||
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.9f, 1.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.9f, 1.0f },
|
||||
|
||||
// Front
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 2.0f, 1.0f },
|
||||
{ 1.0f, 1.0f, 0.6f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 1.0f },
|
||||
|
||||
{ -1.0f, 1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 2.0f, 1.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 2.0f, 1.0f },
|
||||
|
||||
// Back
|
||||
{ -1.0f, -1.0f, 0.6f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 2.0f, 1.0f },
|
||||
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 2.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 2.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, 0.6f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
|
||||
// Right
|
||||
{ 1.0f, -1.0f, 0.6f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, 1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 2.0f, 1.0f },
|
||||
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 2.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 2.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 0.6f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
|
||||
// Left
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 2.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, 0.6f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 1.0f },
|
||||
|
||||
{ -1.0f, -1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 2.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 2.0f, 1.0f }
|
||||
};
|
||||
|
||||
TriMatrix objectToWorld = TriMatrix::translate((float)ViewPos.X, (float)ViewPos.Y, (float)ViewPos.Z) * TriMatrix::scale(1000.0f, 1000.0f, 1000.0f);
|
||||
|
||||
uint32_t solid_top = frontskytex->GetSkyCapColor(false);
|
||||
uint32_t solid_bottom = frontskytex->GetSkyCapColor(true);
|
||||
|
||||
solid_top = RGB32k.RGB[(RPART(solid_top) >> 3)][(GPART(solid_top) >> 3)][(BPART(solid_top) >> 3)];
|
||||
solid_bottom = RGB32k.RGB[(RPART(solid_bottom) >> 3)][(GPART(solid_bottom) >> 3)][(BPART(solid_bottom) >> 3)];
|
||||
|
||||
TriangleDrawer::fill(objectToWorld, cube, 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, solid_top);
|
||||
TriangleDrawer::fill(objectToWorld, cube + 6, 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, solid_bottom);
|
||||
TriangleDrawer::draw(objectToWorld, cube + 2 * 6, 4 * 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, frontskytex);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class SkyDome
|
||||
{
|
||||
public:
|
||||
SkyDome() { CreateDome(); }
|
||||
void Render(visplane_t *pl);
|
||||
|
||||
private:
|
||||
TArray<TriVertex> mVertices;
|
||||
TArray<unsigned int> mPrimStart;
|
||||
int mRows, mColumns;
|
||||
|
||||
void SkyVertex(int r, int c, bool yflip);
|
||||
void CreateSkyHemisphere(bool zflip);
|
||||
void CreateDome();
|
||||
void RenderRow(int row, visplane_t *pl);
|
||||
void RenderCapColorRow(int row, bool bottomCap, visplane_t *pl);
|
||||
|
||||
TriVertex SetVertex(float xx, float yy, float zz, float uu = 0, float vv = 0);
|
||||
TriVertex SetVertexXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0);
|
||||
};
|
||||
|
||||
TriVertex SkyDome::SetVertex(float xx, float yy, float zz, float uu, float vv)
|
||||
{
|
||||
TriVertex v;
|
||||
v.x = xx;
|
||||
v.y = yy;
|
||||
v.z = zz;
|
||||
v.w = 1.0f;
|
||||
v.varying[0] = uu;
|
||||
v.varying[1] = vv;
|
||||
v.varying[2] = 1.0f;
|
||||
return v;
|
||||
}
|
||||
|
||||
TriVertex SkyDome::SetVertexXYZ(float xx, float yy, float zz, float uu, float vv)
|
||||
{
|
||||
TriVertex v;
|
||||
v.x = xx;
|
||||
v.y = zz;
|
||||
v.z = yy;
|
||||
v.w = 1.0f;
|
||||
v.varying[0] = uu;
|
||||
v.varying[1] = vv;
|
||||
v.varying[2] = 1.0f;
|
||||
return v;
|
||||
}
|
||||
|
||||
void SkyDome::SkyVertex(int r, int c, bool zflip)
|
||||
{
|
||||
static const FAngle maxSideAngle = 60.f;
|
||||
static const float scale = 10000.;
|
||||
|
||||
FAngle topAngle = (c / (float)mColumns * 360.f);
|
||||
FAngle sideAngle = maxSideAngle * (mRows - r) / mRows;
|
||||
float height = sideAngle.Sin();
|
||||
float realRadius = scale * sideAngle.Cos();
|
||||
FVector2 pos = topAngle.ToVector(realRadius);
|
||||
float z = (!zflip) ? scale * height : -scale * height;
|
||||
|
||||
float u, v;
|
||||
//uint32_t color = r == 0 ? 0xffffff : 0xffffffff;
|
||||
|
||||
// And the texture coordinates.
|
||||
if (!zflip) // Flipped Y is for the lower hemisphere.
|
||||
{
|
||||
u = (-c / (float)mColumns);
|
||||
v = (r / (float)mRows);
|
||||
}
|
||||
else
|
||||
{
|
||||
u = (-c / (float)mColumns);
|
||||
v = 1.0f + ((mRows - r) / (float)mRows);
|
||||
}
|
||||
|
||||
if (r != 4) z += 300;
|
||||
|
||||
// And finally the vertex.
|
||||
TriVertex vert;
|
||||
vert = SetVertexXYZ(-pos.X, z - 1.f, pos.Y, u * 4.0f, v + 0.5f/*, color*/);
|
||||
mVertices.Push(vert);
|
||||
}
|
||||
|
||||
void SkyDome::CreateSkyHemisphere(bool zflip)
|
||||
{
|
||||
int r, c;
|
||||
|
||||
mPrimStart.Push(mVertices.Size());
|
||||
|
||||
for (c = 0; c < mColumns; c++)
|
||||
{
|
||||
SkyVertex(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());
|
||||
for (c = 0; c <= mColumns; c++)
|
||||
{
|
||||
SkyVertex(r + zflip, c, zflip);
|
||||
SkyVertex(r + 1 - zflip, c, zflip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkyDome::CreateDome()
|
||||
{
|
||||
mColumns = 128;
|
||||
mRows = 4;
|
||||
CreateSkyHemisphere(false);
|
||||
CreateSkyHemisphere(true);
|
||||
mPrimStart.Push(mVertices.Size());
|
||||
}
|
||||
|
||||
void SkyDome::RenderRow(int row, visplane_t *pl)
|
||||
{
|
||||
int x1 = pl->left;
|
||||
int x2 = pl->right;
|
||||
short *uwal = (short *)pl->top;
|
||||
short *dwal = (short *)pl->bottom;
|
||||
TriMatrix objectToWorld = TriMatrix::translate((float)ViewPos.X, (float)ViewPos.Y, (float)ViewPos.Z);
|
||||
TriangleDrawer::draw(objectToWorld, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], TriangleDrawMode::Strip, false, x1, x2 - 1, uwal, dwal, frontskytex);
|
||||
}
|
||||
|
||||
void SkyDome::RenderCapColorRow(int row, bool bottomCap, visplane_t *pl)
|
||||
{
|
||||
uint32_t solid = frontskytex->GetSkyCapColor(bottomCap);
|
||||
solid = RGB32k.RGB[(RPART(solid) >> 3)][(GPART(solid) >> 3)][(BPART(solid) >> 3)];
|
||||
|
||||
int x1 = pl->left;
|
||||
int x2 = pl->right;
|
||||
short *uwal = (short *)pl->top;
|
||||
short *dwal = (short *)pl->bottom;
|
||||
TriMatrix objectToWorld = TriMatrix::translate((float)ViewPos.X, (float)ViewPos.Y, (float)ViewPos.Z);
|
||||
TriangleDrawer::fill(objectToWorld, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], TriangleDrawMode::Fan, bottomCap, x1, x2 - 1, uwal, dwal, solid);
|
||||
}
|
||||
|
||||
void SkyDome::Render(visplane_t *pl)
|
||||
{
|
||||
int rc = mRows + 1;
|
||||
|
||||
// No need to draw this as the software renderer can't look that high anyway
|
||||
//RenderCapColorRow(0, false, pl);
|
||||
//RenderCapColorRow(rc, true, pl);
|
||||
|
||||
for (int i = 1; i <= mRows; i++)
|
||||
{
|
||||
RenderRow(i, pl);
|
||||
RenderRow(rc + i, pl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void R_DrawDomeSky(visplane_t *pl)
|
||||
{
|
||||
static SkyDome skydome;
|
||||
skydome.Render(pl);
|
||||
}
|
||||
|
||||
static void R_DrawSkyColumnStripe(int start_x, int y1, int y2, int columns, double scale, double texturemid, double yrepeat)
|
||||
{
|
||||
uint32_t height = frontskytex->GetHeight();
|
||||
|
@ -1064,6 +1304,16 @@ static void R_DrawSky (visplane_t *pl)
|
|||
R_DrawCapSky(pl);
|
||||
return;
|
||||
}
|
||||
else if (r_skymode == 3)
|
||||
{
|
||||
R_DrawCubeSky(pl);
|
||||
return;
|
||||
}
|
||||
else if (r_skymode == 4)
|
||||
{
|
||||
R_DrawDomeSky(pl);
|
||||
return;
|
||||
}
|
||||
|
||||
int x;
|
||||
float swal;
|
||||
|
|
Loading…
Reference in a new issue