- implemented the 2D drawer for the hardware renderer. Not tested yet.

This commit is contained in:
Christoph Oelckers 2018-03-28 21:38:00 +02:00
parent 25999c1c6a
commit 70b6754299
14 changed files with 232 additions and 26 deletions

View File

@ -9,7 +9,9 @@ struct lightlist_t;
enum EColorManipulation
{
CM_SPECIAL2D = -3, // the special colormaps get passed as color pair from the 2D drawer so they need a different value here.
CM_INGAME2D = -3, // ingame lighting mode for automap
CM_PLAIN2D = -2, // regular 2D drawing.
CM_INVALID=-1,
CM_DEFAULT=0, // untranslated
CM_FIRSTSPECIALCOLORMAP, // first special fixed colormap

View File

@ -138,7 +138,6 @@ void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblend
}
else if (style.Flags & STYLEF_InvertSource)
{
// The only place where InvertSource is used is for inverted sprites with the infrared powerup.
texturemode = TM_INVERSE;
}

View File

@ -432,3 +432,170 @@ unsigned char *FGLRenderer::GetTextureBuffer(FTexture *tex, int &w, int &h)
}
return NULL;
}
//===========================================================================
//
// Vertex buffer for 2D drawer
//
//===========================================================================
#define TDiO ((F2DDrawer::TwoDVertex*)NULL)
class F2DVertexBuffer : public FVertexBuffer
{
uint32_t ibo_id;
public:
F2DVertexBuffer()
{
glGenBuffers(1, &ibo_id);
}
~F2DVertexBuffer()
{
if (ibo_id != 0)
{
glDeleteBuffers(1, &ibo_id);
}
}
void UploadData(F2DDrawer::TwoDVertex *vertices, int vertcount, int *indices, int indexcount)
{
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glBufferData(GL_ARRAY_BUFFER, vertcount * sizeof(vertices[0]), vertices, GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexcount * sizeof(indices[0]), indices, GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void BindVBO() override
{
// set up the vertex buffer for drawing the 2D elements.
glGenBuffers(1, &vbo_id);
glGenBuffers(1, &ibo_id);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FSimpleVertex), &TDiO->x);
glVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, false, sizeof(FSimpleVertex), &TDiO->u);
glVertexAttribPointer(VATTR_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(FSimpleVertex), &TDiO->color0);
glEnableVertexAttribArray(VATTR_VERTEX);
glEnableVertexAttribArray(VATTR_TEXCOORD);
glEnableVertexAttribArray(VATTR_COLOR);
glDisableVertexAttribArray(VATTR_VERTEX2);
glDisableVertexAttribArray(VATTR_NORMAL);
}
};
//===========================================================================
//
// Draws the 2D stuff. This is the version for OpenGL 3 and later.
//
//===========================================================================
void FGLRenderer::Draw2D(F2DDrawer *drawer)
{
F2DDrawer::EDrawType lasttype = F2DDrawer::DrawTypeTriangles;
auto &vertices = drawer->mVertices;
auto &indices = drawer->mIndices;
auto &commands = drawer->mData;
if (commands.Size() == 0) return;
for (auto &v : vertices)
{
// Change from BGRA to RGBA
std::swap(v.color0.r, v.color0.b);
}
auto vb = new F2DVertexBuffer;
vb->UploadData(&vertices[0], vertices.Size(), &indices[0], indices.Size());
gl_RenderState.SetVertexBuffer(vb);
for(auto &cmd : commands)
{
gl_RenderState.ResetColor(); // this is needed to reset the desaturation.
int tm, sb, db, be;
// The texture mode being returned here cannot be used, because the higher level code
// already manipulated the data so that some cases will not be handled correctly.
// Since we already get a proper mode from the calling code this doesn't really matter.
gl_GetRenderStyle(cmd.mRenderStyle, false, false, &tm, &sb, &db, &be);
gl_RenderState.BlendEquation(be);
gl_RenderState.BlendFunc(sb, db);
// Rather than adding remapping code, let's enforce that the constants here are equal.
static_assert(F2DDrawer::DTM_Normal == TM_MODULATE, "DTM_Normal != TM_MODULATE");
static_assert(F2DDrawer::DTM_Opaque == TM_OPAQUE, "DTM_Opaque != TM_OPAQUE");
static_assert(F2DDrawer::DTM_Invert == TM_INVERSE, "DTM_Invert != TM_INVERSE");
static_assert(F2DDrawer::DTM_InvertOpaque == TM_INVERTOPAQUE, "DTM_InvertOpaque != TM_INVERTOPAQUE");
static_assert(F2DDrawer::DTM_Stencil == TM_MASK, "DTM_Stencil != TM_MASK");
static_assert(F2DDrawer::DTM_AlphaTexture == TM_REDTOALPHA, "DTM_AlphaTexture != TM_REDTOALPHA");
gl_RenderState.SetTextureMode(cmd.mDrawMode);
if (cmd.mFlags & F2DDrawer::DTF_Scissor)
{
glEnable(GL_SCISSOR_TEST);
// scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates
glScissor(
GLRenderer->ScreenToWindowX(cmd.mScissor[0]),
GLRenderer->ScreenToWindowX(cmd.mScissor[1]),
GLRenderer->ScreenToWindowX(cmd.mScissor[2] - cmd.mScissor[0]),
GLRenderer->ScreenToWindowX(cmd.mScissor[3] - cmd.mScissor[1]));
}
else glDisable(GL_SCISSOR_TEST);
gl_RenderState.SetObjectColor(cmd.mColor1);
gl_RenderState.SetObjectColor2(cmd.mColor2);
if (cmd.mFlags & F2DDrawer::DTF_IngameLighting)
{
gl_RenderState.SetFixedColormap(CM_INGAME2D);
}
else if (cmd.mFlags & F2DDrawer::DTF_SpecialColormap)
{
gl_RenderState.SetFixedColormap(CM_SPECIAL2D);
}
else
{
gl_RenderState.SetFixedColormap(CM_PLAIN2D);
}
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
switch (cmd.mType)
{
case F2DDrawer::DrawTypeTriangles:
if (cmd.mTexture != nullptr)
{
auto mat = FMaterial::ValidateTexture(cmd.mTexture, false);
if (mat == nullptr) continue;
int gltrans = GLTranslationPalette::GetInternalTranslation(cmd.mTranslation);
gl_RenderState.SetMaterial(mat, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : CLAMP_XY_NOMIP, gltrans, -1, false);
gl_RenderState.EnableTexture(true);
}
else
{
gl_RenderState.EnableTexture(false);
}
gl_RenderState.Apply();
glDrawElements(GL_TRIANGLES, cmd.mIndexCount, GL_UNSIGNED_INT, (const void *)(cmd.mIndexIndex * sizeof(unsigned int)));
break;
case F2DDrawer::DrawTypeLines:
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
glDrawArrays(GL_LINES, cmd.mVertIndex, cmd.mVertCount);
gl_RenderState.EnableTexture(true);
break;
case F2DDrawer::DrawTypePoints:
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
glDrawArrays(GL_POINTS, cmd.mVertIndex, cmd.mVertCount);
gl_RenderState.EnableTexture(true);
break;
}
}
glDisable(GL_SCISSOR_TEST);
gl_RenderState.SetVertexBuffer(nullptr);
delete vb;
}

