- it compiles again.

This won't work, though, because no backend for the new 2D code exists yet.
This commit is contained in:
Christoph Oelckers 2018-03-28 16:40:09 +02:00
parent 33289ade49
commit 16480a3f4b
18 changed files with 195 additions and 1907 deletions

View file

@ -1015,6 +1015,7 @@ set (PCH_SOURCES
stringtable.cpp
teaminfo.cpp
umapinfo.cpp
v_2ddrawer.cpp
v_blend.cpp
v_collection.cpp
v_draw.cpp

View file

@ -36,6 +36,7 @@
#include "gl/textures/gl_translate.h"
#include "vectors.h"
#if 0
//==========================================================================
//
//
@ -490,3 +491,4 @@ void FGL2DDrawer::Clear()
mData.Clear();
mLastLineCmd = -1;
}
#endif

View file

@ -798,10 +798,10 @@ void FGLRenderer::Flush()
mBuffers->BindEyeFB(eye_ix);
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
glScissor(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
m2DDrawer->Draw();
screen->Draw2D();
FGLDebug::PopGroup();
}
m2DDrawer->Clear();
screen->Clear2D();
FGLPostProcessState savedState;
FGLDebug::PushGroup("PresentEyes");
@ -818,8 +818,8 @@ void FGLRenderer::Flush()
void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
{
m2DDrawer->Draw(); // draw all pending 2D stuff before copying the buffer
m2DDrawer->Clear();
screen->Draw2D(); // draw all pending 2D stuff before copying the buffer
screen->Clear2D();
mCustomPostProcessShaders->Run("screen");

View file

@ -105,7 +105,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
gl_spriteindex = 0;
mShaderManager = nullptr;
mLights = nullptr;
m2DDrawer = nullptr;
mTonemapPalette = nullptr;
mBuffers = nullptr;
mPresentShader = nullptr;
@ -160,7 +159,6 @@ void FGLRenderer::Initialize(int width, int height)
mPresent3dRowShader = new FPresent3DRowShader();
mShadowMapShader = new FShadowMapShader();
mCustomPostProcessShaders = new FCustomPostProcessShaders();
m2DDrawer = new FGL2DDrawer;
GetSpecialTextures();
@ -196,7 +194,6 @@ FGLRenderer::~FGLRenderer()
gl_FlushModels();
AActor::DeleteAllAttachedLights();
FMaterial::FlushAll();
if (m2DDrawer != nullptr) delete m2DDrawer;
if (mShaderManager != NULL) delete mShaderManager;
if (mSamplerManager != NULL) delete mSamplerManager;
if (mVBO != NULL) delete mVBO;

View file

@ -146,7 +146,6 @@ public:
FFlatVertexBuffer *mVBO;
FSkyVertexBuffer *mSkyVBO;
FLightBuffer *mLights;
FGL2DDrawer *m2DDrawer;
GL_IRECT mScreenViewport;
GL_IRECT mSceneViewport;

View file

@ -49,7 +49,7 @@
#include "gl/utility/gl_clock.h"
#include "gl/utility/gl_templates.h"
#include "gl/gl_functions.h"
#include "gl/renderer/gl_2ddrawer.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl_debug.h"
#include "r_videoscale.h"
@ -384,100 +384,6 @@ bool OpenGLFrameBuffer::Begin2D(bool copy3d)
return true;
}
//==========================================================================
//
// Draws a texture
//
//==========================================================================
void OpenGLFrameBuffer::DrawTextureParms(FTexture *img, DrawParms &parms)
{
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddTexture(img, parms);
}
//==========================================================================
//
//
//
//==========================================================================
void OpenGLFrameBuffer::DrawLine(int x1, int y1, int x2, int y2, int palcolor, uint32_t color)
{
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddLine(x1, y1, x2, y2, palcolor, color);
}
//==========================================================================
//
//
//
//==========================================================================
void OpenGLFrameBuffer::DrawPixel(int x1, int y1, int palcolor, uint32_t color)
{
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddPixel(x1, y1, palcolor, color);
}
//==========================================================================
//
//
//
//==========================================================================
void OpenGLFrameBuffer::Dim(PalEntry)
{
// Unlike in the software renderer the color is being ignored here because
// view blending only affects the actual view with the GL renderer.
Super::Dim(0);
}
void OpenGLFrameBuffer::DoDim(PalEntry color, float damount, int x1, int y1, int w, int h)
{
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddDim(color, damount, x1, y1, w, h);
}
//==========================================================================
//
//
//
//==========================================================================
void OpenGLFrameBuffer::FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin)
{
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddFlatFill(left, top, right, bottom, src, local_origin);
}
//==========================================================================
//
//
//
//==========================================================================
void OpenGLFrameBuffer::DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color)
{
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddClear(left, top, right, bottom, palcolor, color);
}
//==========================================================================
//
// D3DFB :: FillSimplePoly
//
// Here, "simple" means that a simple triangle fan can draw it.
//
//==========================================================================
void OpenGLFrameBuffer::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip)
{
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr && npoints >= 3)
{
GLRenderer->m2DDrawer->AddPoly(texture, points, npoints, originx, originy, scalex, scaley, rotation, colormap, flatcolor, lightlevel);
}
}
//===========================================================================
//
// Takes a screenshot

View file

@ -56,19 +56,6 @@ public:
// Releases the screenshot buffer.
virtual void ReleaseScreenshotBuffer();
// 2D drawing
void DrawTextureParms(FTexture *img, DrawParms &parms);
void DrawLine(int x1, int y1, int x2, int y2, int palcolor, uint32_t color);
void DrawPixel(int x1, int y1, int palcolor, uint32_t color);
void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color);
void Dim(PalEntry color=0);
void DoDim (PalEntry color, float damount, int x1, int y1, int w, int h);
void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false);
void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
FNativePalette *CreatePalette(FRemapTable *remap);
bool WipeStartScreen(int type);

View file

