Fix sky transition

This commit is contained in:
Magnus Norddahl 2019-12-07 21:17:11 +01:00
parent 90f5eee6c6
commit bb64b178e1
6 changed files with 141 additions and 96 deletions

View file

@ -98,20 +98,17 @@ void PolyVertexInputAssembly::Load(PolyTriangleThreadData *thread, const void *v
if ((UseVertexData & 1) == 0)
{
const auto &c = thread->mainVertexShader.Data.uVertexColor;
thread->mainVertexShader.aColor = MAKEARGB(
static_cast<uint32_t>(c.W * 255.0f + 0.5f),
static_cast<uint32_t>(c.X * 255.0f + 0.5f),
static_cast<uint32_t>(c.Y * 255.0f + 0.5f),
static_cast<uint32_t>(c.Z * 255.0f + 0.5f)
);
thread->mainVertexShader.aColor.X = c.X;
thread->mainVertexShader.aColor.Y = c.Y;
thread->mainVertexShader.aColor.Z = c.Z;
thread->mainVertexShader.aColor.W = c.W;
}
else
{
uint32_t r = attrColor[0];
uint32_t g = attrColor[1];
uint32_t b = attrColor[2];
uint32_t a = attrColor[3];
thread->mainVertexShader.aColor = MAKEARGB(a, r, g, b);
thread->mainVertexShader.aColor.X = attrColor[0] * (1.0f / 255.0f);
thread->mainVertexShader.aColor.Y = attrColor[1] * (1.0f / 255.0f);
thread->mainVertexShader.aColor.Z = attrColor[2] * (1.0f / 255.0f);
thread->mainVertexShader.aColor.W = attrColor[3] * (1.0f / 255.0f);
}
if ((UseVertexData & 2) == 0)

View file

@ -414,8 +414,6 @@ void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode dra
elements += index;
TriDrawTriangleArgs args;
ShadedTriVertex vertbuffer[3];
ShadedTriVertex *vert[3] = { &vertbuffer[0], &vertbuffer[1], &vertbuffer[2] };
if (drawmode == PolyDrawMode::Triangles)
@ -424,7 +422,7 @@ void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode dra
{
for (int j = 0; j < 3; j++)
*vert[j] = ShadeVertex(*(elements++));
DrawShadedTriangle(vert, ccw, &args);
DrawShadedTriangle(vert, ccw);
}
}
else if (drawmode == PolyDrawMode::TriangleFan)
@ -434,7 +432,7 @@ void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode dra
for (int i = 2; i < vcount; i++)
{
*vert[2] = ShadeVertex(*(elements++));
DrawShadedTriangle(vert, ccw, &args);
DrawShadedTriangle(vert, ccw);
std::swap(vert[1], vert[2]);
}
}
@ -446,7 +444,7 @@ void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode dra
for (int i = 2; i < vcount; i++)
{
*vert[2] = ShadeVertex(*(elements++));
DrawShadedTriangle(vert, toggleccw, &args);
DrawShadedTriangle(vert, toggleccw);
ShadedTriVertex *vtmp = vert[0];
vert[0] = vert[1];
vert[1] = vert[2];
@ -478,8 +476,6 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode)
if (vcount < 3)
return;
TriDrawTriangleArgs args;
int vinput = index;
ShadedTriVertex vertbuffer[3];
@ -490,7 +486,7 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode)
{
for (int j = 0; j < 3; j++)
*vert[j] = ShadeVertex(vinput++);
DrawShadedTriangle(vert, ccw, &args);
DrawShadedTriangle(vert, ccw);
}
}
else if (drawmode == PolyDrawMode::TriangleFan)
@ -500,7 +496,7 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode)
for (int i = 2; i < vcount; i++)
{
*vert[2] = ShadeVertex(vinput++);
DrawShadedTriangle(vert, ccw, &args);
DrawShadedTriangle(vert, ccw);
std::swap(vert[1], vert[2]);
}
}
@ -512,7 +508,7 @@ void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode)
for (int i = 2; i < vcount; i++)
{
*vert[2] = ShadeVertex(vinput++);
DrawShadedTriangle(vert, toggleccw, &args);
DrawShadedTriangle(vert, toggleccw);
ShadedTriVertex *vtmp = vert[0];
vert[0] = vert[1];
vert[1] = vert[2];
@ -623,11 +619,6 @@ void PolyTriangleThreadData::DrawShadedLine(const ShadedTriVertex *const* vert)
v.y += vert[w]->gl_Position.Y * weight;
v.z += vert[w]->gl_Position.Z * weight;
v.w += vert[w]->gl_Position.W * weight;
v.u += vert[w]->vTexCoord.X * weight;
v.v += vert[w]->vTexCoord.Y * weight;
v.worldX += vert[w]->pixelpos.X * weight;
v.worldY += vert[w]->pixelpos.Y * weight;
v.worldZ += vert[w]->pixelpos.Z * weight;
}
// Calculate normalized device coordinates:
@ -641,7 +632,11 @@ void PolyTriangleThreadData::DrawShadedLine(const ShadedTriVertex *const* vert)
v.y = viewport_y + viewport_height * (1.0f - v.y) * 0.5f;
}
uint32_t color = vert[0]->vColor;
uint32_t vColorA = (int)(vert[0]->vColor.W * 255.0f + 0.5f);
uint32_t vColorR = (int)(vert[0]->vColor.X * 255.0f + 0.5f);
uint32_t vColorG = (int)(vert[0]->vColor.Y * 255.0f + 0.5f);
uint32_t vColorB = (int)(vert[0]->vColor.Z * 255.0f + 0.5f);
uint32_t color = MAKEARGB(vColorA, vColorR, vColorG, vColorB);
// Slow and naive implementation. Hopefully fast enough..
@ -679,7 +674,7 @@ void PolyTriangleThreadData::DrawShadedLine(const ShadedTriVertex *const* vert)
}
}
void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* vert, bool ccw, TriDrawTriangleArgs *args)
void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* vert, bool ccw)
{
// Reject triangle if degenerate
if (IsDegenerate(vert))
@ -706,6 +701,11 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve
v.worldX += vert[w]->pixelpos.X * weight;
v.worldY += vert[w]->pixelpos.Y * weight;
v.worldZ += vert[w]->pixelpos.Z * weight;
v.a += vert[w]->vColor.W * weight;
v.r += vert[w]->vColor.X * weight;
v.g += vert[w]->vColor.Y * weight;
v.b += vert[w]->vColor.Z * weight;
v.gradientdistZ += vert[w]->gradientdist.Z * weight;
}
}
@ -759,27 +759,14 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve
}
#endif
#if 0
// Keep varyings in -128 to 128 range if possible
// But don't do this for the skycap mode since the V texture coordinate is used for blending
if (numclipvert > 0 && drawargs.BlendMode() != TriBlendMode::Skycap)
{
float newOriginU = floorf(clippedvert[0].u * 0.1f) * 10.0f;
float newOriginV = floorf(clippedvert[0].v * 0.1f) * 10.0f;
for (int i = 0; i < numclipvert; i++)
{
clippedvert[i].u -= newOriginU;
clippedvert[i].v -= newOriginV;
}
}
#endif
TriDrawTriangleArgs args;
if (twosided && numclipvert > 2)
{
args->v1 = &clippedvert[0];
args->v2 = &clippedvert[1];
args->v3 = &clippedvert[2];
ccw = !IsFrontfacing(args);
args.v1 = &clippedvert[0];
args.v2 = &clippedvert[1];
args.v3 = &clippedvert[2];
ccw = !IsFrontfacing(&args);
}
// Draw screen triangles
@ -787,12 +774,12 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve
{
for (int i = numclipvert - 1; i > 1; i--)
{
args->v1 = &clippedvert[numclipvert - 1];
args->v2 = &clippedvert[i - 1];
args->v3 = &clippedvert[i - 2];
if (IsFrontfacing(args) == ccw && args->CalculateGradients())
args.v1 = &clippedvert[numclipvert - 1];
args.v2 = &clippedvert[i - 1];
args.v3 = &clippedvert[i - 2];
if (IsFrontfacing(&args) == ccw && args.CalculateGradients())
{
ScreenTriangle::Draw(args, this);
ScreenTriangle::Draw(&args, this);
}
}
}
@ -800,12 +787,12 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve
{
for (int i = 2; i < numclipvert; i++)
{
args->v1 = &clippedvert[0];
args->v2 = &clippedvert[i - 1];
args->v3 = &clippedvert[i];
if (IsFrontfacing(args) != ccw && args->CalculateGradients())
args.v1 = &clippedvert[0];
args.v2 = &clippedvert[i - 1];
args.v3 = &clippedvert[i];
if (IsFrontfacing(&args) != ccw && args.CalculateGradients())
{
ScreenTriangle::Draw(args, this);
ScreenTriangle::Draw(&args, this);
}
}
}