View File

@ -190,6 +190,7 @@ public:
void DrawPresentTexture(const GL_IRECT &box, bool applyGamma);
void Flush();
void GetSpecialTextures();
void Draw2D(F2DDrawer *data);
bool StartOffscreen();

View File

@ -233,6 +233,27 @@ bool FRenderState::ApplyShader()
{
activeShader->muFixedColormap.Set(0);
}
else if (mColormapState == CM_PLAIN2D)
{
activeShader->muFixedColormap.Set(4);
}
else if (mColormapState == CM_INGAME2D)
{
activeShader->muFixedColormap.Set(5);
}
else if (mColormapState == CM_SPECIAL2D)
{
activeShader->muFixedColormap.Set(2);
activeShader->muFixedColormap.Set(1);
float startr = mObjectColor.r / 255;
float startg = mObjectColor.g / 255;
float startb = mObjectColor.b / 255;
float ranger = mObjectColor2.r / 255 - startr;
float rangeg = mObjectColor2.g / 255 - startg;
float rangeb = mObjectColor2.b / 255 - startb;
activeShader->muColormapStart.Set(startr, startg, startb, 0.f);
activeShader->muColormapRange.Set(ranger, rangeg, rangeb, 0.f);
}
else if (mColormapState > CM_DEFAULT && mColormapState < CM_MAXCOLORMAP)
{
if (FGLRenderBuffers::IsEnabled())

View File

@ -144,7 +144,7 @@ public:
void SetMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader, bool alphatexture)
{
// alpha textures need special treatment in the legacy renderer because withouz shaders they need a different texture.
// alpha textures need special treatment in the legacy renderer because without shaders they need a different texture.
if (alphatexture && gl.legacyMode) translation = INT_MAX;
if (mat->tex->bHasCanvas)

View File

@ -473,3 +473,15 @@ void OpenGLFrameBuffer::ScaleCoordsFromWindow(int16_t &x, int16_t &y)
x = int16_t((x - letterboxX) * Width / letterboxWidth);
y = int16_t((y - letterboxY) * Height / letterboxHeight);
}
//===========================================================================
//
// 2D drawing
//
//===========================================================================
void OpenGLFrameBuffer::Draw2D()
{
//if (gl.legacyMode) Draw2DLegacy();
if (GLRenderer != nullptr) GLRenderer->Draw2D(&m2DDrawer);
}