@ -2046,65 +2046,6 @@ FNativePalette *OpenGLSWFrameBuffer::CreatePalette(FRemapTable *remap)
return tex;
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: Clear
//
// Fills the specified region with a color.
//
//==========================================================================
void OpenGLSWFrameBuffer::DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color)
{
if (In2D < 2)
{
Super::DoClear(left, top, right, bottom, palcolor, color);
return;
}
if (!InScene)
{
return;
}
if (palcolor >= 0 && color == 0)
{
color = GPalette.BaseColors[palcolor];
}
else if (APART(color) < 255)
{
Dim(color, APART(color) / 255.f, left, top, right - left, bottom - top);
return;
}
AddColorOnlyQuad(left, top, right - left, bottom - top, color | 0xFF000000);
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: Dim
//
//==========================================================================
void OpenGLSWFrameBuffer::DoDim(PalEntry color, float amount, int x1, int y1, int w, int h)
{
if (amount <= 0)
{
return;
}
if (In2D < 2)
{
Super::DoDim(color, amount, x1, y1, w, h);
return;
}
if (!InScene)
{
return;
}
if (amount > 1)
{
amount = 1;
}
AddColorOnlyQuad(x1, y1, w, h, color | (int(amount * 255) << 24));
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: BeginLineBatch
@ -2147,60 +2088,13 @@ void OpenGLSWFrameBuffer::EndLineBatch()
BatchType = BATCH_None;
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: DrawLine
//
//==========================================================================
void OpenGLSWFrameBuffer::DrawLine(int x0, int y0, int x1, int y1, int palcolor, uint32_t color)
{
if (In2D < 2)
{
Super::DrawLine(x0, y0, x1, y1, palcolor, color);
return;
}
if (!InScene)
{
return;
}
if (BatchType != BATCH_Lines)
{
BeginLineBatch();
}
if (VertexPos == NUM_VERTS)
{ // Flush the buffer and refill it.
EndLineBatch();
BeginLineBatch();
}
// Add the endpoints to the vertex buffer.
VertexData[VertexPos].x = float(x0);
VertexData[VertexPos].y = float(y0);
VertexData[VertexPos].z = 0;
VertexData[VertexPos].rhw = 1;
VertexData[VertexPos].color0 = color;
VertexData[VertexPos].color1 = 0;
VertexData[VertexPos].tu = 0;
VertexData[VertexPos].tv = 0;
VertexData[VertexPos + 1].x = float(x1);
VertexData[VertexPos + 1].y = float(y1);
VertexData[VertexPos + 1].z = 0;
VertexData[VertexPos + 1].rhw = 1;
VertexData[VertexPos + 1].color0 = color;
VertexData[VertexPos + 1].color1 = 0;
VertexData[VertexPos + 1].tu = 0;
VertexData[VertexPos + 1].tv = 0;
VertexPos += 2;
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: DrawPixel
//
//==========================================================================
#if 0
void OpenGLSWFrameBuffer::DrawPixel(int x, int y, int palcolor, uint32_t color)
{
if (In2D < 2)
@ -2221,485 +2115,7 @@ void OpenGLSWFrameBuffer::DrawPixel(int x, int y, int palcolor, uint32_t color)
SetAlphaBlend(GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
DrawPoints(1, &pt);
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: DrawTextureV
//
// If not in 2D mode, just call the normal software version.
// If in 2D mode, then use Direct3D calls to perform the drawing.
//
//==========================================================================
void OpenGLSWFrameBuffer::DrawTextureParms(FTexture *img, DrawParms &parms)
{
if (In2D < 2)
{
Super::DrawTextureParms(img, parms);
return;
}
if (!InScene)
{
return;
}
FTextureFormat fmt;
if (parms.style.Flags & STYLEF_RedIsAlpha) fmt = TEX_Gray;
else if (parms.remap != nullptr) fmt = TEX_Pal;
else fmt = img->GetFormat();
OpenGLTex *tex = static_cast<OpenGLTex *>(img->GetNative(fmt, false));
if (tex == nullptr)
{
assert(tex != nullptr);
return;
}
CheckQuadBatch();
double xscale = parms.destwidth / parms.texwidth;
double yscale = parms.destheight / parms.texheight;
double x0 = parms.x - parms.left * xscale;
double y0 = parms.y - parms.top * yscale;
double x1 = x0 + parms.destwidth;
double y1 = y0 + parms.destheight;
float u0 = 0;
float v0 = 0;
float u1 = 1;
float v1 = 1;
double uscale = 1.f;
bool scissoring = false;
FBVERTEX *vert;
if (parms.flipX)
{
swapvalues(u0, u1);
}
if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
{
double wi = MIN(parms.windowright, parms.texwidth);
x0 += parms.windowleft * xscale;
u0 = float(u0 + parms.windowleft * uscale);
x1 -= (parms.texwidth - wi) * xscale;
u1 = float(u1 - (parms.texwidth - wi) * uscale);
}
// Use a scissor test because the math above introduces some jitter
// that is noticeable at low resolutions.
if (y0 < parms.uclip || y1 > parms.dclip || x0 < parms.lclip || x1 > parms.rclip)
{
scissoring = true;
if (QuadBatchPos > 0)
{
EndQuadBatch();
BeginQuadBatch();
}
glEnable(GL_SCISSOR_TEST);
glScissor(parms.lclip, parms.uclip, parms.rclip - parms.lclip, parms.dclip - parms.uclip);
}
parms.bilinear = false;
uint32_t color0, color1;
BufferedTris *quad = &QuadExtra[QuadBatchPos];
if (!SetStyle(tex, parms, color0, color1, *quad))
{
goto done;
}
quad->Texture = tex->Tex.get();
if (parms.bilinear)
{
quad->Flags |= BQF_Bilinear;
}
quad->NumTris = 2;
quad->NumVerts = 4;
vert = &VertexData[VertexPos];
{
PalEntry color = color1;
color = PalEntry((color.a * parms.color.a) / 255, (color.r * parms.color.r) / 255, (color.g * parms.color.g) / 255, (color.b * parms.color.b) / 255);
color1 = color;
}
// Fill the vertex buffer.
vert[0].x = float(x0);
vert[0].y = float(y0);
vert[0].z = 0;
vert[0].rhw = 1;
vert[0].color0 = color0;
vert[0].color1 = color1;
vert[0].tu = u0;
vert[0].tv = v0;
vert[1].x = float(x1);
vert[1].y = float(y0);
vert[1].z = 0;
vert[1].rhw = 1;
vert[1].color0 = color0;
vert[1].color1 = color1;
vert[1].tu = u1;
vert[1].tv = v0;
vert[2].x = float(x1);
vert[2].y = float(y1);
vert[2].z = 0;
vert[2].rhw = 1;
vert[2].color0 = color0;
vert[2].color1 = color1;
vert[2].tu = u1;
vert[2].tv = v1;
vert[3].x = float(x0);
vert[3].y = float(y1);
vert[3].z = 0;
vert[3].rhw = 1;
vert[3].color0 = color0;
vert[3].color1 = color1;
vert[3].tu = u0;
vert[3].tv = v1;
// Fill the vertex index buffer.
IndexData[IndexPos] = VertexPos;
IndexData[IndexPos + 1] = VertexPos + 1;
IndexData[IndexPos + 2] = VertexPos + 2;
IndexData[IndexPos + 3] = VertexPos;
IndexData[IndexPos + 4] = VertexPos + 2;
IndexData[IndexPos + 5] = VertexPos + 3;
// Batch the quad.
QuadBatchPos++;
VertexPos += 4;
IndexPos += 6;
done:
if (scissoring)
{
EndQuadBatch();
glDisable(GL_SCISSOR_TEST);
}
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: FlatFill
//
// Fills an area with a repeating copy of the texture.
//
//==========================================================================
void OpenGLSWFrameBuffer::FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin)
{
if (In2D < 2)
{
Super::FlatFill(left, top, right, bottom, src, local_origin);
return;
}
if (!InScene)
{
return;
}
OpenGLTex *tex = static_cast<OpenGLTex *>(src->GetNative(src->GetFormat(), true));
if (tex == nullptr)
{
return;
}
float x0 = float(left);
float y0 = float(top);
float x1 = float(right);
float y1 = float(bottom);
float itw = 1.f / float(src->GetWidth());
float ith = 1.f / float(src->GetHeight());
float xo = local_origin ? x0 : 0;
float yo = local_origin ? y0 : 0;
float u0 = (x0 - xo) * itw;
float v0 = (y0 - yo) * ith;
float u1 = (x1 - xo) * itw;
float v1 = (y1 - yo) * ith;
CheckQuadBatch();
BufferedTris *quad = &QuadExtra[QuadBatchPos];
FBVERTEX *vert = &VertexData[VertexPos];
quad->ClearSetup();
if (tex->GetTexFormat() == GL_R8 && !tex->IsGray)
{
quad->Flags = BQF_WrapUV | BQF_GamePalette; // | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_PalTex;
}
else
{
quad->Flags = BQF_WrapUV; // | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_Plain;
}
quad->Palette = nullptr;
quad->Texture = tex->Tex.get();
quad->NumVerts = 4;
quad->NumTris = 2;
vert[0].x = x0;
vert[0].y = y0;
vert[0].z = 0;
vert[0].rhw = 1;
vert[0].color0 = 0;
vert[0].color1 = 0xFFFFFFFF;
vert[0].tu = u0;
vert[0].tv = v0;
vert[1].x = x1;
vert[1].y = y0;
vert[1].z = 0;
vert[1].rhw = 1;
vert[1].color0 = 0;
vert[1].color1 = 0xFFFFFFFF;
vert[1].tu = u1;
vert[1].tv = v0;
vert[2].x = x1;
vert[2].y = y1;
vert[2].z = 0;
vert[2].rhw = 1;
vert[2].color0 = 0;
vert[2].color1 = 0xFFFFFFFF;
vert[2].tu = u1;
vert[2].tv = v1;
vert[3].x = x0;
vert[3].y = y1;
vert[3].z = 0;
vert[3].rhw = 1;
vert[3].color0 = 0;
vert[3].color1 = 0xFFFFFFFF;
vert[3].tu = u0;
vert[3].tv = v1;
IndexData[IndexPos] = VertexPos;
IndexData[IndexPos + 1] = VertexPos + 1;
IndexData[IndexPos + 2] = VertexPos + 2;
IndexData[IndexPos + 3] = VertexPos;
IndexData[IndexPos + 4] = VertexPos + 2;
IndexData[IndexPos + 5] = VertexPos + 3;
QuadBatchPos++;
VertexPos += 4;
IndexPos += 6;
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: FillSimplePoly
//
// Here, "simple" means that a simple triangle fan can draw it.
//
//==========================================================================
void OpenGLSWFrameBuffer::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip)
{
// Use an equation similar to player sprites to determine shade
double fadelevel = clamp((swrenderer::LightVisibility::LightLevelToShade(lightlevel, true) / 65536. - 12) / NUMCOLORMAPS, 0.0, 1.0);
BufferedTris *quad;
FBVERTEX *verts;
OpenGLTex *tex;
float uscale, vscale;
int i, ipos;
uint32_t color0, color1;
float ox, oy;
float cosrot, sinrot;
bool dorotate = rotation != 0;
if (npoints < 3)
{ // This is no polygon.
return;
}
if (In2D < 2)
{
Super::FillSimplePoly(texture, points, npoints, originx, originy, scalex, scaley, rotation, colormap, lightlevel, flatcolor, bottomclip);
return;
}
if (!InScene)
{
return;
}
tex = static_cast<OpenGLTex *>(texture->GetNative(texture->GetFormat(), true));
if (tex == nullptr)
{
return;
}
cosrot = (float)cos(rotation.Radians());
sinrot = (float)sin(rotation.Radians());
CheckQuadBatch(npoints - 2, npoints);
quad = &QuadExtra[QuadBatchPos];
verts = &VertexData[VertexPos];
color0 = 0;
color1 = 0xFFFFFFFF;
quad->ClearSetup();
if (tex->GetTexFormat() == GL_R8 && !tex->IsGray)
{
quad->Flags = BQF_WrapUV | BQF_GamePalette | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_PalTex;
if (colormap.Desaturation != 0)
{
quad->Flags |= BQF_Desaturated;
}
quad->ShaderNum = BQS_InGameColormap;
quad->Desat = colormap.Desaturation;
color0 = ColorARGB(255, colormap.LightColor.r, colormap.LightColor.g, colormap.LightColor.b);
color1 = ColorARGB(uint32_t((1 - fadelevel) * 255),
uint32_t(colormap.FadeColor.r * fadelevel),
uint32_t(colormap.FadeColor.g * fadelevel),
uint32_t(colormap.FadeColor.b * fadelevel));
}
else
{
quad->Flags = BQF_WrapUV | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_Plain;
}
quad->Palette = nullptr;
quad->Texture = tex->Tex.get();
quad->NumVerts = npoints;
quad->NumTris = npoints - 2;
uscale = float(1.f / (texture->GetScaledWidth() * scalex));
vscale = float(1.f / (texture->GetScaledHeight() * scaley));
ox = float(originx);
oy = float(originy);
for (i = 0; i < npoints; ++i)
{
verts[i].x = points[i].X;
verts[i].y = points[i].Y;
verts[i].z = 0;
verts[i].rhw = 1;
verts[i].color0 = color0;
verts[i].color1 = color1;
float u = points[i].X - ox;
float v = points[i].Y - oy;
if (dorotate)
{
float t = u;
u = t * cosrot - v * sinrot;
v = v * cosrot + t * sinrot;
}
verts[i].tu = u * uscale;
verts[i].tv = v * vscale;
}
for (ipos = IndexPos, i = 2; i < npoints; ++i, ipos += 3)
{
IndexData[ipos] = VertexPos;
IndexData[ipos + 1] = VertexPos + i - 1;
IndexData[ipos + 2] = VertexPos + i;
}
QuadBatchPos++;
VertexPos += npoints;
IndexPos = ipos;
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: AddColorOnlyQuad
//
// Adds a single-color, untextured quad to the batch.
//
//==========================================================================
void OpenGLSWFrameBuffer::AddColorOnlyQuad(int left, int top, int width, int height, uint32_t color)
{
BufferedTris *quad;
FBVERTEX *verts;
CheckQuadBatch();
quad = &QuadExtra[QuadBatchPos];
verts = &VertexData[VertexPos];
float x = float(left);
float y = float(top);
quad->ClearSetup();
quad->ShaderNum = BQS_ColorOnly;
if ((color & 0xFF000000) != 0xFF000000)
{
quad->BlendOp = GL_FUNC_ADD;
quad->SrcBlend = GL_SRC_ALPHA;
quad->DestBlend = GL_ONE_MINUS_SRC_ALPHA;
}
quad->Palette = nullptr;
quad->Texture = nullptr;
quad->NumVerts = 4;
quad->NumTris = 2;
verts[0].x = x;
verts[0].y = y;
verts[0].z = 0;
verts[0].rhw = 1;
verts[0].color0 = color;
verts[0].color1 = 0;
verts[0].tu = 0;
verts[0].tv = 0;
verts[1].x = x + width;
verts[1].y = y;
verts[1].z = 0;
verts[1].rhw = 1;
verts[1].color0 = color;
verts[1].color1 = 0;
verts[1].tu = 0;
verts[1].tv = 0;
verts[2].x = x + width;
verts[2].y = y + height;
verts[2].z = 0;
verts[2].rhw = 1;
verts[2].color0 = color;
verts[2].color1 = 0;
verts[2].tu = 0;
verts[2].tv = 0;
verts[3].x = x;
verts[3].y = y + height;
verts[3].z = 0;
verts[3].rhw = 1;
verts[3].color0 = color;
verts[3].color1 = 0;
verts[3].tu = 0;
verts[3].tv = 0;
IndexData[IndexPos] = VertexPos;
IndexData[IndexPos + 1] = VertexPos + 1;
IndexData[IndexPos + 2] = VertexPos + 2;
IndexData[IndexPos + 3] = VertexPos;
IndexData[IndexPos + 4] = VertexPos + 2;
IndexData[IndexPos + 5] = VertexPos + 3;
QuadBatchPos++;
VertexPos += 4;
IndexPos += 6;
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: AddColorOnlyRect
//
// Like AddColorOnlyQuad, except it's hollow.
//
//==========================================================================
void OpenGLSWFrameBuffer::AddColorOnlyRect(int left, int top, int width, int height, uint32_t color)
{
AddColorOnlyQuad(left, top, width - 1, 1, color); // top
AddColorOnlyQuad(left + width - 1, top, 1, height - 1, color); // right
AddColorOnlyQuad(left + 1, top + height - 1, width - 1, 1, color); // bottom
AddColorOnlyQuad(left, top + 1, 1, height - 1, color); // left
}
#endif
//==========================================================================
//
@ -2921,199 +2337,6 @@ void OpenGLSWFrameBuffer::EndBatch()
}
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: SetStyle
//
// Patterned after R_SetPatchStyle.
//
//==========================================================================
bool OpenGLSWFrameBuffer::SetStyle(OpenGLTex *tex, DrawParms &parms, uint32_t &color0, uint32_t &color1, BufferedTris &quad)
{
int fmt = tex->GetTexFormat();
FRenderStyle style = parms.style;
float alpha;
bool stencilling;
if (style.Flags & STYLEF_TransSoulsAlpha)
{
alpha = transsouls;
}
else if (style.Flags & STYLEF_Alpha1)
{
alpha = 1;
}
else
{
alpha = clamp(parms.Alpha, 0.f, 1.f);
}
style.CheckFuzz();
if (style.BlendOp == STYLEOP_Shadow)
{
style = LegacyRenderStyles[STYLE_TranslucentStencil];
alpha = 0.3f;
parms.fillcolor = 0;
}
// FIXME: Fuzz effect is not written
if (style.BlendOp == STYLEOP_FuzzOrAdd || style.BlendOp == STYLEOP_Fuzz)
{
style.BlendOp = STYLEOP_Add;
}
else if (style.BlendOp == STYLEOP_FuzzOrSub)
{
style.BlendOp = STYLEOP_Sub;
}
else if (style.BlendOp == STYLEOP_FuzzOrRevSub)
{
style.BlendOp = STYLEOP_RevSub;
}
stencilling = false;
quad.Palette = nullptr;
quad.Flags = 0;
quad.Desat = 0;
switch (style.BlendOp)
{
default:
case STYLEOP_Add: quad.BlendOp = GL_FUNC_ADD; break;
case STYLEOP_Sub: quad.BlendOp = GL_FUNC_SUBTRACT; break;
case STYLEOP_RevSub: quad.BlendOp = GL_FUNC_REVERSE_SUBTRACT; break;
case STYLEOP_None: return false;
}
quad.SrcBlend = GetStyleAlpha(style.SrcAlpha);
quad.DestBlend = GetStyleAlpha(style.DestAlpha);
if (style.Flags & STYLEF_InvertOverlay)
{
// Only the overlay color is inverted, not the overlay alpha.
parms.colorOverlay = ColorARGB(APART(parms.colorOverlay),
255 - RPART(parms.colorOverlay), 255 - GPART(parms.colorOverlay),
255 - BPART(parms.colorOverlay));
}
SetColorOverlay(parms.colorOverlay, alpha, color0, color1);
if (style.Flags & STYLEF_ColorIsFixed)
{
if (style.Flags & STYLEF_InvertSource)
{ // Since the source color is a constant, we can invert it now
// without spending time doing it in the shader.
parms.fillcolor = ColorXRGB(255 - RPART(parms.fillcolor),
255 - GPART(parms.fillcolor), 255 - BPART(parms.fillcolor));
}
// Set up the color mod to replace the color from the image data.
color0 = (color0 & ColorRGBA(0, 0, 0, 255)) | (parms.fillcolor & ColorRGBA(255, 255, 255, 0));
color1 &= ColorRGBA(0, 0, 0, 255);
if (style.Flags & STYLEF_RedIsAlpha)
{
// Note that if the source texture is paletted, the palette is ignored.
quad.Flags = 0;
quad.ShaderNum = BQS_RedToAlpha;
}
else if (fmt == GL_R8)
{
quad.Flags = BQF_GamePalette;
quad.ShaderNum = BQS_PalTex;
}
else
{
quad.Flags = 0;
quad.ShaderNum = BQS_Plain;
}
}
else
{
if (style.Flags & STYLEF_RedIsAlpha)
{
quad.Flags = 0;
quad.ShaderNum = BQS_RedToAlpha;
}
else if (fmt == GL_R8)
{
if (parms.remap != nullptr)
{
quad.Flags = BQF_CustomPalette;
quad.Palette = reinterpret_cast<OpenGLPal *>(parms.remap->GetNative());
quad.ShaderNum = BQS_PalTex;
}
else if (tex->IsGray)
{
quad.Flags = 0;
quad.ShaderNum = BQS_Plain;
}
else
{
quad.Flags = BQF_GamePalette;
quad.ShaderNum = BQS_PalTex;
}
}
else
{
quad.Flags = 0;
quad.ShaderNum = BQS_Plain;
}
if (style.Flags & STYLEF_InvertSource)
{
quad.Flags |= BQF_InvertSource;
}
if (parms.specialcolormap != nullptr)
{ // Emulate an invulnerability or similar colormap.
float *start, *end;
start = parms.specialcolormap->ColorizeStart;
end = parms.specialcolormap->ColorizeEnd;
if (quad.Flags & BQF_InvertSource)
{
quad.Flags &= ~BQF_InvertSource;
swapvalues(start, end);
}
quad.ShaderNum = BQS_SpecialColormap;
color0 = ColorRGBA(uint32_t(start[0] / 2 * 255), uint32_t(start[1] / 2 * 255), uint32_t(start[2] / 2 * 255), color0 >> 24);
color1 = ColorRGBA(uint32_t(end[0] / 2 * 255), uint32_t(end[1] / 2 * 255), uint32_t(end[2] / 2 * 255), color1 >> 24);
}
else if (parms.colormapstyle != nullptr)
{ // Emulate the fading from an in-game colormap (colorized, faded, and desaturated)
if (parms.colormapstyle->Desaturate != 0)
{
quad.Flags |= BQF_Desaturated;
}
quad.ShaderNum = BQS_InGameColormap;
quad.Desat = parms.colormapstyle->Desaturate;
color0 = ColorARGB(color1 >> 24,
parms.colormapstyle->Color.r,
parms.colormapstyle->Color.g,
parms.colormapstyle->Color.b);
double fadelevel = parms.colormapstyle->FadeLevel;
color1 = ColorARGB(uint32_t((1 - fadelevel) * 255),
uint32_t(parms.colormapstyle->Fade.r * fadelevel),
uint32_t(parms.colormapstyle->Fade.g * fadelevel),
uint32_t(parms.colormapstyle->Fade.b * fadelevel));
}
}
// For unmasked images, force the alpha from the image data to be ignored.
if (!parms.masked && quad.ShaderNum != BQS_InGameColormap)
{
color0 = (color0 & ColorRGBA(255, 255, 255, 0)) | ColorValue(0, 0, 0, alpha);
color1 &= ColorRGBA(255, 255, 255, 0);
// If our alpha is one and we are doing normal adding, then we can turn the blend off completely.
if (quad.BlendOp == GL_FUNC_ADD &&
((alpha == 1 && quad.SrcBlend == GL_SRC_ALPHA) || quad.SrcBlend == GL_ONE) &&
((alpha == 1 && quad.DestBlend == GL_ONE_MINUS_SRC_ALPHA) || quad.DestBlend == GL_ZERO))
{
quad.BlendOp = 0;
}
quad.Flags |= BQF_DisableAlphaTest;
}
return true;
}
int OpenGLSWFrameBuffer::GetStyleAlpha(int type)
{
switch (type)
@ -3127,26 +2350,6 @@ int OpenGLSWFrameBuffer::GetStyleAlpha(int type)
}
void OpenGLSWFrameBuffer::SetColorOverlay(uint32_t color, float alpha, uint32_t &color0, uint32_t &color1)
{
if (APART(color) != 0)
{
int a = APART(color) * 256 / 255;
color0 = ColorRGBA(
(RPART(color) * a) >> 8,
(GPART(color) * a) >> 8,
(BPART(color) * a) >> 8,
0);
a = 256 - a;
color1 = ColorRGBA(a, a, a, int(alpha * 255));
}
else
{
color0 = 0;
color1 = ColorValue(1, 1, 1, alpha);
}
}
void OpenGLSWFrameBuffer::EnableAlphaTest(bool enabled)
{
if (enabled != AlphaTestEnabled)

View file

@ -54,13 +54,6 @@ public:
void DrawBlendingRect() override;
FNativeTexture *CreateTexture(FTexture *gametex, FTextureFormat fmt, bool wrapping) override;
FNativePalette *CreatePalette(FRemapTable *remap) override;
void DrawTextureParms(FTexture *img, DrawParms &parms) override;
void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color) override;
void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h) override;
void FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin) override;
void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor) override;
void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor) override;
void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, double originx, double originy, double scalex, double scaley, DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip) override;
bool WipeStartScreen(int type) override;
void WipeEndScreen() override;
bool WipeDo(int ticks) override;
@ -365,11 +358,7 @@ private:
void KillNativeTexs();
void DrawLetterbox(int x, int y, int width, int height);
void Draw3DPart(bool copy3d);
bool SetStyle(OpenGLTex *tex, DrawParms &parms, uint32_t &color0, uint32_t &color1, BufferedTris &quad);
static int GetStyleAlpha(int type);
static void SetColorOverlay(uint32_t color, float alpha, uint32_t &color0, uint32_t &color1);
void AddColorOnlyQuad(int left, int top, int width, int height, uint32_t color);
void AddColorOnlyRect(int left, int top, int width, int height, uint32_t color);
void CheckQuadBatch(int numtris = 2, int numverts = 4);
void BeginQuadBatch();
void EndQuadBatch();

View file

@ -169,8 +169,8 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type)
void OpenGLFrameBuffer::WipeEndScreen()
{
GLRenderer->m2DDrawer->Draw();
GLRenderer->m2DDrawer->Clear();
screen->Draw2D();
screen->Clear2D();
const auto &viewport = GLRenderer->mScreenViewport;
wipeendscreen = new FHardwareTexture(viewport.width, viewport.height, true);

View file

@ -74,6 +74,20 @@ CVAR (Float, snd_menuvolume, 0.6f, CVAR_ARCHIVE)
CVAR(Int, m_use_mouse, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CUSTOM_CVAR(Float, dimamount, -1.f, CVAR_ARCHIVE)
{
if (self < 0.f && self != -1.f)
{
self = -1.f;
}
else if (self > 1.f)
{
self = 1.f;
}
}
CVAR(Color, dimcolor, 0xffd700, CVAR_ARCHIVE)
DEFINE_ACTION_FUNCTION(DMenu, GetCurrentMenu)
{
@ -766,6 +780,41 @@ void M_Ticker (void)
}
}
//==========================================================================
//
// M_Dim
//
// Applies a colored overlay to the entire screen, with the opacity
// determined by the dimamount cvar.
//
//==========================================================================
static void M_Dim()
{
PalEntry dimmer;
float amount;
if (dimamount >= 0)
{
dimmer = PalEntry(dimcolor);
amount = dimamount;
}
else
{
dimmer = gameinfo.dimcolor;
amount = gameinfo.dimamount;
}
if (gameinfo.gametype == GAME_Hexen && gamestate == GS_DEMOSCREEN)
{ // On the Hexen title screen, the default dimming is not
// enough to make the menus readable.
amount = MIN<float>(1.f, amount*2.f);
}
screen->Dim(dimmer, amount, 0, 0, screen->GetWidth(), screen->GetHeight());
}
//=============================================================================
//
//
@ -784,7 +833,7 @@ void M_Drawer (void)
GLRenderer->BlurScene(gameinfo.bluramount);
if (!CurrentMenu->DontDim)
{
screen->Dim(fade);
M_Dim();
V_SetBorderNeedRefresh();
}
CurrentMenu->CallDrawer();

View file

@ -38,7 +38,7 @@
#include "doomtype.h"
#include "vectors.h"
#include "v_palette.h"
#include "v_video.h"
#include "v_colortables.h"
#include "colormatcher.h"
#include "r_data/renderstyle.h"
#include "r_data/r_translate.h"

52
src/v_colortables.h Normal file
View file

@ -0,0 +1,52 @@
#pragma once
// extracted from v_video.h because this caused circular dependencies between v_video.h and textures.h
// Translucency tables
// RGB32k is a normal R5G5B5 -> palette lookup table.
// Use a union so we can "overflow" without warnings.
// Otherwise, we get stuff like this from Clang (when compiled
// with -fsanitize=bounds) while running:
// src/v_video.cpp:390:12: runtime error: index 1068 out of bounds for type 'uint8_t [32]'
// src/r_draw.cpp:273:11: runtime error: index 1057 out of bounds for type 'uint8_t [32]'
union ColorTable32k
{
uint8_t RGB[32][32][32];
uint8_t All[32 *32 *32];
};
extern ColorTable32k RGB32k;
// [SP] RGB666 support
union ColorTable256k
{
uint8_t RGB[64][64][64];
uint8_t All[64 *64 *64];
};
extern ColorTable256k RGB256k;
// Col2RGB8 is a pre-multiplied palette for color lookup. It is stored in a
// special R10B10G10 format for efficient blending computation.
// --RRRRRrrr--BBBBBbbb--GGGGGggg-- at level 64
// --------rrrr------bbbb------gggg at level 1
extern uint32_t Col2RGB8[65][256];
// Col2RGB8_LessPrecision is the same as Col2RGB8, but the LSB for red
// and blue are forced to zero, so if the blend overflows, it won't spill
// over into the next component's value.
// --RRRRRrrr-#BBBBBbbb-#GGGGGggg-- at level 64
// --------rrr#------bbb#------gggg at level 1
extern uint32_t *Col2RGB8_LessPrecision[65];
// Col2RGB8_Inverse is the same as Col2RGB8_LessPrecision, except the source
// palette has been inverted.
extern uint32_t Col2RGB8_Inverse[65][256];
// "Magic" numbers used during the blending:
// --000001111100000111110000011111 = 0x01f07c1f
// -0111111111011111111101111111111 = 0x3FEFFBFF
// -1000000000100000000010000000000 = 0x40100400
// ------10000000001000000000100000 = 0x40100400 >> 5
// --11111-----11111-----11111----- = 0x40100400 - (0x40100400 >> 5) aka "white"
// --111111111111111111111111111111 = 0x3FFFFFFF

View file

@ -59,19 +59,6 @@
#include "textures.h"
#include "vm.h"
CUSTOM_CVAR(Float, dimamount, -1.f, CVAR_ARCHIVE)
{
if (self < 0.f && self != -1.f)
{
self = -1.f;
}
else if (self > 1.f)
{
self = 1.f;
}
}
CVAR(Color, dimcolor, 0xffd700, CVAR_ARCHIVE)
CUSTOM_CVAR(Int, uiscale, 0, CVAR_ARCHIVE | CVAR_NOINITCALL)
{
if (self < 0)
@ -476,6 +463,7 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
parms->colorOverlay = 0;
parms->alphaChannel = false;
parms->flipX = false;
parms->flipY = false;
parms->color = 0xffffffff;
//parms->shadowAlpha = 0;
parms->shadowColor = 0;
@ -492,6 +480,10 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
parms->cellx = parms->celly = 0;
parms->maxstrlen = INT_MAX;
parms->virtBottom = false;
parms->srcx = 0.;
parms->srcy = 0.;
parms->srcwidth = 1.;
parms->srcheight = 1.;
// Parse the tag list for attributes. (For floating point attributes,
// consider that the C ABI dictates that all floats be promoted to
@ -661,6 +653,26 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
parms->flipX = ListGetInt(tags);
break;
case DTA_FlipY:
parms->flipY = ListGetInt(tags);
break;
case DTA_SrcX:
parms->srcx = ListGetDouble(tags) / img->GetScaledWidthDouble();
break;
case DTA_SrcY:
parms->srcy = ListGetDouble(tags) / img->GetScaledHeightDouble();
break;
case DTA_SrcWidth:
parms->srcwidth = ListGetDouble(tags) / img->GetScaledWidthDouble();
break;
case DTA_SrcHeight:
parms->srcheight = ListGetDouble(tags) / img->GetScaledHeightDouble();
break;
case DTA_TopOffset:
assert(fortext == false);
if (fortext) return false;
@ -1029,6 +1041,7 @@ void DFrameBuffer::FillBorder (FTexture *img)
void DFrameBuffer::DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor)
{
m2DDrawer.AddLine(x0, y0, x1, y1, palColor, realcolor);
}
DEFINE_ACTION_FUNCTION(_Screen, DrawLine)
@ -1052,6 +1065,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawLine)
void DFrameBuffer::DrawPixel(int x, int y, int palColor, uint32_t realcolor)
{
m2DDrawer.AddPixel(x, y, palColor, realcolor);
}
//==========================================================================
@ -1062,10 +1076,6 @@ void DFrameBuffer::DrawPixel(int x, int y, int palColor, uint32_t realcolor)
//
//==========================================================================
void DFrameBuffer::DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color)
{
}
void DFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color)
{
if (clipwidth >= 0 && clipheight >= 0)
@ -1090,7 +1100,12 @@ void DFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor,
right = left + w;
bottom = top + h;
}
DoClear(left, top, right, bottom, palcolor, color);
if (palcolor >= 0 && color == 0)
{
color = GPalette.BaseColors[palcolor] | 0xff000000;
}
m2DDrawer.AddColorOnlyQuad(left, top, right - left, bottom - top, color | 0xFF000000);
}
DEFINE_ACTION_FUNCTION(_Screen, Clear)
@ -1115,8 +1130,17 @@ DEFINE_ACTION_FUNCTION(_Screen, Clear)
//
//==========================================================================
void DFrameBuffer::DoDim(PalEntry color, float damount, int x1, int y1, int w, int h)
void DFrameBuffer::DoDim(PalEntry color, float amount, int x1, int y1, int w, int h)
{
if (amount <= 0)
{
return;
}
if (amount > 1)
{
amount = 1;
}
m2DDrawer.AddColorOnlyQuad(x1, y1, w, h, color | (int(amount * 255) << 24));
}
void DFrameBuffer::Dim(PalEntry color, float damount, int x1, int y1, int w, int h)
@ -1175,6 +1199,7 @@ void DFrameBuffer::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley, DAngle rotation,
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip)
{
m2DDrawer.AddPoly(tex, points, npoints, originx, originy, scalex, scaley, rotation, colormap, flatcolor, lightlevel);
}
//==========================================================================
@ -1188,68 +1213,9 @@ void DFrameBuffer::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
void DFrameBuffer::FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin)
{
int w = src->GetWidth();
int h = src->GetHeight();
// Repeatedly draw the texture, left-to-right, top-to-bottom.
for (int y = local_origin ? top : (top / h * h); y < bottom; y += h)
{
for (int x = local_origin ? left : (left / w * w); x < right; x += w)
{
DrawTexture(src, x, y,
DTA_ClipLeft, left,
DTA_ClipRight, right,
DTA_ClipTop, top,
DTA_ClipBottom, bottom,
DTA_TopOffset, 0,
DTA_LeftOffset, 0,
TAG_DONE);
}
}
m2DDrawer.AddFlatFill(left, top, right, bottom, src, local_origin);
}
//==========================================================================
//
// DCanvas :: Dim
//
// Applies a colored overlay to the entire screen, with the opacity
// determined by the dimamount cvar.
//
//==========================================================================
void DFrameBuffer::Dim(PalEntry color)
{
PalEntry dimmer;
float amount;
if (dimamount >= 0)
{
dimmer = PalEntry(dimcolor);
amount = dimamount;
}
else
{
dimmer = gameinfo.dimcolor;
amount = gameinfo.dimamount;
}
if (gameinfo.gametype == GAME_Hexen && gamestate == GS_DEMOSCREEN)
{ // On the Hexen title screen, the default dimming is not
// enough to make the menus readable.
amount = MIN<float>(1.f, amount*2.f);
}
// Add the cvar's dimming on top of the color passed to the function
if (color.a != 0)
{
float dim[4] = { color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f };
V_AddBlend(dimmer.r / 255.f, dimmer.g / 255.f, dimmer.b / 255.f, amount, dim);
dimmer = PalEntry(uint8_t(dim[0] * 255), uint8_t(dim[1] * 255), uint8_t(dim[2] * 255));
amount = dim[3];
}
Dim(dimmer, amount, 0, 0, Width, Height);
}
//==========================================================================
//
// V_SetBorderNeedRefresh