View file

@ -196,11 +196,18 @@ public:
struct Scanline
{
float W[MAXWIDTH];
float WeightV1[MAXWIDTH];
float WeightV2[MAXWIDTH];
uint16_t U[MAXWIDTH];
uint16_t V[MAXWIDTH];
float WorldX[MAXWIDTH];
float WorldY[MAXWIDTH];
float WorldZ[MAXWIDTH];
uint8_t vColorA[MAXWIDTH];
uint8_t vColorR[MAXWIDTH];
uint8_t vColorG[MAXWIDTH];
uint8_t vColorB[MAXWIDTH];
float GradientdistZ[MAXWIDTH];
uint32_t FragColor[MAXWIDTH];
uint16_t lightarray[MAXWIDTH];
uint32_t dynlights[MAXWIDTH];
@ -263,7 +270,7 @@ private:
ShadedTriVertex ShadeVertex(int index);
void DrawShadedPoint(const ShadedTriVertex *const* vertex);
void DrawShadedLine(const ShadedTriVertex *const* vertices);
void DrawShadedTriangle(const ShadedTriVertex *const* vertices, bool ccw, TriDrawTriangleArgs *args);
void DrawShadedTriangle(const ShadedTriVertex *const* vertices, bool ccw);
static bool IsDegenerate(const ShadedTriVertex *const* vertices);
static bool IsFrontfacing(TriDrawTriangleArgs *args);

View file

@ -15,8 +15,11 @@ public:
Vec4f gl_Position;
float gl_ClipDistance[5];
Vec4f vTexCoord;
uint32_t vColor;
Vec4f vColor;
Vec4f pixelpos;
//Vec3f glowdist;
Vec3f gradientdist;
//Vec4f vEyeNormal;
Vec4f vWorldNormal;
};
@ -26,16 +29,11 @@ public:
// Input
Vec4f aPosition;
Vec2f aTexCoord;
uint32_t aColor;
Vec4f aColor;
Vec4f aVertex2;
Vec4f aNormal;
Vec4f aNormal2;
// Output
Vec3f glowdist;
Vec3f gradientdist;
Vec4f vEyeNormal;
// Defines
bool SIMPLE = false;
bool SPHEREMAP = false;
@ -70,14 +68,14 @@ public:
pixelpos.Z = worldcoord.Z;
pixelpos.W = -eyeCoordPos.Z / eyeCoordPos.W;
if (Data.uGlowTopColor.W > 0 || Data.uGlowBottomColor.W > 0)
/*if (Data.uGlowTopColor.W > 0 || Data.uGlowBottomColor.W > 0)
{
float topatpoint = (Data.uGlowTopPlane.W + Data.uGlowTopPlane.X * worldcoord.X + Data.uGlowTopPlane.Y * worldcoord.Z) * Data.uGlowTopPlane.Z;
float bottomatpoint = (Data.uGlowBottomPlane.W + Data.uGlowBottomPlane.X * worldcoord.X + Data.uGlowBottomPlane.Y * worldcoord.Z) * Data.uGlowBottomPlane.Z;
glowdist.X = topatpoint - worldcoord.Y;
glowdist.Y = worldcoord.Y - bottomatpoint;
glowdist.Z = clamp(glowdist.X / (topatpoint - bottomatpoint), 0.0f, 1.0f);
}
}*/
if (Data.uObjectColor2.a != 0)
{
@ -95,7 +93,7 @@ public:
}
vWorldNormal = mul(NormalModelMatrix, Vec4f(normalize(mix3(aNormal, aNormal2, Data.uInterpolationFactor)), 1.0f));
vEyeNormal = mul(Viewpoint->mNormalViewMatrix, vWorldNormal);
//vEyeNormal = mul(Viewpoint->mNormalViewMatrix, vWorldNormal);
}
if (!SPHEREMAP)

