2019-11-05 22:35:38 +00:00
|
|
|
/*
|
2020-01-02 18:38:47 +00:00
|
|
|
** hw_draw2d.cpp
|
|
|
|
** 2d drawer Renderer interface
|
|
|
|
**
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
** Copyright 2018-2019 Christoph Oelckers
|
|
|
|
** All rights reserved.
|
|
|
|
**
|
|
|
|
** Redistribution and use in source and binary forms, with or without
|
|
|
|
** modification, are permitted provided that the following conditions
|
|
|
|
** are met:
|
|
|
|
**
|
|
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer.
|
|
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
|
|
** documentation and/or other materials provided with the distribution.
|
|
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
|
|
** derived from this software without specific prior written permission.
|
|
|
|
**
|
|
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
**---------------------------------------------------------------------------
|
2019-11-05 22:35:38 +00:00
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
2020-01-02 18:38:47 +00:00
|
|
|
|
2019-11-05 22:35:38 +00:00
|
|
|
#include "cmdlib.h"
|
|
|
|
#include "gl_buffers.h"
|
|
|
|
#include "v_2ddrawer.h"
|
|
|
|
#include "c_cvars.h"
|
|
|
|
#include "glbackend.h"
|
|
|
|
#include "v_draw.h"
|
2019-11-10 14:15:14 +00:00
|
|
|
#include "palette.h"
|
2020-01-18 12:23:01 +00:00
|
|
|
#include "flatvertices.h"
|
2020-05-23 12:36:35 +00:00
|
|
|
#include "build.h"
|
2019-11-05 22:35:38 +00:00
|
|
|
|
2019-12-29 20:36:21 +00:00
|
|
|
extern int16_t numshades;
|
2020-01-19 22:27:59 +00:00
|
|
|
extern TArray<VSMatrix> matrixArray;
|
|
|
|
|
2019-11-05 22:35:38 +00:00
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Vertex buffer for 2D drawer
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
class F2DVertexBuffer
|
|
|
|
{
|
|
|
|
IVertexBuffer *mVertexBuffer;
|
|
|
|
IIndexBuffer *mIndexBuffer;
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
F2DVertexBuffer()
|
|
|
|
{
|
|
|
|
mVertexBuffer = new OpenGLRenderer::GLVertexBuffer();
|
|
|
|
mIndexBuffer = new OpenGLRenderer::GLIndexBuffer();
|
|
|
|
|
|
|
|
static const FVertexBufferAttribute format[] = {
|
|
|
|
{ 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(F2DDrawer::TwoDVertex, x) },
|
|
|
|
{ 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(F2DDrawer::TwoDVertex, u) },
|
|
|
|
{ 0, VATTR_COLOR, VFmt_Byte4, (int)myoffsetof(F2DDrawer::TwoDVertex, color0) }
|
|
|
|
};
|
|
|
|
mVertexBuffer->SetFormat(1, 3, sizeof(F2DDrawer::TwoDVertex), format);
|
|
|
|
}
|
|
|
|
~F2DVertexBuffer()
|
|
|
|
{
|
|
|
|
delete mIndexBuffer;
|
|
|
|
delete mVertexBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UploadData(F2DDrawer::TwoDVertex *vertices, int vertcount, int *indices, int indexcount)
|
|
|
|
{
|
|
|
|
mVertexBuffer->SetData(vertcount * sizeof(*vertices), vertices, false);
|
|
|
|
mIndexBuffer->SetData(indexcount * sizeof(unsigned int), indices, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<IVertexBuffer *, IIndexBuffer *> GetBufferObjects() const
|
|
|
|
{
|
|
|
|
return std::make_pair(mVertexBuffer, mIndexBuffer);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Draws the 2D stuff. This is the version for OpenGL 3 and later.
|
|
|
|
//
|
|
|
|
//===========================================================================
|
2019-11-21 18:30:27 +00:00
|
|
|
void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, int32_t uniqid);
|
2019-11-05 22:35:38 +00:00
|
|
|
|
2019-11-06 22:40:10 +00:00
|
|
|
void GLInstance::Draw2D(F2DDrawer *drawer)
|
2019-11-05 22:35:38 +00:00
|
|
|
{
|
|
|
|
VSMatrix mat(0);
|
2020-01-19 13:08:48 +00:00
|
|
|
SetIdentityMatrix(Matrix_View);
|
2020-01-19 15:06:31 +00:00
|
|
|
SetIdentityMatrix(Matrix_Model);
|
2020-01-19 13:08:48 +00:00
|
|
|
SetIdentityMatrix(Matrix_Detail);
|
2019-11-05 22:35:38 +00:00
|
|
|
mat.ortho(0, xdim, ydim, 0, -1, 1);
|
2019-11-06 22:40:10 +00:00
|
|
|
SetMatrix(Matrix_Projection, mat.get());
|
|
|
|
SetViewport(0, 0, xdim, ydim);
|
|
|
|
EnableDepthTest(false);
|
|
|
|
EnableMultisampling(false);
|
|
|
|
EnableBlend(true);
|
2019-11-10 10:59:22 +00:00
|
|
|
EnableAlphaTest(true);
|
2020-01-03 09:09:38 +00:00
|
|
|
SetRenderStyle(LegacyRenderStyles[STYLE_Translucent]);
|
2019-11-05 22:35:38 +00:00
|
|
|
|
|
|
|
auto &vertices = drawer->mVertices;
|
|
|
|
auto &indices = drawer->mIndices;
|
|
|
|
auto &commands = drawer->mData;
|
|
|
|
|
|
|
|
if (commands.Size() == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drawer->mIsFirstPass)
|
|
|
|
{
|
|
|
|
for (auto &v : vertices)
|
|
|
|
{
|
|
|
|
// Change from BGRA to RGBA
|
|
|
|
std::swap(v.color0.r, v.color0.b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
F2DVertexBuffer vb;
|
|
|
|
vb.UploadData(&vertices[0], vertices.Size(), &indices[0], indices.Size());
|
2019-12-26 16:42:45 +00:00
|
|
|
assert(vb.GetBufferObjects().first && vb.GetBufferObjects().second);
|
2019-11-06 22:40:10 +00:00
|
|
|
SetVertexBuffer(vb.GetBufferObjects().first, 0, 0);
|
|
|
|
SetIndexBuffer(vb.GetBufferObjects().second);
|
|
|
|
SetFadeDisable(true);
|
2019-11-05 22:35:38 +00:00
|
|
|
|
|
|
|
for(auto &cmd : commands)
|
|
|
|
{
|
2019-11-21 18:30:27 +00:00
|
|
|
|
2019-11-05 22:35:38 +00:00
|
|
|
|
|
|
|
int gltrans = -1;
|
2019-12-29 20:36:21 +00:00
|
|
|
|
2020-01-03 09:09:38 +00:00
|
|
|
SetRenderStyle(cmd.mRenderStyle);
|
2019-11-05 22:35:38 +00:00
|
|
|
//state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed));
|
|
|
|
//state.SetTextureMode(cmd.mDrawMode);
|
|
|
|
|
|
|
|
if (cmd.mFlags & F2DDrawer::DTF_Scissor)
|
|
|
|
{
|
|
|
|
// scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates
|
|
|
|
// Note that the origin here is the lower left corner!
|
2020-01-05 09:21:34 +00:00
|
|
|
int sciX = screen->ScreenToWindowX(cmd.mScissor[0]);
|
|
|
|
int sciY = screen->ScreenToWindowY(cmd.mScissor[3]);
|
|
|
|
int sciW = screen->ScreenToWindowX(cmd.mScissor[2]) - sciX;
|
|
|
|
int sciH = screen->ScreenToWindowY(cmd.mScissor[1]) - sciY;
|
2019-12-29 21:18:20 +00:00
|
|
|
SetScissor(sciX, sciY, sciW, sciH);
|
2019-11-05 22:35:38 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-29 21:18:20 +00:00
|
|
|
DisableScissor();
|
2019-11-05 22:35:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//state.SetFog(cmd.mColor1, 0);
|
2019-11-06 22:40:10 +00:00
|
|
|
SetColor(1, 1, 1);
|
2019-11-05 22:35:38 +00:00
|
|
|
//state.SetColor(1, 1, 1, 1, cmd.mDesaturate);
|
|
|
|
|
|
|
|
if (cmd.mTexture != nullptr)
|
|
|
|
{
|
|
|
|
auto tex = cmd.mTexture;
|
2020-01-14 21:37:23 +00:00
|
|
|
|
2019-12-29 20:36:21 +00:00
|
|
|
if (cmd.mType == F2DDrawer::DrawTypeRotateSprite)
|
|
|
|
{
|
|
|
|
// todo: Set up hictinting. (broken as the feature is...)
|
|
|
|
SetShade(cmd.mRemapIndex >> 16, numshades);
|
|
|
|
SetFadeDisable(false);
|
2020-05-23 12:36:35 +00:00
|
|
|
auto saved = curbasepal; // screw Build's dependencies on global state variables. We only need to change this for the following SetTexture call.
|
|
|
|
curbasepal = (cmd.mRemapIndex >> 8) & 0xff;
|
|
|
|
auto savedf = globalflags;
|
|
|
|
if (curbasepal > 0) globalflags |= GLOBAL_NO_GL_FULLBRIGHT; // temp. hack to disable brightmaps.
|
2020-05-24 08:30:09 +00:00
|
|
|
SetTexture(-1, tex, cmd.mRemapIndex & 0xff, 4/*DAMETH_CLAMPED*/, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY);
|
2020-05-23 12:36:35 +00:00
|
|
|
curbasepal = saved;
|
|
|
|
globalflags = savedf;
|
2019-12-29 20:36:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetFadeDisable(true);
|
|
|
|
SetShade(0, numshades);
|
|
|
|
SetNamedTexture(cmd.mTexture, cmd.mRemapIndex, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY);
|
|
|
|
}
|
2020-01-18 14:18:04 +00:00
|
|
|
EnableBlend(!(cmd.mRenderStyle.Flags & STYLEF_Alpha1));
|
2019-11-06 22:40:10 +00:00
|
|
|
UseColorOnly(false);
|
2019-11-05 22:35:38 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-06 22:40:10 +00:00
|
|
|
UseColorOnly(true);
|
2019-11-05 22:35:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (cmd.mType)
|
|
|
|
{
|
|
|
|
case F2DDrawer::DrawTypeTriangles:
|
2019-12-29 20:36:21 +00:00
|
|
|
case F2DDrawer::DrawTypeRotateSprite:
|
2020-01-18 21:41:08 +00:00
|
|
|
DrawElement(DT_TRIANGLES, cmd.mIndexIndex, cmd.mIndexCount, renderState);
|
2019-11-05 22:35:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case F2DDrawer::DrawTypeLines:
|
2020-01-18 21:41:08 +00:00
|
|
|
DrawElement(DT_LINES, cmd.mVertIndex, cmd.mVertCount, renderState);
|
2019-11-05 22:35:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case F2DDrawer::DrawTypePoints:
|
2019-11-06 22:40:10 +00:00
|
|
|
//Draw(DT_POINTS, cmd.mVertIndex, cmd.mVertCount);
|
2019-11-05 22:35:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
state.SetObjectColor(0xffffffff);
|
|
|
|
state.SetObjectColor2(0);
|
|
|
|
state.SetAddColor(0);
|
|
|
|
state.EnableTextureMatrix(false);
|
|
|
|
state.SetEffect(EFF_NONE);
|
|
|
|
*/
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//state.SetRenderStyle(STYLE_Translucent);
|
2019-12-26 16:42:45 +00:00
|
|
|
ClearBufferState();
|
2019-11-06 22:40:10 +00:00
|
|
|
UseColorOnly(false);
|
2019-11-05 22:35:38 +00:00
|
|
|
//state.EnableBrightmap(true);
|
|
|
|
//state.SetTextureMode(TM_NORMAL);
|
2019-12-29 20:36:21 +00:00
|
|
|
SetShade(0, numshades);
|
2019-11-06 22:40:10 +00:00
|
|
|
SetFadeDisable(false);
|
|
|
|
SetColor(1, 1, 1);
|
2019-12-29 21:18:20 +00:00
|
|
|
DisableScissor();
|
2019-11-05 22:35:38 +00:00
|
|
|
//drawer->mIsFirstPass = false;
|
2019-12-29 20:36:21 +00:00
|
|
|
EnableBlend(true);
|
2019-11-10 10:59:22 +00:00
|
|
|
EnableMultisampling(true);
|
2020-01-19 15:06:31 +00:00
|
|
|
SetIdentityMatrix(Matrix_Projection);
|
2020-01-19 22:27:59 +00:00
|
|
|
matrixArray.Resize(1);
|
2020-01-31 21:07:51 +00:00
|
|
|
renderState.Apply(polymostShader, lastState); // actually set the desired state before returning.
|
2019-11-05 22:35:38 +00:00
|
|
|
}
|
2019-11-10 14:15:14 +00:00
|
|
|
|
|
|
|
|
2020-01-19 15:06:31 +00:00
|
|
|
static int32_t tint_blood_r = 0, tint_blood_g = 0, tint_blood_b = 0;
|
2020-05-23 12:40:54 +00:00
|
|
|
extern PalEntry palfadergb;
|
2020-01-19 15:06:31 +00:00
|
|
|
|
|
|
|
void DrawFullscreenBlends()
|
2019-11-10 14:15:14 +00:00
|
|
|
{
|
2020-01-03 22:38:50 +00:00
|
|
|
GLInterface.SetIdentityMatrix(Matrix_Projection);
|
2020-01-19 15:06:31 +00:00
|
|
|
GLInterface.SetIdentityMatrix(Matrix_Model);
|
|
|
|
GLInterface.SetIdentityMatrix(Matrix_View);
|
2019-11-10 14:15:14 +00:00
|
|
|
|
|
|
|
GLInterface.EnableDepthTest(false);
|
|
|
|
GLInterface.EnableAlphaTest(false);
|
|
|
|
GLInterface.EnableBlend(true);
|
|
|
|
GLInterface.UseColorOnly(true);
|
|
|
|
|
2020-05-23 12:40:54 +00:00
|
|
|
if (palfadergb.a > 0)
|
2020-01-19 15:06:31 +00:00
|
|
|
{
|
|
|
|
// Todo: reroute to the 2D drawer
|
|
|
|
GLInterface.SetRenderStyle(LegacyRenderStyles[STYLE_Translucent]);
|
2020-05-23 12:40:54 +00:00
|
|
|
GLInterface.SetColorub(palfadergb.r, palfadergb.g, palfadergb.b, palfadergb.a);
|
2020-01-19 15:06:31 +00:00
|
|
|
GLInterface.Draw(DT_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 4);
|
|
|
|
}
|
|
|
|
if (tint_blood_r | tint_blood_g | tint_blood_b)
|
|
|
|
{
|
|
|
|
GLInterface.SetRenderStyle(LegacyRenderStyles[STYLE_Add]);
|
2019-11-10 14:15:14 +00:00
|
|
|
|
2020-01-19 15:06:31 +00:00
|
|
|
GLInterface.SetColorub(max(tint_blood_r, 0), max(tint_blood_g, 0), max(tint_blood_b, 0), 255);
|
|
|
|
GLInterface.Draw(DT_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 4);
|
2020-01-18 12:23:01 +00:00
|
|
|
|
2020-01-19 15:06:31 +00:00
|
|
|
GLInterface.SetRenderStyle(LegacyRenderStyles[STYLE_Subtract]);
|
|
|
|
GLInterface.SetColorub(max(-tint_blood_r, 0), max(-tint_blood_g, 0), max(-tint_blood_b, 0), 255);
|
|
|
|
GLInterface.Draw(DT_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 4);
|
2020-01-18 12:23:01 +00:00
|
|
|
|
2020-01-19 15:06:31 +00:00
|
|
|
GLInterface.SetColorub(255, 255, 255, 255);
|
|
|
|
GLInterface.SetRenderStyle(LegacyRenderStyles[STYLE_Translucent]);
|
|
|
|
}
|
2020-01-19 22:49:53 +00:00
|
|
|
GLInterface.DoDraw();
|
2019-11-10 14:15:14 +00:00
|
|
|
GLInterface.UseColorOnly(false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void videoTintBlood(int32_t r, int32_t g, int32_t b)
|
|
|
|
{
|
|
|
|
tint_blood_r = r;
|
|
|
|
tint_blood_g = g;
|
|
|
|
tint_blood_b = b;
|
|
|
|
}
|