View file

@ -41,6 +41,8 @@
#include "dobject.h"
#include "r_data/renderstyle.h"
#include "c_cvars.h"
#include "v_colortables.h"
#include "v_2ddrawer.h"
extern int CleanWidth, CleanHeight, CleanXfac, CleanYfac;
extern int CleanWidth_1, CleanHeight_1, CleanXfac_1, CleanYfac_1;
@ -129,6 +131,12 @@ enum
// New additions.
DTA_Color,
DTA_FlipY, // bool: flip image vertically
DTA_SrcX, // specify a source rectangle (this supersedes the poorly implemented DTA_WindowLeft/Right
DTA_SrcY,
DTA_SrcWidth,
DTA_SrcHeight
};
enum
@ -162,12 +170,13 @@ struct DrawParms
double top;
double left;
float Alpha;
uint32_t fillcolor;
PalEntry fillcolor;
FRemapTable *remap;
uint32_t colorOverlay;
PalEntry colorOverlay;
PalEntry color;
INTBOOL alphaChannel;
INTBOOL flipX;
INTBOOL flipY;
//float shadowAlpha;
int shadowColor;
INTBOOL keepratio;
@ -181,6 +190,8 @@ struct DrawParms
int maxstrlen;
bool fortext;
bool virtBottom;
double srcx, srcy;
double srcwidth, srcheight;
};
struct Va_List
@ -276,10 +287,11 @@ public:
class DFrameBuffer
{
typedef DSimpleCanvas Super;
F2DDrawer m2DDrawer;
protected:
void DrawTextureV(FTexture *img, double x, double y, uint32_t tag, va_list tags) = delete;
virtual void DrawTextureParms(FTexture *img, DrawParms &parms);
void DrawTextureParms(FTexture *img, DrawParms &parms);
template<class T>
bool ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, bool fortext) const;
@ -394,30 +406,30 @@ public:
void SetClipRect(int x, int y, int w, int h);
void GetClipRect(int *x, int *y, int *w, int *h);
// Dim the entire canvas for the menus
virtual void Dim(PalEntry color = 0);
virtual void Draw2D() {}
void Clear2D() { m2DDrawer.Clear(); }
// Dim part of the canvas
virtual void Dim(PalEntry color, float amount, int x1, int y1, int w, int h) final;
virtual void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h);
void Dim(PalEntry color, float amount, int x1, int y1, int w, int h);
void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h);
// Fill an area with a texture
virtual void FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin = false);
void FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin = false);
// Fill a simple polygon with a texture
virtual void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley, DAngle rotation,
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
// Set an area to a specified color
virtual void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) final;
virtual void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color);
void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color);
// Draws a line
virtual void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor);
void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor);
// Draws a single pixel
virtual void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor);
void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor);
bool SetTextureParms(DrawParms *parms, FTexture *img, double x, double y) const;
void DrawTexture(FTexture *img, double x, double y, int tags, ...);
@ -482,54 +494,6 @@ extern DFrameBuffer *screen;
EXTERN_CVAR (Float, Gamma)
// Translucency tables
// RGB32k is a normal R5G5B5 -> palette lookup table.
// Use a union so we can "overflow" without warnings.
// Otherwise, we get stuff like this from Clang (when compiled
// with -fsanitize=bounds) while running:
// src/v_video.cpp:390:12: runtime error: index 1068 out of bounds for type 'uint8_t [32]'
// src/r_draw.cpp:273:11: runtime error: index 1057 out of bounds for type 'uint8_t [32]'
union ColorTable32k
{
uint8_t RGB[32][32][32];
uint8_t All[32 *32 *32];
};
extern ColorTable32k RGB32k;
// [SP] RGB666 support
union ColorTable256k
{
uint8_t RGB[64][64][64];
uint8_t All[64 *64 *64];
};
extern ColorTable256k RGB256k;
// Col2RGB8 is a pre-multiplied palette for color lookup. It is stored in a
// special R10B10G10 format for efficient blending computation.
// --RRRRRrrr--BBBBBbbb--GGGGGggg-- at level 64
// --------rrrr------bbbb------gggg at level 1
extern uint32_t Col2RGB8[65][256];
// Col2RGB8_LessPrecision is the same as Col2RGB8, but the LSB for red
// and blue are forced to zero, so if the blend overflows, it won't spill
// over into the next component's value.
// --RRRRRrrr-#BBBBBbbb-#GGGGGggg-- at level 64
// --------rrr#------bbb#------gggg at level 1
extern uint32_t *Col2RGB8_LessPrecision[65];
// Col2RGB8_Inverse is the same as Col2RGB8_LessPrecision, except the source
// palette has been inverted.
extern uint32_t Col2RGB8_Inverse[65][256];
// "Magic" numbers used during the blending:
// --000001111100000111110000011111 = 0x01f07c1f
// -0111111111011111111101111111111 = 0x3FEFFBFF
// -1000000000100000000010000000000 = 0x40100400
// ------10000000001000000000100000 = 0x40100400 >> 5
// --11111-----11111-----11111----- = 0x40100400 - (0x40100400 >> 5) aka "white"
// --111111111111111111111111111111 = 0x3FFFFFFF
// Allocates buffer screens, call before R_Init.
void V_Init (bool restart);