View file

@ -371,6 +371,42 @@ static void WriteVaryingWrap(float pos, float step, int x0, int x1, const float*
}
#endif
#ifdef NO_SSE
static void WriteVaryingColor(float pos, float step, int x0, int x1, const float* w, uint8_t* varying)
{
for (int x = x0; x < x1; x++)
{
varying[x] = (int)(pos * w[x] * 255.0f);
pos += step;
}
}
#else
static void WriteVaryingColor(float pos, float step, int x0, int x1, const float* w, uint8_t* varying)
{
int ssecount = ((x1 - x0) & ~3);
int sseend = x0 + ssecount;
__m128 mstep = _mm_set1_ps(step * 4.0f);
__m128 mpos = _mm_setr_ps(pos, pos + step, pos + step + step, pos + step + step + step);
for (int x = x0; x < sseend; x += 4)
{
__m128i value = _mm_cvttps_epi32(_mm_mul_ps(_mm_mul_ps(mpos, _mm_loadu_ps(w + x)), _mm_set1_ps(255.0f)));
value = _mm_packs_epi32(value, value);
value = _mm_packus_epi16(value, value);
*(uint32_t*)(varying + x) = _mm_cvtsi128_si32(value);
mpos = _mm_add_ps(mpos, mstep);
}
pos += ssecount * step;
for (int x = sseend; x < x1; x++)
{
varying[x] = (int)(pos * w[x] * 255.0f);
pos += step;
}
}
#endif
static void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
{
float startX = x0 + (0.5f - args->v1->x);
@ -381,6 +417,11 @@ static void WriteVaryings(int y, int x0, int x1, const TriDrawTriangleArgs* args
WriteVarying(args->v1->worldX * args->v1->w + args->gradientX.WorldX * startX + args->gradientY.WorldX * startY, args->gradientX.WorldX, x0, x1, thread->scanline.W, thread->scanline.WorldX);
WriteVarying(args->v1->worldY * args->v1->w + args->gradientX.WorldY * startX + args->gradientY.WorldY * startY, args->gradientX.WorldY, x0, x1, thread->scanline.W, thread->scanline.WorldY);
WriteVarying(args->v1->worldZ * args->v1->w + args->gradientX.WorldZ * startX + args->gradientY.WorldZ * startY, args->gradientX.WorldZ, x0, x1, thread->scanline.W, thread->scanline.WorldZ);
WriteVarying(args->v1->gradientdistZ * args->v1->w + args->gradientX.GradientdistZ * startX + args->gradientY.GradientdistZ * startY, args->gradientX.GradientdistZ, x0, x1, thread->scanline.W, thread->scanline.GradientdistZ);
WriteVaryingColor(args->v1->a * args->v1->w + args->gradientX.A * startX + args->gradientY.A * startY, args->gradientX.A, x0, x1, thread->scanline.W, thread->scanline.vColorA);
WriteVaryingColor(args->v1->r * args->v1->w + args->gradientX.R * startX + args->gradientY.R * startY, args->gradientX.R, x0, x1, thread->scanline.W, thread->scanline.vColorR);
WriteVaryingColor(args->v1->g * args->v1->w + args->gradientX.G * startX + args->gradientY.G * startY, args->gradientX.G, x0, x1, thread->scanline.W, thread->scanline.vColorG);
WriteVaryingColor(args->v1->b * args->v1->w + args->gradientX.B * startX + args->gradientY.B * startY, args->gradientX.B, x0, x1, thread->scanline.W, thread->scanline.vColorB);
}
static const int shiftTable[] = {
@ -621,17 +662,17 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread)
const void* tex2Pixels = thread->textures[1].pixels;
bool tex2Bgra = thread->textures[1].bgra;
uint32_t frag = thread->mainVertexShader.vColor;
uint32_t frag_r = RPART(frag);
uint32_t frag_g = GPART(frag);
uint32_t frag_b = BPART(frag);
uint32_t frag_a = APART(frag);
frag_r += frag_r >> 7; // 255 -> 256
frag_g += frag_g >> 7; // 255 -> 256
frag_b += frag_b >> 7; // 255 -> 256
frag_a += frag_a >> 7; // 255 -> 256
for (int x = x0; x < x1; x++)
{
uint32_t frag_r = thread->scanline.vColorR[x];
uint32_t frag_g = thread->scanline.vColorG[x];
uint32_t frag_b = thread->scanline.vColorB[x];
uint32_t frag_a = thread->scanline.vColorA[x];
frag_r += frag_r >> 7; // 255 -> 256
frag_g += frag_g >> 7; // 255 -> 256
frag_b += frag_b >> 7; // 255 -> 256
frag_a += frag_a >> 7; // 255 -> 256
uint32_t t1 = SampleTexture(u[x], v[x], texPixels, texWidth, texHeight, texBgra);
uint32_t t2 = SampleTexture(u[x], 0xffff - v[x], tex2Pixels, tex2Width, tex2Height, tex2Bgra);
@ -797,13 +838,15 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread)
}
else
{
float t = thread->mainVertexShader.gradientdist.Z;
float inv_t = 1.0f - t;
uint32_t r = (int)((streamdata.uObjectColor.r * inv_t + streamdata.uObjectColor2.r * t) * 256.0f);
uint32_t g = (int)((streamdata.uObjectColor.g * inv_t + streamdata.uObjectColor2.g * t) * 256.0f);
uint32_t b = (int)((streamdata.uObjectColor.b * inv_t + streamdata.uObjectColor2.b * t) * 256.0f);
float* gradientdistZ = thread->scanline.GradientdistZ;
for (int x = x0; x < x1; x++)
{
float t = gradientdistZ[x];
float inv_t = 1.0f - t;
uint32_t r = (int)((streamdata.uObjectColor.r * inv_t + streamdata.uObjectColor2.r * t) * 256.0f);
uint32_t g = (int)((streamdata.uObjectColor.g * inv_t + streamdata.uObjectColor2.g * t) * 256.0f);
uint32_t b = (int)((streamdata.uObjectColor.b * inv_t + streamdata.uObjectColor2.b * t) * 256.0f);
uint32_t texel = fragcolor[x];
fragcolor[x] = MAKEARGB(
APART(texel),
@ -831,25 +874,24 @@ static void RunShader(int x0, int x1, PolyTriangleThreadData* thread)
}
}
if (thread->mainVertexShader.vColor != 0xffffffff)
for (int x = x0; x < x1; x++)
{
uint32_t a = APART(thread->mainVertexShader.vColor);
uint32_t r = RPART(thread->mainVertexShader.vColor);
uint32_t g = GPART(thread->mainVertexShader.vColor);
uint32_t b = BPART(thread->mainVertexShader.vColor);
uint32_t r = thread->scanline.vColorR[x];
uint32_t g = thread->scanline.vColorG[x];
uint32_t b = thread->scanline.vColorB[x];
uint32_t a = thread->scanline.vColorA[x];
a += a >> 7;
r += r >> 7;
g += g >> 7;
b += b >> 7;
for (int x = x0; x < x1; x++)
{
uint32_t texel = fragcolor[x];
fragcolor[x] = MAKEARGB(
(APART(texel) * a + 127) >> 8,
(RPART(texel) * r + 127) >> 8,
(GPART(texel) * g + 127) >> 8,
(BPART(texel) * b + 127) >> 8);
}
uint32_t texel = fragcolor[x];
fragcolor[x] = MAKEARGB(
(APART(texel) * a + 127) >> 8,
(RPART(texel) * r + 127) >> 8,
(GPART(texel) * g + 127) >> 8,
(BPART(texel) * b + 127) >> 8);
}
if (constants->uLightLevel >= 0.0f && thread->numPolyLights > 0)

View file

@ -35,12 +35,16 @@ struct ScreenTriVertex
float x, y, z, w;
float u, v;
float worldX, worldY, worldZ;
float a, r, g, b;
float gradientdistZ;
};
struct ScreenTriangleStepVariables
{
float W, U, V;
float WorldX, WorldY, WorldZ, Padding; // Padding so it can be loaded directly into a XMM register
float WorldX, WorldY, WorldZ;
float A, R, G, B;
float GradientdistZ;
};
struct TriDrawTriangleArgs
@ -64,6 +68,11 @@ struct TriDrawTriangleArgs
gradientX.WorldX = FindGradientX(bottomX, v1->worldX, v2->worldX, v3->worldX);
gradientX.WorldY = FindGradientX(bottomX, v1->worldY, v2->worldY, v3->worldY);
gradientX.WorldZ = FindGradientX(bottomX, v1->worldZ, v2->worldZ, v3->worldZ);
gradientX.A = FindGradientX(bottomX, v1->a, v2->a, v3->a);
gradientX.R = FindGradientX(bottomX, v1->r, v2->r, v3->r);
gradientX.G = FindGradientX(bottomX, v1->g, v2->g, v3->g);
gradientX.B = FindGradientX(bottomX, v1->b, v2->b, v3->b);
gradientX.GradientdistZ = FindGradientX(bottomX, v1->gradientdistZ, v2->gradientdistZ, v3->gradientdistZ);
gradientY.W = FindGradientY(bottomY, 1.0f, 1.0f, 1.0f);
gradientY.U = FindGradientY(bottomY, v1->u, v2->u, v3->u);
@ -71,6 +80,11 @@ struct TriDrawTriangleArgs
gradientY.WorldX = FindGradientY(bottomY, v1->worldX, v2->worldX, v3->worldX);
gradientY.WorldY = FindGradientY(bottomY, v1->worldY, v2->worldY, v3->worldY);
gradientY.WorldZ = FindGradientY(bottomY, v1->worldZ, v2->worldZ, v3->worldZ);
gradientY.A = FindGradientY(bottomY, v1->a, v2->a, v3->a);
gradientY.R = FindGradientY(bottomY, v1->r, v2->r, v3->r);
gradientY.G = FindGradientY(bottomY, v1->g, v2->g, v3->g);
gradientY.B = FindGradientY(bottomY, v1->b, v2->b, v3->b);
gradientY.GradientdistZ = FindGradientY(bottomY, v1->gradientdistZ, v2->gradientdistZ, v3->gradientdistZ);
return true;
}