View File

@ -68,6 +68,7 @@ public:
void SetVSync(bool vsync);
void ScaleCoordsFromWindow(int16_t &x, int16_t &y) override;
void Draw2D() override;
bool HWGammaActive = false; // Are we using hardware or software gamma?
std::shared_ptr<FGLDebug> mDebug; // Debug API

View File

@ -35,8 +35,7 @@ enum TexMode
TM_INVERSE, // (1-r, 1-g, 1-b, a)
TM_REDTOALPHA, // (1, 1, 1, r)
TM_CLAMPY, // (r, g, b, (t >= 0.0 && t <= 1.0)? a:0)
TM_INVERTOPAQUE, // used by GL 2.x fallback code.
TM_INVERTOPAQUE, // (1-r, 1-g, 1-b, 1)
};
enum ELightMethod

View File

@ -62,14 +62,17 @@ bool GLTranslationPalette::Update()
return true;
}
int GLTranslationPalette::GetInternalTranslation(FRemapTable *remap)
{
if (remap == nullptr || remap->Inactive) return 0;
GLTranslationPalette *tpal = static_cast<GLTranslationPalette*>(remap->GetNative());
if (tpal == nullptr) return 0;
return tpal->GetIndex();
}
int GLTranslationPalette::GetInternalTranslation(int trans)
{
if (trans <= 0) return 0;
FRemapTable *remap = TranslationToTable(trans);
if (remap == NULL || remap->Inactive) return 0;
GLTranslationPalette *tpal = static_cast<GLTranslationPalette*>(remap->GetNative());
if (tpal == NULL) return 0;
return tpal->GetIndex();
return GetInternalTranslation(TranslationToTable(trans));
}

View File

@ -30,6 +30,7 @@ public:
static GLTranslationPalette *CreatePalette(FRemapTable *remap);
static int GetInternalTranslation(int trans);
static int GetInternalTranslation(FRemapTable *trans);
static PalEntry *GetPalette(unsigned int index)
{
return index > 0 && index <= AllPalettes.Size()? AllPalettes[index-1].pe : NULL;

View File

@ -25,9 +25,9 @@ public:
DTM_Normal = 0,
DTM_Stencil = 1,
DTM_Opaque = 2,
DTM_AlphaTexture = 3,
DTM_Invert = 4,
DTM_InvertOpaque = 5,
DTM_Invert = 3,
DTM_AlphaTexture = 4,
DTM_InvertOpaque = 6,
};
enum ETextureFlags : uint8_t

View File

@ -287,9 +287,8 @@ public:
class DFrameBuffer
{
typedef DSimpleCanvas Super;
F2DDrawer m2DDrawer;
protected:
void DrawTextureV(FTexture *img, double x, double y, uint32_t tag, va_list tags) = delete;
void DrawTextureParms(FTexture *img, DrawParms &parms);
@ -297,6 +296,7 @@ protected:
bool ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, bool fortext) const;
void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms);
F2DDrawer m2DDrawer;
int Width = 0;
int Height = 0;
bool Bgra = 0;

View File

@ -37,18 +37,18 @@ float4 SampleTexture(float2 tex_coord)
// Normal color calculation for most drawing modes.
float4 NormalColor(float2 tex_coord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
float4 NormalColor(float2 tex_coord : TEXCOORD0, float4 VertexColor : COLOR0, float4 Overlay : COLOR1) : COLOR
{
return Flash + SampleTexture(tex_coord) * InvFlash;
return Overlay + SampleTexture(tex_coord) * VertexColor;
}
// Copy the red channel to the alpha channel. Pays no attention to palettes.
// Copy the red channel to the alpha channel. Pays no attention to palettes and only works with grayscale textures
float4 RedToAlpha(float2 tex_coord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
float4 RedToAlpha(float2 tex_coord : TEXCOORD0, float4 VertexColor : COLOR0, float4 Overlay : COLOR1) : COLOR
{
float4 color = Invert(tex2D(Image, tex_coord));
color.a = color.r;
return Flash + color * InvFlash;
color.a *= color.r;
return Overlay + color * VertexColor;
}
// Just return the value of c0.
@ -87,12 +87,12 @@ float4 InGameColormap(float2 tex_coord : TEXCOORD0, float4 color : COLOR0, float
rgb.rgb = intensity.rgb + rgb.rgb * Desaturation.y;
#endif
// Fade
rgb.rgb = rgb.rgb * fade.aaa + fade.rgb;
// Shade and Alpha
rgb = rgb * color;
// Fade
rgb.rgb = rgb.rgb * fade.aaa + fade.rgb;
return rgb;
}