View file

@ -1785,65 +1785,6 @@ FNativePalette *D3DFB::CreatePalette(FRemapTable *remap)
return tex;
}
//==========================================================================
//
// D3DFB :: Clear
//
// Fills the specified region with a color.
//
//==========================================================================
void D3DFB::DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color)
{
if (In2D < 2)
{
Super::DoClear(left, top, right, bottom, palcolor, color);
return;
}
if (!InScene)
{
return;
}
if (palcolor >= 0 && color == 0)
{
color = GPalette.BaseColors[palcolor];
}
else if (APART(color) < 255)
{
Dim(color, APART(color)/255.f, left, top, right - left, bottom - top);
return;
}
AddColorOnlyQuad(left, top, right - left, bottom - top, color | 0xFF000000);
}
//==========================================================================
//
// D3DFB :: Dim
//
//==========================================================================
void D3DFB::DoDim (PalEntry color, float amount, int x1, int y1, int w, int h)
{
if (amount <= 0)
{
return;
}
if (In2D < 2)
{
Super::DoDim(color, amount, x1, y1, w, h);
return;
}
if (!InScene)
{
return;
}
if (amount > 1)
{
amount = 1;
}
AddColorOnlyQuad(x1, y1, w, h, color | (int(amount * 255) << 24));
}
//==========================================================================
//
// D3DFB :: BeginLineBatch
@ -1886,53 +1827,6 @@ void D3DFB::EndLineBatch()
BatchType = BATCH_None;
}
//==========================================================================
//
// D3DFB :: DrawLine
//
//==========================================================================
void D3DFB::DrawLine(int x0, int y0, int x1, int y1, int palcolor, uint32_t color)
{
if (In2D < 2)
{
Super::DrawLine(x0, y0, x1, y1, palcolor, color);
return;
}
if (!InScene)
{
return;
}
if (BatchType != BATCH_Lines)
{
BeginLineBatch();
}
if (VertexPos == NUM_VERTS)
{ // Flush the buffer and refill it.
EndLineBatch();
BeginLineBatch();
}
// Add the endpoints to the vertex buffer.
VertexData[VertexPos].x = float(x0);
VertexData[VertexPos].y = float(y0) + LBOffset;
VertexData[VertexPos].z = 0;
VertexData[VertexPos].rhw = 1;
VertexData[VertexPos].color0 = color;
VertexData[VertexPos].color1 = 0;
VertexData[VertexPos].tu = 0;
VertexData[VertexPos].tv = 0;
VertexData[VertexPos+1].x = float(x1);
VertexData[VertexPos+1].y = float(y1) + LBOffset;
VertexData[VertexPos+1].z = 0;
VertexData[VertexPos+1].rhw = 1;
VertexData[VertexPos+1].color0 = color;
VertexData[VertexPos+1].color1 = 0;
VertexData[VertexPos+1].tu = 0;
VertexData[VertexPos+1].tv = 0;
VertexPos += 2;
}
//==========================================================================
//
@ -1940,6 +1834,7 @@ void D3DFB::DrawLine(int x0, int y0, int x1, int y1, int palcolor, uint32_t colo
//
//==========================================================================
#if 0
void D3DFB::DrawPixel(int x, int y, int palcolor, uint32_t color)
{
if (In2D < 2)
@ -1960,512 +1855,7 @@ void D3DFB::DrawPixel(int x, int y, int palcolor, uint32_t color)
SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
D3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &pt, sizeof(FBVERTEX));
}
//==========================================================================
//
// D3DFB :: DrawTextureV
//
// If not in 2D mode, just call the normal software version.
// If in 2D mode, then use Direct3D calls to perform the drawing.
//
//==========================================================================
void D3DFB::DrawTextureParms (FTexture *img, DrawParms &parms)
{
if (In2D < 2)
{
Super::DrawTextureParms(img, parms);
return;
}
if (!InScene)
{
return;
}
FTextureFormat fmt;
if (parms.style.Flags & STYLEF_RedIsAlpha) fmt = TEX_Gray;
else if (parms.remap != nullptr) fmt = TEX_Pal;
else fmt = img->GetFormat();
D3DTex *tex = static_cast<D3DTex *>(img->GetNative(fmt, false));
if (tex == NULL)
{
assert(tex != NULL);
return;
}
CheckQuadBatch();
double xscale = parms.destwidth / parms.texwidth;
double yscale = parms.destheight / parms.texheight;
double x0 = parms.x - parms.left * xscale;
double y0 = parms.y - parms.top * yscale;
double x1 = x0 + parms.destwidth;
double y1 = y0 + parms.destheight;
float u0 = 0;
float v0 = 0;
float u1 = 1;
float v1 = 1;
double uscale = 1.f;
bool scissoring = false;
FBVERTEX *vert;
float yoffs;
if (parms.flipX)
{
swapvalues(u0, u1);
}
if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
{
double wi = MIN(parms.windowright, parms.texwidth);
x0 += parms.windowleft * xscale;
u0 = float(u0 + parms.windowleft * uscale);
x1 -= (parms.texwidth - wi) * xscale;
u1 = float(u1 - (parms.texwidth - wi) * uscale);
}
// Use a scissor test because the math above introduces some jitter
// that is noticeable at low resolutions.
if (y0 < parms.uclip || y1 > parms.dclip || x0 < parms.lclip || x1 > parms.rclip)
{
scissoring = true;
if (QuadBatchPos > 0)
{
EndQuadBatch();
BeginQuadBatch();
}
RECT scissor = {
parms.lclip, parms.uclip + LBOffsetI,
parms.rclip, parms.dclip + LBOffsetI
};
D3DDevice->SetScissorRect(&scissor);
D3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
}
parms.bilinear = false;
D3DCOLOR color0, color1;
BufferedTris *quad = &QuadExtra[QuadBatchPos];
if (!SetStyle(tex, parms, color0, color1, *quad))
{
goto done;
}
quad->Texture = tex->Tex;
if (parms.bilinear)
{
quad->Flags |= BQF_Bilinear;
}
quad->NumTris = 2;
quad->NumVerts = 4;
yoffs = GatheringWipeScreen ? 0.5f : 0.5f - LBOffset;
x0 = x0 - 0.5f;
y0 = y0 - yoffs;
x1 = x1 - 0.5f;
y1 = y1 - yoffs;
vert = &VertexData[VertexPos];
{
PalEntry color = color1;
color = PalEntry((color.a * parms.color.a) / 255, (color.r * parms.color.r) / 255, (color.g * parms.color.g) / 255, (color.b * parms.color.b) / 255);
color1 = color;
}
// Fill the vertex buffer.
vert[0].x = float(x0);
vert[0].y = float(y0);
vert[0].z = 0;
vert[0].rhw = 1;
vert[0].color0 = color0;
vert[0].color1 = color1;
vert[0].tu = u0;
vert[0].tv = v0;
vert[1].x = float(x1);
vert[1].y = float(y0);
vert[1].z = 0;
vert[1].rhw = 1;
vert[1].color0 = color0;
vert[1].color1 = color1;
vert[1].tu = u1;
vert[1].tv = v0;
vert[2].x = float(x1);
vert[2].y = float(y1);
vert[2].z = 0;
vert[2].rhw = 1;
vert[2].color0 = color0;
vert[2].color1 = color1;
vert[2].tu = u1;
vert[2].tv = v1;
vert[3].x = float(x0);
vert[3].y = float(y1);
vert[3].z = 0;
vert[3].rhw = 1;
vert[3].color0 = color0;
vert[3].color1 = color1;
vert[3].tu = u0;
vert[3].tv = v1;
// Fill the vertex index buffer.
IndexData[IndexPos ] = VertexPos;
IndexData[IndexPos + 1] = VertexPos + 1;
IndexData[IndexPos + 2] = VertexPos + 2;
IndexData[IndexPos + 3] = VertexPos;
IndexData[IndexPos + 4] = VertexPos + 2;
IndexData[IndexPos + 5] = VertexPos + 3;
// Batch the quad.
QuadBatchPos++;
VertexPos += 4;
IndexPos += 6;
done:
if (scissoring)
{
EndQuadBatch();
D3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
}
}
//==========================================================================
//
// D3DFB :: FlatFill
//
// Fills an area with a repeating copy of the texture.
//
//==========================================================================
void D3DFB::FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin)
{
if (In2D < 2)
{
Super::FlatFill(left, top, right, bottom, src, local_origin);
return;
}
if (!InScene)
{
return;
}
D3DTex *tex = static_cast<D3DTex *>(src->GetNative(src->GetFormat(), true));
if (tex == NULL)
{
return;
}
float yoffs = GatheringWipeScreen ? 0.5f : 0.5f - LBOffset;
float x0 = float(left);
float y0 = float(top);
float x1 = float(right);
float y1 = float(bottom);
float itw = 1.f / float(src->GetWidth());
float ith = 1.f / float(src->GetHeight());
float xo = local_origin ? x0 : 0;
float yo = local_origin ? y0 : 0;
float u0 = (x0 - xo) * itw;
float v0 = (y0 - yo) * ith;
float u1 = (x1 - xo) * itw;
float v1 = (y1 - yo) * ith;
x0 -= 0.5f;
y0 -= yoffs;
x1 -= 0.5f;
y1 -= yoffs;
CheckQuadBatch();
BufferedTris *quad = &QuadExtra[QuadBatchPos];
FBVERTEX *vert = &VertexData[VertexPos];
quad->Group1 = 0;
if (tex->GetTexFormat() == D3DFMT_L8 && !tex->IsGray)
{
quad->Flags = BQF_WrapUV | BQF_GamePalette; // | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_PalTex;
}
else
{
quad->Flags = BQF_WrapUV; // | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_Plain;
}
quad->Palette = NULL;
quad->Texture = tex->Tex;
quad->NumVerts = 4;
quad->NumTris = 2;
vert[0].x = x0;
vert[0].y = y0;
vert[0].z = 0;
vert[0].rhw = 1;
vert[0].color0 = 0;
vert[0].color1 = 0xFFFFFFFF;
vert[0].tu = u0;
vert[0].tv = v0;
vert[1].x = x1;
vert[1].y = y0;
vert[1].z = 0;
vert[1].rhw = 1;
vert[1].color0 = 0;
vert[1].color1 = 0xFFFFFFFF;
vert[1].tu = u1;
vert[1].tv = v0;
vert[2].x = x1;
vert[2].y = y1;
vert[2].z = 0;
vert[2].rhw = 1;
vert[2].color0 = 0;
vert[2].color1 = 0xFFFFFFFF;
vert[2].tu = u1;
vert[2].tv = v1;
vert[3].x = x0;
vert[3].y = y1;
vert[3].z = 0;
vert[3].rhw = 1;
vert[3].color0 = 0;
vert[3].color1 = 0xFFFFFFFF;
vert[3].tu = u0;
vert[3].tv = v1;
IndexData[IndexPos ] = VertexPos;
IndexData[IndexPos + 1] = VertexPos + 1;
IndexData[IndexPos + 2] = VertexPos + 2;
IndexData[IndexPos + 3] = VertexPos;
IndexData[IndexPos + 4] = VertexPos + 2;
IndexData[IndexPos + 5] = VertexPos + 3;
QuadBatchPos++;
VertexPos += 4;
IndexPos += 6;
}
//==========================================================================
//
// D3DFB :: FillSimplePoly
//
// Here, "simple" means that a simple triangle fan can draw it.
//
// Bottomclip is ignored by this implementation, since the hardware renderer
// will unconditionally draw the status bar border every frame on top of the
// polygons, so there's no need to waste time setting up a special scissor
// rectangle here and needlessly forcing separate batches.
//
//==========================================================================
void D3DFB::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip)
{
// Use an equation similar to player sprites to determine shade
double fadelevel = clamp((swrenderer::LightVisibility::LightLevelToShade(lightlevel, true)/65536. - 12) / NUMCOLORMAPS, 0.0, 1.0);
BufferedTris *quad;
FBVERTEX *verts;
D3DTex *tex;
float yoffs, uscale, vscale;
int i, ipos;
D3DCOLOR color0, color1;
float ox, oy;
float cosrot, sinrot;
bool dorotate = rotation != 0;
if (npoints < 3)
{ // This is no polygon.
return;
}
if (In2D < 2)
{
Super::FillSimplePoly(texture, points, npoints, originx, originy, scalex, scaley, rotation, colormap, flatcolor, lightlevel, bottomclip);
return;
}
if (!InScene)
{
return;
}
tex = static_cast<D3DTex *>(texture->GetNative(texture->GetFormat(), true));
if (tex == NULL)
{
return;
}
cosrot = (float)cos(rotation.Radians());
sinrot = (float)sin(rotation.Radians());
CheckQuadBatch(npoints - 2, npoints);
quad = &QuadExtra[QuadBatchPos];
verts = &VertexData[VertexPos];
color0 = 0;
color1 = 0xFFFFFFFF;
quad->Group1 = 0;
if (tex->GetTexFormat() == D3DFMT_L8 && !tex->IsGray)
{
quad->Flags = BQF_WrapUV | BQF_GamePalette | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_PalTex;
if (colormap.Desaturation != 0)
{
quad->Flags |= BQF_Desaturated;
}
quad->ShaderNum = BQS_InGameColormap;
quad->Desat = colormap.Desaturation;
color0 = D3DCOLOR_ARGB(255, colormap.LightColor.r, colormap.LightColor.g, colormap.LightColor.b);
color1 = D3DCOLOR_ARGB(DWORD((1 - fadelevel) * 255),
DWORD(colormap.FadeColor.r * fadelevel),
DWORD(colormap.FadeColor.g * fadelevel),
DWORD(colormap.FadeColor.b * fadelevel));
}
else
{
quad->Flags = BQF_WrapUV | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_Plain;
}
quad->Palette = NULL;
quad->Texture = tex->Tex;
quad->NumVerts = npoints;
quad->NumTris = npoints - 2;
yoffs = GatheringWipeScreen ? 0 : LBOffset;
uscale = float(1.f / (texture->GetScaledWidth() * scalex));
vscale = float(1.f / (texture->GetScaledHeight() * scaley));
ox = float(originx);
oy = float(originy);
for (i = 0; i < npoints; ++i)
{
verts[i].x = points[i].X;
verts[i].y = points[i].Y + yoffs;
verts[i].z = 0;
verts[i].rhw = 1;
verts[i].color0 = color0;
verts[i].color1 = color1;
float u = points[i].X - 0.5f - ox;
float v = points[i].Y - 0.5f - oy;
if (dorotate)
{
float t = u;
u = t * cosrot - v * sinrot;
v = v * cosrot + t * sinrot;
}
verts[i].tu = u * uscale;
verts[i].tv = v * vscale;
}
for (ipos = IndexPos, i = 2; i < npoints; ++i, ipos += 3)
{
IndexData[ipos ] = VertexPos;
IndexData[ipos + 1] = VertexPos + i - 1;
IndexData[ipos + 2] = VertexPos + i;
}
QuadBatchPos++;
VertexPos += npoints;
IndexPos = ipos;
}
//==========================================================================
//
// D3DFB :: AddColorOnlyQuad
//
// Adds a single-color, untextured quad to the batch.
//
//==========================================================================
void D3DFB::AddColorOnlyQuad(int left, int top, int width, int height, D3DCOLOR color)
{
BufferedTris *quad;
FBVERTEX *verts;
CheckQuadBatch();
quad = &QuadExtra[QuadBatchPos];
verts = &VertexData[VertexPos];
float x = float(left) - 0.5f;
float y = float(top) - 0.5f + (GatheringWipeScreen ? 0 : LBOffset);
quad->Group1 = 0;
quad->ShaderNum = BQS_ColorOnly;
if ((color & 0xFF000000) != 0xFF000000)
{
quad->BlendOp = D3DBLENDOP_ADD;
quad->SrcBlend = D3DBLEND_SRCALPHA;
quad->DestBlend = D3DBLEND_INVSRCALPHA;
}
quad->Palette = NULL;
quad->Texture = NULL;
quad->NumVerts = 4;
quad->NumTris = 2;
verts[0].x = x;
verts[0].y = y;
verts[0].z = 0;
verts[0].rhw = 1;
verts[0].color0 = color;
verts[0].color1 = 0;
verts[0].tu = 0;
verts[0].tv = 0;
verts[1].x = x + width;
verts[1].y = y;
verts[1].z = 0;
verts[1].rhw = 1;
verts[1].color0 = color;
verts[1].color1 = 0;
verts[1].tu = 0;
verts[1].tv = 0;
verts[2].x = x + width;
verts[2].y = y + height;
verts[2].z = 0;
verts[2].rhw = 1;
verts[2].color0 = color;
verts[2].color1 = 0;
verts[2].tu = 0;
verts[2].tv = 0;
verts[3].x = x;
verts[3].y = y + height;
verts[3].z = 0;
verts[3].rhw = 1;
verts[3].color0 = color;
verts[3].color1 = 0;
verts[3].tu = 0;
verts[3].tv = 0;
IndexData[IndexPos ] = VertexPos;
IndexData[IndexPos + 1] = VertexPos + 1;
IndexData[IndexPos + 2] = VertexPos + 2;
IndexData[IndexPos + 3] = VertexPos;
IndexData[IndexPos + 4] = VertexPos + 2;
IndexData[IndexPos + 5] = VertexPos + 3;
QuadBatchPos++;
VertexPos += 4;
IndexPos += 6;
}
//==========================================================================
//
// D3DFB :: AddColorOnlyRect
//
// Like AddColorOnlyQuad, except it's hollow.
//
//==========================================================================
void D3DFB::AddColorOnlyRect(int left, int top, int width, int height, D3DCOLOR color)
{
AddColorOnlyQuad(left, top, width - 1, 1, color); // top
AddColorOnlyQuad(left + width - 1, top, 1, height - 1, color); // right
AddColorOnlyQuad(left + 1, top + height - 1, width - 1, 1, color); // bottom
AddColorOnlyQuad(left, top + 1, 1, height - 1, color); // left
}
#endif
//==========================================================================
//
@ -2690,199 +2080,6 @@ void D3DFB::EndBatch()
}
}
//==========================================================================
//
// D3DFB :: SetStyle
//
// Patterned after R_SetPatchStyle.
//
//==========================================================================
bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms, D3DCOLOR &color0, D3DCOLOR &color1, BufferedTris &quad)
{
D3DFORMAT fmt = tex->GetTexFormat();
FRenderStyle style = parms.style;
float alpha;
bool stencilling;
if (style.Flags & STYLEF_TransSoulsAlpha)
{
alpha = transsouls;
}
else if (style.Flags & STYLEF_Alpha1)
{
alpha = 1;
}
else
{
alpha = clamp(parms.Alpha, 0.f, 1.f);
}
style.CheckFuzz();
if (style.BlendOp == STYLEOP_Shadow)
{
style = LegacyRenderStyles[STYLE_TranslucentStencil];
alpha = 0.3f;
parms.fillcolor = 0;
}
// FIXME: Fuzz effect is not written
if (style.BlendOp == STYLEOP_FuzzOrAdd || style.BlendOp == STYLEOP_Fuzz)
{
style.BlendOp = STYLEOP_Add;
}
else if (style.BlendOp == STYLEOP_FuzzOrSub)
{
style.BlendOp = STYLEOP_Sub;
}
else if (style.BlendOp == STYLEOP_FuzzOrRevSub)
{
style.BlendOp = STYLEOP_RevSub;
}
stencilling = false;
quad.Palette = NULL;
quad.Flags = 0;
quad.Desat = 0;
switch (style.BlendOp)
{
default:
case STYLEOP_Add: quad.BlendOp = D3DBLENDOP_ADD; break;
case STYLEOP_Sub: quad.BlendOp = D3DBLENDOP_SUBTRACT; break;
case STYLEOP_RevSub: quad.BlendOp = D3DBLENDOP_REVSUBTRACT; break;
case STYLEOP_None: return false;
}
quad.SrcBlend = GetStyleAlpha(style.SrcAlpha);
quad.DestBlend = GetStyleAlpha(style.DestAlpha);
if (style.Flags & STYLEF_InvertOverlay)
{
// Only the overlay color is inverted, not the overlay alpha.
parms.colorOverlay = D3DCOLOR_ARGB(APART(parms.colorOverlay),
255 - RPART(parms.colorOverlay), 255 - GPART(parms.colorOverlay),
255 - BPART(parms.colorOverlay));
}
SetColorOverlay(parms.colorOverlay, alpha, color0, color1);
if (style.Flags & STYLEF_ColorIsFixed)
{
if (style.Flags & STYLEF_InvertSource)
{ // Since the source color is a constant, we can invert it now
// without spending time doing it in the shader.
parms.fillcolor = D3DCOLOR_XRGB(255 - RPART(parms.fillcolor),
255 - GPART(parms.fillcolor), 255 - BPART(parms.fillcolor));
}
// Set up the color mod to replace the color from the image data.
color0 = (color0 & D3DCOLOR_RGBA(0,0,0,255)) | (parms.fillcolor & D3DCOLOR_RGBA(255,255,255,0));
color1 &= D3DCOLOR_RGBA(0,0,0,255);
if (style.Flags & STYLEF_RedIsAlpha)
{
// Note that if the source texture is paletted, the palette is ignored.
quad.Flags = 0;
quad.ShaderNum = BQS_RedToAlpha;
}
else if (fmt == D3DFMT_L8)
{
quad.Flags = BQF_GamePalette;
quad.ShaderNum = BQS_PalTex;
}
else
{
quad.Flags = 0;
quad.ShaderNum = BQS_Plain;
}
}
else
{
if (style.Flags & STYLEF_RedIsAlpha)
{
quad.Flags = 0;
quad.ShaderNum = BQS_RedToAlpha;
}
else if (fmt == D3DFMT_L8)
{
if (parms.remap != NULL)
{
quad.Flags = BQF_CustomPalette;
quad.Palette = reinterpret_cast<D3DPal *>(parms.remap->GetNative());
quad.ShaderNum = BQS_PalTex;
}
else if (tex->IsGray)
{
quad.Flags = 0;
quad.ShaderNum = BQS_Plain;
}
else
{
quad.Flags = BQF_GamePalette;
quad.ShaderNum = BQS_PalTex;
}
}
else
{
quad.Flags = 0;
quad.ShaderNum = BQS_Plain;
}
if (style.Flags & STYLEF_InvertSource)
{
quad.Flags |= BQF_InvertSource;
}
if (parms.specialcolormap != NULL)
{ // Emulate an invulnerability or similar colormap.
float *start, *end;
start = parms.specialcolormap->ColorizeStart;
end = parms.specialcolormap->ColorizeEnd;
if (quad.Flags & BQF_InvertSource)
{
quad.Flags &= ~BQF_InvertSource;
swapvalues(start, end);
}
quad.ShaderNum = BQS_SpecialColormap;
color0 = D3DCOLOR_RGBA(DWORD(start[0]/2*255), DWORD(start[1]/2*255), DWORD(start[2]/2*255), color0 >> 24);
color1 = D3DCOLOR_RGBA(DWORD(end[0]/2*255), DWORD(end[1]/2*255), DWORD(end[2]/2*255), color1 >> 24);
}
else if (parms.colormapstyle != NULL)
{ // Emulate the fading from an in-game colormap (colorized, faded, and desaturated)
if (parms.colormapstyle->Desaturate != 0)
{
quad.Flags |= BQF_Desaturated;
}
quad.ShaderNum = BQS_InGameColormap;
quad.Desat = parms.colormapstyle->Desaturate;
color0 = D3DCOLOR_ARGB(color1 >> 24,
parms.colormapstyle->Color.r,
parms.colormapstyle->Color.g,
parms.colormapstyle->Color.b);
double fadelevel = parms.colormapstyle->FadeLevel;
color1 = D3DCOLOR_ARGB(DWORD((1 - fadelevel) * 255),
DWORD(parms.colormapstyle->Fade.r * fadelevel),
DWORD(parms.colormapstyle->Fade.g * fadelevel),
DWORD(parms.colormapstyle->Fade.b * fadelevel));
}
}
// For unmasked images, force the alpha from the image data to be ignored.
if (!parms.masked && quad.ShaderNum != BQS_InGameColormap)
{
color0 = (color0 & D3DCOLOR_RGBA(255, 255, 255, 0)) | D3DCOLOR_COLORVALUE(0, 0, 0, alpha);
color1 &= D3DCOLOR_RGBA(255, 255, 255, 0);
// If our alpha is one and we are doing normal adding, then we can turn the blend off completely.
if (quad.BlendOp == D3DBLENDOP_ADD &&
((alpha == 1 && quad.SrcBlend == D3DBLEND_SRCALPHA) || quad.SrcBlend == D3DBLEND_ONE) &&
((alpha == 1 && quad.DestBlend == D3DBLEND_INVSRCALPHA) || quad.DestBlend == D3DBLEND_ZERO))
{
quad.BlendOp = D3DBLENDOP(0);
}
quad.Flags |= BQF_DisableAlphaTest;
}
return true;
}
D3DBLEND D3DFB::GetStyleAlpha(int type)
{
switch (type)
@ -2896,26 +2093,6 @@ D3DBLEND D3DFB::GetStyleAlpha(int type)
}
void D3DFB::SetColorOverlay(DWORD color, float alpha, D3DCOLOR &color0, D3DCOLOR &color1)
{
if (APART(color) != 0)
{
int a = APART(color) * 256 / 255;
color0 = D3DCOLOR_RGBA(
(RPART(color) * a) >> 8,
(GPART(color) * a) >> 8,
(BPART(color) * a) >> 8,
0);
a = 256 - a;
color1 = D3DCOLOR_RGBA(a, a, a, int(alpha * 255));
}
else
{
color0 = 0;
color1 = D3DCOLOR_COLORVALUE(1, 1, 1, alpha);
}
}
void D3DFB::EnableAlphaTest(BOOL enabled)
{
if (enabled != AlphaTestEnabled)

View file

@ -47,15 +47,6 @@ public:
void DrawBlendingRect ();
FNativeTexture *CreateTexture (FTexture *gametex, FTextureFormat fmt, bool wrapping);
FNativePalette *CreatePalette (FRemapTable *remap);
void DrawTextureParms (FTexture *img, DrawParms &parms);
void DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color);
void DoDim (PalEntry color, float amount, int x1, int y1, int w, int h);
void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin);
void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor);
void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor);
void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip) override;
bool WipeStartScreen(int type);
void WipeEndScreen();
bool WipeDo(int ticks);
@ -156,12 +147,9 @@ private:
PackedTexture *AllocPackedTexture(int width, int height, bool wrapping, D3DFORMAT format);
void DrawLetterbox();
void Draw3DPart(bool copy3d);
bool SetStyle(D3DTex *tex, DrawParms &parms, D3DCOLOR &color0, D3DCOLOR &color1, BufferedTris &quad);
static D3DBLEND GetStyleAlpha(int type);
static void SetColorOverlay(DWORD color, float alpha, D3DCOLOR &color0, D3DCOLOR &color1);
void DoWindowedGamma();
void AddColorOnlyQuad(int left, int top, int width, int height, D3DCOLOR color);
void AddColorOnlyRect(int left, int top, int width, int height, D3DCOLOR color);
void CheckQuadBatch(int numtris=2, int numverts=4);
void BeginQuadBatch();
void EndQuadBatch();

View file

@ -155,6 +155,14 @@ enum DrawTextureTags
DTA_TextLen, // stop after this many characters, even if \0 not hit
DTA_CellX, // horizontal size of character cell
DTA_CellY, // vertical size of character cell
DTA_Color,
DTA_FlipY, // bool: flip image vertically
DTA_SrcX, // specify a source rectangle (this supersedes the poorly implemented DTA_WindowLeft/Right
DTA_SrcY,
DTA_SrcWidth,
DTA_SrcHeight
};
struct Screen native