mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-22 12:11:25 +00:00
- replace the old rect drawers with new ones based on render styles
This commit is contained in:
parent
23fce56b5e
commit
d425fb2d4a
7 changed files with 603 additions and 1436 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -36,12 +36,6 @@
|
|||
#include "poly_triangle.h"
|
||||
#include "swrenderer/drawers/r_draw_rgba.h"
|
||||
#include "screen_triangle.h"
|
||||
#ifndef NO_SSE
|
||||
#include "poly_drawer32_sse2.h"
|
||||
#else
|
||||
#include "poly_drawer32.h"
|
||||
#endif
|
||||
#include "poly_drawer8.h"
|
||||
#include "x86.h"
|
||||
|
||||
static void SortVertices(const TriDrawTriangleArgs *args, ShadedTriVertex **sortedVertices)
|
||||
|
@ -1284,6 +1278,516 @@ void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args)
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ModeT>
|
||||
void DrawRect8(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;
|
||||
|
||||
const uint8_t *colormaps, *texPixels, *translation;
|
||||
int texWidth, texHeight;
|
||||
uint32_t fillcolor;
|
||||
int alpha;
|
||||
uint32_t light;
|
||||
|
||||
texPixels = args->TexturePixels();
|
||||
translation = args->Translation();
|
||||
texWidth = args->TextureWidth();
|
||||
texHeight = args->TextureHeight();
|
||||
fillcolor = args->Color();
|
||||
alpha = args->Alpha();
|
||||
colormaps = args->BaseColormap();
|
||||
light = args->Light();
|
||||
light += light >> 7; // 255 -> 256
|
||||
light = ((256 - light) * NUMCOLORMAPS) & 0xffffff00;
|
||||
|
||||
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);
|
||||
|
||||
uint32_t posV = startV;
|
||||
int num_cores = thread->num_cores;
|
||||
int skip = thread->skipped_by_thread(y0);
|
||||
posV += skip * stepV;
|
||||
stepV *= num_cores;
|
||||
for (int y = y0 + skip; y < y1; y += num_cores, posV += stepV)
|
||||
{
|
||||
uint8_t *destLine = ((uint8_t*)destOrg) + y * destPitch;
|
||||
|
||||
uint32_t posU = startU;
|
||||
for (int x = x0; x < x1; x++)
|
||||
{
|
||||
int fg = 0;
|
||||
int fgalpha = 255;
|
||||
|
||||
if (ModeT::SWFlags & SWSTYLEF_Fill)
|
||||
{
|
||||
fg = fillcolor;
|
||||
}
|
||||
else if (ModeT::BlendOp != STYLEOP_Fuzz)
|
||||
{
|
||||
uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16;
|
||||
uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16;
|
||||
fg = texPixels[texelX * texHeight + texelY];
|
||||
|
||||
if (ModeT::SWFlags & SWSTYLEF_Translated)
|
||||
fg = translation[fg];
|
||||
|
||||
fgalpha = (fg != 0) ? 255 : 0;
|
||||
}
|
||||
|
||||
if (ModeT::BlendOp == STYLEOP_Fuzz)
|
||||
{
|
||||
using namespace swrenderer;
|
||||
|
||||
uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16;
|
||||
uint32_t texelY = (((posV << 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;
|
||||
|
||||
uint32_t a = 256 - sampleshadeout;
|
||||
|
||||
uint32_t dest = GPalette.BaseColors[destLine[x]].d;
|
||||
uint32_t r = (RPART(dest) * a) >> 8;
|
||||
uint32_t g = (GPART(dest) * a) >> 8;
|
||||
uint32_t b = (BPART(dest) * a) >> 8;
|
||||
destLine[x] = RGB256k.All[((r >> 2) << 12) | ((g >> 2) << 6) | (b >> 2)];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill))
|
||||
{
|
||||
if (ModeT::Flags & STYLEF_RedIsAlpha)
|
||||
fgalpha = fg;
|
||||
fg = fillcolor;
|
||||
}
|
||||
|
||||
if (!(ModeT::Flags & STYLEF_Alpha1))
|
||||
{
|
||||
fgalpha = (fgalpha * alpha) >> 8;
|
||||
}
|
||||
|
||||
uint8_t shadedfg = colormaps[light + fg];
|
||||
|
||||
if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero)
|
||||
{
|
||||
destLine[x] = shadedfg;
|
||||
}
|
||||
else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One)
|
||||
{
|
||||
uint32_t src = GPalette.BaseColors[shadedfg];
|
||||
uint32_t dest = GPalette.BaseColors[destLine[x]];
|
||||
|
||||
if (ModeT::BlendOp == STYLEOP_Add)
|
||||
{
|
||||
uint32_t out_r = MIN<uint32_t>(RPART(dest) + RPART(src), 255);
|
||||
uint32_t out_g = MIN<uint32_t>(GPART(dest) + GPART(src), 255);
|
||||
uint32_t out_b = MIN<uint32_t>(BPART(dest) + BPART(src), 255);
|
||||
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
|
||||
}
|
||||
else if (ModeT::BlendOp == STYLEOP_RevSub)
|
||||
{
|
||||
uint32_t out_r = MAX<uint32_t>(RPART(dest) - RPART(src), 0);
|
||||
uint32_t out_g = MAX<uint32_t>(GPART(dest) - GPART(src), 0);
|
||||
uint32_t out_b = MAX<uint32_t>(BPART(dest) - BPART(src), 0);
|
||||
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
|
||||
}
|
||||
else //if (ModeT::BlendOp == STYLEOP_Sub)
|
||||
{
|
||||
uint32_t out_r = MAX<uint32_t>(RPART(src) - RPART(dest), 0);
|
||||
uint32_t out_g = MAX<uint32_t>(GPART(src) - GPART(dest), 0);
|
||||
uint32_t out_b = MAX<uint32_t>(BPART(src) - BPART(dest), 0);
|
||||
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
|
||||
}
|
||||
}
|
||||
else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor)
|
||||
{
|
||||
uint32_t src = GPalette.BaseColors[shadedfg];
|
||||
uint32_t dest = GPalette.BaseColors[destLine[x]];
|
||||
|
||||
uint32_t sfactor_r = RPART(src); sfactor_r += sfactor_r >> 7; // 255 -> 256
|
||||
uint32_t sfactor_g = GPART(src); sfactor_g += sfactor_g >> 7; // 255 -> 256
|
||||
uint32_t sfactor_b = BPART(src); sfactor_b += sfactor_b >> 7; // 255 -> 256
|
||||
uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256
|
||||
uint32_t dfactor_r = 256 - sfactor_r;
|
||||
uint32_t dfactor_g = 256 - sfactor_g;
|
||||
uint32_t dfactor_b = 256 - sfactor_b;
|
||||
uint32_t out_r = (RPART(dest) * dfactor_r + RPART(src) * sfactor_r + 128) >> 8;
|
||||
uint32_t out_g = (GPART(dest) * dfactor_g + GPART(src) * sfactor_g + 128) >> 8;
|
||||
uint32_t out_b = (BPART(dest) * dfactor_b + BPART(src) * sfactor_b + 128) >> 8;
|
||||
|
||||
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
|
||||
}
|
||||
else if (ModeT::BlendSrc == STYLEALPHA_Src && ModeT::BlendDest == STYLEALPHA_InvSrc && fgalpha == 255)
|
||||
{
|
||||
destLine[x] = shadedfg;
|
||||
}
|
||||
else if (ModeT::BlendSrc != STYLEALPHA_Src || ModeT::BlendDest != STYLEALPHA_InvSrc || fgalpha != 0)
|
||||
{
|
||||
uint32_t src = GPalette.BaseColors[shadedfg];
|
||||
uint32_t dest = GPalette.BaseColors[destLine[x]];
|
||||
|
||||
uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256
|
||||
uint32_t dfactor = 256 - sfactor;
|
||||
uint32_t src_r = RPART(src) * sfactor;
|
||||
uint32_t src_g = GPART(src) * sfactor;
|
||||
uint32_t src_b = BPART(src) * sfactor;
|
||||
uint32_t dest_r = RPART(dest);
|
||||
uint32_t dest_g = GPART(dest);
|
||||
uint32_t dest_b = BPART(dest);
|
||||
if (ModeT::BlendDest == STYLEALPHA_One)
|
||||
{
|
||||
dest_r <<= 8;
|
||||
dest_g <<= 8;
|
||||
dest_b <<= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t dfactor = 256 - sfactor;
|
||||
dest_r *= dfactor;
|
||||
dest_g *= dfactor;
|
||||
dest_b *= dfactor;
|
||||
}
|
||||
|
||||
uint32_t out_r, out_g, out_b;
|
||||
if (ModeT::BlendOp == STYLEOP_Add)
|
||||
{
|
||||
if (ModeT::BlendDest == STYLEALPHA_One)
|
||||
{
|
||||
out_r = MIN<int32_t>((dest_r + src_r + 128) >> 8, 255);
|
||||
out_g = MIN<int32_t>((dest_g + src_g + 128) >> 8, 255);
|
||||
out_b = MIN<int32_t>((dest_b + src_b + 128) >> 8, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_r = (dest_r + src_r + 128) >> 8;
|
||||
out_g = (dest_g + src_g + 128) >> 8;
|
||||
out_b = (dest_b + src_b + 128) >> 8;
|
||||
}
|
||||
}
|
||||
else if (ModeT::BlendOp == STYLEOP_RevSub)
|
||||
{
|
||||
out_r = MAX<int32_t>(static_cast<int32_t>(dest_r - src_r + 128) >> 8, 0);
|
||||
out_g = MAX<int32_t>(static_cast<int32_t>(dest_g - src_g + 128) >> 8, 0);
|
||||
out_b = MAX<int32_t>(static_cast<int32_t>(dest_b - src_b + 128) >> 8, 0);
|
||||
}
|
||||
else //if (ModeT::BlendOp == STYLEOP_Sub)
|
||||
{
|
||||
out_r = MAX<int32_t>(static_cast<int32_t>(src_r - dest_r + 128) >> 8, 0);
|
||||
out_g = MAX<int32_t>(static_cast<int32_t>(src_g - dest_g + 128) >> 8, 0);
|
||||
out_b = MAX<int32_t>(static_cast<int32_t>(src_b - dest_b + 128) >> 8, 0);
|
||||
}
|
||||
|
||||
destLine[x] = RGB256k.All[((out_r >> 2) << 12) | ((out_g >> 2) << 6) | (out_b >> 2)];
|
||||
}
|
||||
}
|
||||
|
||||
posU += stepU;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ModeT, typename OptT>
|
||||
void DrawRectOpt32(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;
|
||||
|
||||
const uint32_t *texPixels, *translation;
|
||||
int texWidth, texHeight;
|
||||
uint32_t fillcolor;
|
||||
int alpha;
|
||||
uint32_t light;
|
||||
uint32_t shade_fade_r, shade_fade_g, shade_fade_b, shade_light_r, shade_light_g, shade_light_b, desaturate, inv_desaturate;
|
||||
|
||||
texPixels = (const uint32_t*)args->TexturePixels();
|
||||
translation = (const uint32_t*)args->Translation();
|
||||
texWidth = args->TextureWidth();
|
||||
texHeight = args->TextureHeight();
|
||||
fillcolor = args->Color();
|
||||
alpha = args->Alpha();
|
||||
light = args->Light();
|
||||
light += light >> 7; // 255 -> 256
|
||||
|
||||
if (OptT::Flags & SWOPT_ColoredFog)
|
||||
{
|
||||
shade_fade_r = args->ShadeFadeRed();
|
||||
shade_fade_g = args->ShadeFadeGreen();
|
||||
shade_fade_b = args->ShadeFadeBlue();
|
||||
shade_light_r = args->ShadeLightRed();
|
||||
shade_light_g = args->ShadeLightGreen();
|
||||
shade_light_b = args->ShadeLightBlue();
|
||||
desaturate = args->ShadeDesaturate();
|
||||
inv_desaturate = 256 - desaturate;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
uint32_t posV = startV;
|
||||
int num_cores = thread->num_cores;
|
||||
int skip = thread->skipped_by_thread(y0);
|
||||
posV += skip * stepV;
|
||||
stepV *= num_cores;
|
||||
for (int y = y0 + skip; y < y1; y += num_cores, posV += stepV)
|
||||
{
|
||||
uint32_t *destLine = ((uint32_t*)destOrg) + y * destPitch;
|
||||
|
||||
uint32_t posU = startU;
|
||||
for (int x = x0; x < x1; x++)
|
||||
{
|
||||
uint32_t fg = 0;
|
||||
|
||||
if (ModeT::SWFlags & SWSTYLEF_Fill)
|
||||
{
|
||||
fg = fillcolor;
|
||||
}
|
||||
else if (ModeT::SWFlags & SWSTYLEF_FogBoundary)
|
||||
{
|
||||
fg = destLine[x];
|
||||
}
|
||||
else if (ModeT::BlendOp != STYLEOP_Fuzz)
|
||||
{
|
||||
uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16;
|
||||
uint32_t texelY = (((posV << 8) >> 16) * texHeight) >> 16;
|
||||
|
||||
if (ModeT::SWFlags & SWSTYLEF_Translated)
|
||||
{
|
||||
fg = translation[((const uint8_t*)texPixels)[texelX * texHeight + texelY]];
|
||||
}
|
||||
else if (ModeT::Flags & STYLEF_RedIsAlpha)
|
||||
{
|
||||
fg = ((const uint8_t*)texPixels)[texelX * texHeight + texelY];
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = texPixels[texelX * texHeight + texelY];
|
||||
}
|
||||
}
|
||||
|
||||
if (ModeT::BlendOp == STYLEOP_Fuzz)
|
||||
{
|
||||
using namespace swrenderer;
|
||||
|
||||
uint32_t texelX = (((posU << 8) >> 16) * texWidth) >> 16;
|
||||
uint32_t texelY = (((posV << 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;
|
||||
|
||||
uint32_t a = 256 - sampleshadeout;
|
||||
|
||||
uint32_t dest = destLine[x];
|
||||
uint32_t out_r = (RPART(dest) * a) >> 8;
|
||||
uint32_t out_g = (GPART(dest) * a) >> 8;
|
||||
uint32_t out_b = (BPART(dest) * a) >> 8;
|
||||
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill))
|
||||
{
|
||||
if (ModeT::Flags & STYLEF_RedIsAlpha)
|
||||
fg = (fg << 24) | (fillcolor & 0x00ffffff);
|
||||
else
|
||||
fg = (fg & 0xff000000) | (fillcolor & 0x00ffffff);
|
||||
}
|
||||
|
||||
uint32_t fgalpha = fg >> 24;
|
||||
|
||||
if (!(ModeT::Flags & STYLEF_Alpha1))
|
||||
{
|
||||
fgalpha = (fgalpha * alpha) >> 8;
|
||||
}
|
||||
|
||||
int lightshade = light;
|
||||
|
||||
uint32_t lit_r = 0, lit_g = 0, lit_b = 0;
|
||||
|
||||
uint32_t shadedfg_r, shadedfg_g, shadedfg_b;
|
||||
if (OptT::Flags & SWOPT_ColoredFog)
|
||||
{
|
||||
uint32_t fg_r = RPART(fg);
|
||||
uint32_t fg_g = GPART(fg);
|
||||
uint32_t fg_b = BPART(fg);
|
||||
uint32_t intensity = ((fg_r * 77 + fg_g * 143 + fg_b * 37) >> 8) * desaturate;
|
||||
shadedfg_r = (((shade_fade_r + ((fg_r * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_r) >> 8;
|
||||
shadedfg_g = (((shade_fade_g + ((fg_g * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_g) >> 8;
|
||||
shadedfg_b = (((shade_fade_b + ((fg_b * inv_desaturate + intensity) >> 8) * lightshade) >> 8) * shade_light_b) >> 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
shadedfg_r = (RPART(fg) * lightshade) >> 8;
|
||||
shadedfg_g = (GPART(fg) * lightshade) >> 8;
|
||||
shadedfg_b = (BPART(fg) * lightshade) >> 8;
|
||||
}
|
||||
|
||||
if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_Zero)
|
||||
{
|
||||
destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b);
|
||||
}
|
||||
else if (ModeT::BlendSrc == STYLEALPHA_One && ModeT::BlendDest == STYLEALPHA_One)
|
||||
{
|
||||
uint32_t dest = destLine[x];
|
||||
|
||||
if (ModeT::BlendOp == STYLEOP_Add)
|
||||
{
|
||||
uint32_t out_r = MIN<uint32_t>(RPART(dest) + shadedfg_r, 255);
|
||||
uint32_t out_g = MIN<uint32_t>(GPART(dest) + shadedfg_g, 255);
|
||||
uint32_t out_b = MIN<uint32_t>(BPART(dest) + shadedfg_b, 255);
|
||||
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
|
||||
}
|
||||
else if (ModeT::BlendOp == STYLEOP_RevSub)
|
||||
{
|
||||
uint32_t out_r = MAX<uint32_t>(RPART(dest) - shadedfg_r, 0);
|
||||
uint32_t out_g = MAX<uint32_t>(GPART(dest) - shadedfg_g, 0);
|
||||
uint32_t out_b = MAX<uint32_t>(BPART(dest) - shadedfg_b, 0);
|
||||
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
|
||||
}
|
||||
else //if (ModeT::BlendOp == STYLEOP_Sub)
|
||||
{
|
||||
uint32_t out_r = MAX<uint32_t>(shadedfg_r - RPART(dest), 0);
|
||||
uint32_t out_g = MAX<uint32_t>(shadedfg_g - GPART(dest), 0);
|
||||
uint32_t out_b = MAX<uint32_t>(shadedfg_b - BPART(dest), 0);
|
||||
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
|
||||
}
|
||||
}
|
||||
else if (ModeT::SWFlags & SWSTYLEF_SrcColorOneMinusSrcColor)
|
||||
{
|
||||
uint32_t dest = destLine[x];
|
||||
|
||||
uint32_t sfactor_r = shadedfg_r; sfactor_r += sfactor_r >> 7; // 255 -> 256
|
||||
uint32_t sfactor_g = shadedfg_g; sfactor_g += sfactor_g >> 7; // 255 -> 256
|
||||
uint32_t sfactor_b = shadedfg_b; sfactor_b += sfactor_b >> 7; // 255 -> 256
|
||||
uint32_t sfactor_a = fgalpha; sfactor_a += sfactor_a >> 7; // 255 -> 256
|
||||
uint32_t dfactor_r = 256 - sfactor_r;
|
||||
uint32_t dfactor_g = 256 - sfactor_g;
|
||||
uint32_t dfactor_b = 256 - sfactor_b;
|
||||
uint32_t out_r = (RPART(dest) * dfactor_r + shadedfg_r * sfactor_r + 128) >> 8;
|
||||
uint32_t out_g = (GPART(dest) * dfactor_g + shadedfg_g * sfactor_g + 128) >> 8;
|
||||
uint32_t out_b = (BPART(dest) * dfactor_b + shadedfg_b * sfactor_b + 128) >> 8;
|
||||
|
||||
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
|
||||
}
|
||||
else if (ModeT::BlendSrc == STYLEALPHA_Src && ModeT::BlendDest == STYLEALPHA_InvSrc && fgalpha == 255)
|
||||
{
|
||||
destLine[x] = MAKEARGB(255, shadedfg_r, shadedfg_g, shadedfg_b);
|
||||
}
|
||||
else if (ModeT::BlendSrc != STYLEALPHA_Src || ModeT::BlendDest != STYLEALPHA_InvSrc || fgalpha != 0)
|
||||
{
|
||||
uint32_t dest = destLine[x];
|
||||
|
||||
uint32_t sfactor = fgalpha; sfactor += sfactor >> 7; // 255 -> 256
|
||||
uint32_t src_r = shadedfg_r * sfactor;
|
||||
uint32_t src_g = shadedfg_g * sfactor;
|
||||
uint32_t src_b = shadedfg_b * sfactor;
|
||||
uint32_t dest_r = RPART(dest);
|
||||
uint32_t dest_g = GPART(dest);
|
||||
uint32_t dest_b = BPART(dest);
|
||||
if (ModeT::BlendDest == STYLEALPHA_One)
|
||||
{
|
||||
dest_r <<= 8;
|
||||
dest_g <<= 8;
|
||||
dest_b <<= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t dfactor = 256 - sfactor;
|
||||
dest_r *= dfactor;
|
||||
dest_g *= dfactor;
|
||||
dest_b *= dfactor;
|
||||
}
|
||||
|
||||
uint32_t out_r, out_g, out_b;
|
||||
if (ModeT::BlendOp == STYLEOP_Add)
|
||||
{
|
||||
if (ModeT::BlendDest == STYLEALPHA_One)
|
||||
{
|
||||
out_r = MIN<int32_t>((dest_r + src_r + 128) >> 8, 255);
|
||||
out_g = MIN<int32_t>((dest_g + src_g + 128) >> 8, 255);
|
||||
out_b = MIN<int32_t>((dest_b + src_b + 128) >> 8, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_r = (dest_r + src_r + 128) >> 8;
|
||||
out_g = (dest_g + src_g + 128) >> 8;
|
||||
out_b = (dest_b + src_b + 128) >> 8;
|
||||
}
|
||||
}
|
||||
else if (ModeT::BlendOp == STYLEOP_RevSub)
|
||||
{
|
||||
out_r = MAX<int32_t>(static_cast<int32_t>(dest_r - src_r + 128) >> 8, 0);
|
||||
out_g = MAX<int32_t>(static_cast<int32_t>(dest_g - src_g + 128) >> 8, 0);
|
||||
out_b = MAX<int32_t>(static_cast<int32_t>(dest_b - src_b + 128) >> 8, 0);
|
||||
}
|
||||
else //if (ModeT::BlendOp == STYLEOP_Sub)
|
||||
{
|
||||
out_r = MAX<int32_t>(static_cast<int32_t>(src_r - dest_r + 128) >> 8, 0);
|
||||
out_g = MAX<int32_t>(static_cast<int32_t>(src_g - dest_g + 128) >> 8, 0);
|
||||
out_b = MAX<int32_t>(static_cast<int32_t>(src_b - dest_b + 128) >> 8, 0);
|
||||
}
|
||||
|
||||
destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
|
||||
}
|
||||
}
|
||||
|
||||
posU += stepU;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ModeT>
|
||||
void DrawRect32(const void *destOrg, int destWidth, int destHeight, int destPitch, const RectDrawArgs *args, PolyTriangleThreadData *thread)
|
||||
{
|
||||
using namespace TriScreenDrawerModes;
|
||||
|
||||
if (args->SimpleShade())
|
||||
DrawRectOpt32<ModeT, DrawerOptF>(destOrg, destWidth, destHeight, destPitch, args, thread);
|
||||
else
|
||||
DrawRectOpt32<ModeT, DrawerOptCF>(destOrg, destWidth, destHeight, destPitch, args, thread);
|
||||
}
|
||||
|
||||
void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *) =
|
||||
{
|
||||
&DrawSpan8<TriScreenDrawerModes::StyleOpaque>,
|
||||
|
@ -1350,58 +1854,66 @@ void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs
|
|||
|
||||
void(*ScreenTriangle::RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) =
|
||||
{
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureOpaque
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::MaskedBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureMasked
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::AddClampBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureAdd
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::SubClampBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureSub
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::RevSubClampBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureRevSub
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::AddSrcColorBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureAddSrcColor
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedOpaque
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::MaskedBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedMasked
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::AddClampBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedAdd
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::SubClampBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedSub
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::RevSubClampBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedRevSub
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::AddSrcColorBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedAddSrcColor
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::ShadedBlend, TriScreenDrawerModes::ShadedSampler>::Execute, // Shaded
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::AddClampShadedBlend, TriScreenDrawerModes::ShadedSampler>::Execute, // AddShaded
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::ShadedBlend, TriScreenDrawerModes::StencilSampler>::Execute, // Stencil
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::AddClampShadedBlend, TriScreenDrawerModes::StencilSampler>::Execute, // AddStencil
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::FillSampler>::Execute, // FillOpaque
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::AddClampBlend, TriScreenDrawerModes::FillSampler>::Execute, // FillAdd
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::SubClampBlend, TriScreenDrawerModes::FillSampler>::Execute, // FillSub
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::RevSubClampBlend, TriScreenDrawerModes::FillSampler>::Execute, // FillRevSub
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::AddSrcColorBlend, TriScreenDrawerModes::FillSampler>::Execute, // FillAddSrcColor
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::SkycapSampler>::Execute, // Skycap
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::ShadedBlend, TriScreenDrawerModes::FuzzSampler>::Execute, // Fuzz
|
||||
&RectScreenDrawer8<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::FogBoundarySampler>::Execute // FogBoundary
|
||||
&DrawRect8<TriScreenDrawerModes::StyleOpaque>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleSkycap>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleFogBoundary>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleSrcColor>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleFill>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleNormal>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleFuzzy>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleStencil>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleTranslucent>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleAdd>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleShaded>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleTranslucentStencil>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleShadow>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleSubtract>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleAddStencil>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleAddShaded>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleOpaqueTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleSrcColorTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleNormalTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleStencilTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleTranslucentTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleAddTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleShadedTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleTranslucentStencilTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleShadowTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleSubtractTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleAddStencilTranslated>,
|
||||
&DrawRect8<TriScreenDrawerModes::StyleAddShadedTranslated>
|
||||
};
|
||||
|
||||
void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *) =
|
||||
{
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureOpaque
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::MaskedBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureMasked
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::AddClampBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureAdd
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::SubClampBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureSub
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::RevSubClampBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureRevSub
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::AddSrcColorBlend, TriScreenDrawerModes::TextureSampler>::Execute, // TextureAddSrcColor
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedOpaque
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::MaskedBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedMasked
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::AddClampBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedAdd
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::SubClampBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedSub
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::RevSubClampBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedRevSub
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::AddSrcColorBlend, TriScreenDrawerModes::TranslatedSampler>::Execute, // TranslatedAddSrcColor
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::ShadedBlend, TriScreenDrawerModes::ShadedSampler>::Execute, // Shaded
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::AddClampShadedBlend, TriScreenDrawerModes::ShadedSampler>::Execute, // AddShaded
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::ShadedBlend, TriScreenDrawerModes::StencilSampler>::Execute, // Stencil
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::AddClampShadedBlend, TriScreenDrawerModes::StencilSampler>::Execute, // AddStencil
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::FillSampler>::Execute, // FillOpaque
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::AddClampBlend, TriScreenDrawerModes::FillSampler>::Execute, // FillAdd
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::SubClampBlend, TriScreenDrawerModes::FillSampler>::Execute, // FillSub
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::RevSubClampBlend, TriScreenDrawerModes::FillSampler>::Execute, // FillRevSub
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::AddSrcColorBlend, TriScreenDrawerModes::FillSampler>::Execute, // FillAddSrcColor
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::SkycapSampler>::Execute, // Skycap
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::ShadedBlend, TriScreenDrawerModes::FuzzSampler>::Execute, // Fuzz
|
||||
&RectScreenDrawer32<TriScreenDrawerModes::OpaqueBlend, TriScreenDrawerModes::FogBoundarySampler>::Execute, // FogBoundary
|
||||
&DrawRect32<TriScreenDrawerModes::StyleOpaque>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleSkycap>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleFogBoundary>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleSrcColor>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleFill>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleNormal>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleFuzzy>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleStencil>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleTranslucent>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleAdd>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleShaded>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleTranslucentStencil>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleShadow>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleSubtract>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleAddStencil>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleAddShaded>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleOpaqueTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleSrcColorTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleNormalTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleStencilTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleTranslucentTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleAddTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleShadedTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleTranslucentStencilTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleShadowTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleSubtractTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleAddStencilTranslated>,
|
||||
&DrawRect32<TriScreenDrawerModes::StyleAddShadedTranslated>
|
||||
};
|
||||
|
||||
int ScreenTriangle::FuzzStart = 0;
|
||||
|
|
|
@ -136,34 +136,6 @@ 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:
|
||||
|
@ -219,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,
|
||||
|
|
Loading…
Reference in a new issue