- hooked up the 2D drawer

compiles but not tested yet.
This commit is contained in:
Christoph Oelckers 2019-11-05 23:35:38 +01:00
parent 341ca9dd3a
commit de829128ea
19 changed files with 676 additions and 63 deletions

View file

@ -713,6 +713,8 @@ set (PCH_SOURCES
glbackend/glbackend.cpp
glbackend/gl_palmanager.cpp
glbackend/gl_texture.cpp
glbackend/gl_buffers.cpp
glbackend/hw_draw2d.cpp
mact/src/animlib.cpp
mact/src/control.cpp

View file

@ -108,6 +108,8 @@ enum ERenderAlpha
STYLEALPHA_InvSrcCol, // Blend factor is 1.0 - color (HWR only)
STYLEALPHA_DstCol, // Blend factor is dest. color (HWR only)
STYLEALPHA_InvDstCol, // Blend factor is 1.0 - dest. color (HWR only)
STYLEALPHA_Dst, // Blend factor is dest. alpha
STYLEALPHA_InvDst, // Blend factor is 1.0 - dest. alpha
STYLEALPHA_MAX
};

View file

@ -247,7 +247,7 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms)
dg.mVertCount = 4;
dg.mTexture = img;
dg.mTranslation = 0;
dg.mRemapIndex = parms.remap;
SetStyle(img, parms, vertexcolor, dg);
u1 = parms.srcx;

View file

@ -67,7 +67,7 @@ public:
int mIndexCount;
FTexture *mTexture;
FRemapTable *mTranslation;
int mRemapIndex;
PalEntry mSpecialColormap[2];
int mScissor[4];
int mDesaturate;
@ -86,7 +86,7 @@ public:
{
return mTexture == other.mTexture &&
mType == other.mType &&
mTranslation == other.mTranslation &&
mRemapIndex == other.mRemapIndex &&
mSpecialColormap[0].d == other.mSpecialColormap[0].d &&
mSpecialColormap[1].d == other.mSpecialColormap[1].d &&
!memcmp(mScissor, other.mScissor, sizeof(mScissor)) &&

View file

@ -265,7 +265,7 @@ bool ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, Va_Li
parms->burn = false;
parms->monospace = EMonospacing::Off;
parms->spacing = 0;
parms->remap = 0;
parms->remap = -1;
// Parse the tag list for attributes. (For floating point attributes,
// consider that the C ABI dictates that all floats be promoted to

View file

@ -126,7 +126,7 @@ void DrawTextCommon(F2DDrawer* drawer, FFont *font, int normalcolor, double x, d
double cx;
double cy;
int boldcolor;
FRemapTable *range;
int range;
int kerning;
FTexture *pic;

View file

@ -52,6 +52,7 @@
#include "myiswalpha.h"
#include "fontchars.h"
#include "imagehelpers.h"
#include "glbackend/glbackend.h"
#include "fontinternals.h"
@ -219,7 +220,7 @@ void FFont::SetDefaultTranslation(uint32_t *othercolors)
SimpleTranslation(mycolors, mytranslation, myreverse, myluminosity);
SimpleTranslation(othercolors, othertranslation, otherreverse, otherluminosity);
FRemapTable remap(ActiveColors);
FRemapTable remap;
remap.Palette[0] = 0;
for (unsigned l = 1; l < myluminosity.Size(); l++)
@ -247,7 +248,7 @@ void FFont::SetDefaultTranslation(uint32_t *othercolors)
}
}
}
Ranges[CR_UNTRANSLATED] = remap;
Ranges[CR_UNTRANSLATED] = GLInterface.GetPaletteIndex(remap.Palette);
forceremap = true;
}
@ -355,7 +356,7 @@ void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity
int i, j;
const TranslationParm *parmstart = (const TranslationParm *)ranges;
FRemapTable remap(total_colors);
FRemapTable remap;
// Create different translations for different color ranges
Ranges.Clear();
@ -380,15 +381,14 @@ void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity
}
else
{
remap = Ranges[0];
}
Ranges.Push(remap);
Ranges.Push(GLInterface.GetPaletteIndex(remap.Palette));
continue;
}
assert(parmstart->RangeStart >= 0);
remap.Palette[255] = 0;
remap.Palette[0] = 0;
for (j = 0; j < ActiveColors; j++)
{
@ -414,7 +414,8 @@ void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity
b = clamp(b, 0, 255);
remap.Palette[j] = PalEntry(255,r,g,b);
}
Ranges.Push(remap);
Ranges.Push(GLInterface.GetPaletteIndex(remap.Palette));
// Advance to the next color range.
while (parmstart[1].RangeStart > parmstart[0].RangeEnd)
@ -431,7 +432,7 @@ void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity
//
//==========================================================================
FRemapTable *FFont::GetColorTranslation (EColorRange range, PalEntry *color) const
int FFont::GetColorTranslation (EColorRange range, PalEntry *color) const
{
if (noTranslate)
{
@ -444,11 +445,11 @@ FRemapTable *FFont::GetColorTranslation (EColorRange range, PalEntry *color) con
if (color != nullptr) *color = retcolor;
}
if (ActiveColors == 0)
return nullptr;
return -1;
else if (range >= NumTextColors)
range = CR_UNTRANSLATED;
//if (range == CR_UNTRANSLATED && !translateUntranslated) return nullptr;
return &Ranges[range];
return Ranges[range];
}
//==========================================================================

View file

@ -376,8 +376,8 @@ public:
SimpleTranslation(colors, othertranslation, otherreverse, otherluminosity);
FRemapTable remap(ActiveColors);
remap.Palette[255] = 0;
FRemapTable remap;
remap.Palette[0] = 0;
for (unsigned l = 1; l < 18; l++)
{

View file

@ -99,7 +99,7 @@ public:
virtual FTexture *GetChar (int code, int translation, int *const width, bool *redirected = nullptr) const;
virtual int GetCharWidth (int code) const;
FRemapTable *GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const;
int GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const;
int GetSpaceWidth () const { return SpaceWidth; }
int GetHeight () const { return FontHeight; }
int GetDefaultKerning () const { return GlobalKerning; }
@ -164,7 +164,7 @@ protected:
};
TArray<CharData> Chars;
int ActiveColors;
TArray<FRemapTable> Ranges;
TArray<int> Ranges;
uint8_t PatchRemap[256];
FName FontName = NAME_None;
@ -192,17 +192,7 @@ char* CleanseString(char* str);
struct FRemapTable
{
FRemapTable(int count = 256) {}
~FRemapTable() { delete Palette; }
PalEntry *Palette = nullptr; // The ideal palette this maps to
int PalIndex;
int NumEntries; // # of elements in this table (usually 256)
bool Inactive; // This table is inactive and should be treated as if it was passed as NULL
private:
void Free();
void Alloc(int count);
PalEntry Palette[256] = { }; // The ideal palette this maps to
};

View file

@ -1,3 +1,4 @@
#pragma once
/*
OpenGL loader generated by glad 0.1.33 on Mon Sep 16 17:51:07 2019.

View file

@ -0,0 +1,83 @@
#pragma once
#include <stddef.h>
#include <assert.h>
class FRenderState;
// The low level code needs to know which attributes exist.
// OpenGL needs to change the state of all of them per buffer binding.
// VAOs are mostly useless for this because they lump buffer and binding state together which the model code does not want.
enum
{
VATTR_VERTEX,
VATTR_TEXCOORD,
VATTR_COLOR,
VATTR_VERTEX2,
VATTR_NORMAL,
VATTR_NORMAL2,
VATTR_MAX
};
enum EVertexAttributeFormat
{
VFmt_Float4,
VFmt_Float3,
VFmt_Float2,
VFmt_Float,
VFmt_Byte4,
VFmt_Packed_A2R10G10B10,
};
struct FVertexBufferAttribute
{
int binding;
int location;
int format;
int offset;
};
class IBuffer
{
protected:
size_t buffersize = 0;
void *map = nullptr;
public:
IBuffer() = default;
IBuffer(const IBuffer &) = delete;
IBuffer &operator=(const IBuffer &) = delete;
virtual ~IBuffer() = default;
virtual void SetData(size_t size, const void *data, bool staticdata = true) = 0;
virtual void SetSubData(size_t offset, size_t size, const void *data) = 0;
virtual void *Lock(unsigned int size) = 0;
virtual void Unlock() = 0;
virtual void Resize(size_t newsize) = 0;
virtual void Map() {} // Only needed by old OpenGL but this needs to be in the interface.
virtual void Unmap() {}
void *Memory() { assert(map); return map; }
size_t Size() { return buffersize; }
};
class IVertexBuffer : virtual public IBuffer
{
public:
virtual void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) = 0;
};
// This merely exists to have a dedicated type for index buffers to inherit from.
class IIndexBuffer : virtual public IBuffer
{
// Element size is fixed to 4, thanks to OpenGL requiring this info to be coded into the glDrawElements call.
// This mostly prohibits a more flexible buffer setup but GZDoom doesn't use any other format anyway.
// Ob Vulkam, element size is a buffer property and of no concern to the drawing functions (as it should be.)
};
class IDataBuffer : virtual public IBuffer
{
// Can be either uniform or shader storage buffer, depending on its needs.
public:
virtual void BindRange(FRenderState *state, size_t start, size_t length) = 0;
};

View file

@ -0,0 +1,218 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2018 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
/*
** Low level vertex buffer class
**
**/
#include <algorithm>
#include "glad/glad.h"
#include "glbackend.h"
#include "gl_buffers.h"
namespace OpenGLRenderer
{
//==========================================================================
//
// basic buffer implementation
//
//==========================================================================
GLBuffer::GLBuffer(int usetype)
: mUseType(usetype)
{
glGenBuffers(1, &mBufferId);
}
GLBuffer::~GLBuffer()
{
if (mBufferId != 0)
{
glBindBuffer(mUseType, mBufferId);
glUnmapBuffer(mUseType);
glBindBuffer(mUseType, 0);
glDeleteBuffers(1, &mBufferId);
}
}
void GLBuffer::Bind()
{
glBindBuffer(mUseType, mBufferId);
}
void GLBuffer::SetData(size_t size, const void *data, bool staticdata)
{
Bind();
if (data != nullptr)
{
glBufferData(mUseType, size, data, staticdata? GL_STATIC_DRAW : GL_STREAM_DRAW);
}
else
{
mPersistent = /*screen->BuffersArePersistent() &&*/ !staticdata;
if (mPersistent)
{
glBufferStorage(mUseType, size, nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
map = glMapBufferRange(mUseType, 0, size, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
}
else
{
glBufferData(mUseType, size, nullptr, staticdata ? GL_STATIC_DRAW : GL_STREAM_DRAW);
map = nullptr;
}
if (!staticdata) nomap = false;
}
buffersize = size;
}
void GLBuffer::SetSubData(size_t offset, size_t size, const void *data)
{
Bind();
glBufferSubData(mUseType, offset, size, data);
}
void GLBuffer::Map()
{
assert(nomap == false); // do not allow mapping of static buffers. Vulkan cannot do that so it should be blocked in OpenGL, too.
if (!mPersistent && !nomap)
{
Bind();
map = glMapBufferRange(mUseType, 0, buffersize, GL_MAP_WRITE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
}
}
void GLBuffer::Unmap()
{
assert(nomap == false);
if (!mPersistent && map != nullptr)
{
Bind();
glUnmapBuffer(mUseType);
map = nullptr;
}
}
void *GLBuffer::Lock(unsigned int size)
{
// This initializes this buffer as a static object with no data.
SetData(size, nullptr, true);
return glMapBufferRange(mUseType, 0, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
}
void GLBuffer::Unlock()
{
Bind();
glUnmapBuffer(mUseType);
}
void GLBuffer::Resize(size_t newsize)
{
assert(!nomap); // only mappable buffers can be resized.
if (newsize > buffersize && !nomap)
{
// reallocate the buffer with twice the size
unsigned int oldbuffer = mBufferId;
// first unmap the old buffer
Bind();
glUnmapBuffer(mUseType);
glGenBuffers(1, &mBufferId);
SetData(newsize, nullptr, false);
glBindBuffer(GL_COPY_READ_BUFFER, oldbuffer);
// copy contents and delete the old buffer.
glCopyBufferSubData(GL_COPY_READ_BUFFER, mUseType, 0, 0, buffersize);
glBindBuffer(GL_COPY_READ_BUFFER, 0);
glDeleteBuffers(1, &oldbuffer);
buffersize = newsize;
}
}
//===========================================================================
//
// Vertex buffer implementation
//
//===========================================================================
void GLVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs)
{
static int VFmtToGLFmt[] = { GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT_2_10_10_10_REV };
static uint8_t VFmtToSize[] = {4, 3, 2, 1, 4, 4};
mStride = stride;
mNumBindingPoints = numBindingPoints;
for(int i = 0; i < numAttributes; i++)
{
if (attrs[i].location >= 0 && attrs[i].location < VATTR_MAX)
{
auto & attrinf = mAttributeInfo[attrs[i].location];
attrinf.format = VFmtToGLFmt[attrs[i].format];
attrinf.size = VFmtToSize[attrs[i].format];
attrinf.offset = attrs[i].offset;
attrinf.bindingpoint = attrs[i].binding;
}
}
}
void GLVertexBuffer::Bind(int *offsets)
{
int i = 0;
// This is what gets called from RenderState.Apply. It shouldn't be called anywhere else if the render state is in use
GLBuffer::Bind();
for(auto &attrinf : mAttributeInfo)
{
if (attrinf.size == 0)
{
glDisableVertexAttribArray(i);
}
else
{
glEnableVertexAttribArray(i);
size_t ofs = offsets == nullptr ? attrinf.offset : attrinf.offset + mStride * offsets[attrinf.bindingpoint];
glVertexAttribPointer(i, attrinf.size, attrinf.format, attrinf.format != GL_FLOAT, (GLsizei)mStride, (void*)(intptr_t)ofs);
}
i++;
}
}
void GLDataBuffer::BindRange(FRenderState *state, size_t start, size_t length)
{
glBindBufferRange(mUseType, mBindingPoint, mBufferId, start, length);
}
void GLDataBuffer::BindBase()
{
glBindBufferBase(mUseType, mBindingPoint, mBufferId);
}
GLVertexBuffer::GLVertexBuffer() : GLBuffer(GL_ARRAY_BUFFER) {}
GLIndexBuffer::GLIndexBuffer() : GLBuffer(GL_ELEMENT_ARRAY_BUFFER) {}
GLDataBuffer::GLDataBuffer(int bindingpoint, bool is_ssbo) : GLBuffer(is_ssbo ? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER), mBindingPoint(bindingpoint) {}
}

View file

@ -0,0 +1,73 @@
#pragma once
#include "buffers.h"
#ifdef _MSC_VER
// silence bogus warning C4250: 'GLVertexBuffer': inherits 'GLBuffer::GLBuffer::SetData' via dominance
// According to internet infos, the warning is erroneously emitted in this case.
#pragma warning(disable:4250)
#endif
namespace OpenGLRenderer
{
class GLBuffer : virtual public IBuffer
{
protected:
const int mUseType;
unsigned int mBufferId;
int mAllocationSize = 0;
bool mPersistent = false;
bool nomap = true;
GLBuffer(int usetype);
~GLBuffer();
void SetData(size_t size, const void *data, bool staticdata) override;
void SetSubData(size_t offset, size_t size, const void *data) override;
void Map() override;
void Unmap() override;
void Resize(size_t newsize) override;
void *Lock(unsigned int size) override;
void Unlock() override;
public:
void Bind();
};
class GLVertexBuffer : public IVertexBuffer, public GLBuffer
{
// If this could use the modern (since GL 4.3) binding system, things would be simpler... :(
struct GLVertexBufferAttribute
{
int bindingpoint;
int format;
int size;
int offset;
};
int mNumBindingPoints;
GLVertexBufferAttribute mAttributeInfo[VATTR_MAX] = {}; // Thanks to OpenGL's state system this needs to contain info about every attribute that may ever be in use throughout the entire renderer.
size_t mStride = 0;
public:
GLVertexBuffer();
void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) override;
void Bind(int *offsets);
};
class GLIndexBuffer : public IIndexBuffer, public GLBuffer
{
public:
GLIndexBuffer();
};
class GLDataBuffer : public IDataBuffer, public GLBuffer
{
int mBindingPoint;
public:
GLDataBuffer(int bindingpoint, bool is_ssbo);
void BindRange(FRenderState* state, size_t start, size_t length);
void BindBase();
};
}

View file

@ -40,6 +40,7 @@
#include "baselayer.h"
#include "resourcefile.h"
#include "imagehelpers.h"
#include "v_font.h"
//===========================================================================
//

View file

@ -1,6 +1,7 @@
#pragma once
#include "PalEntry.h"
#include "gl_buffers.h"
class PolymostShader;
enum PRSFlags
@ -34,6 +35,10 @@ struct PolymostRenderState
float NPOTEmulationXOffset;
float Brightness = 1.f;
PalEntry FogColor;
IVertexBuffer* VertexBuffer = nullptr;
int VB_Offset[2] = {};
IIndexBuffer* IndexBuffer = nullptr;
void Apply(PolymostShader *shader);
};

View file

@ -39,6 +39,7 @@
#include "polymost.h"
#include "textures.h"
#include "bitmap.h"
#include "v_font.h"
#include "../../glbackend/glbackend.h"
// Test CVARs.
@ -155,10 +156,6 @@ FHardwareTexture* GLInstance::LoadTexture(FTexture* tex, int textype, int palid)
bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int method, int sampleroverride, float xpanning, float ypanning, FTexture *det, float detscale, FTexture *glow)
{
if (picnum == 3692)
{
int a = 0;
}
if (tex->GetWidth() <= 0 || tex->GetHeight() <= 0) return false;
int usepalette = fixpalette >= 1 ? fixpalette - 1 : curbasepal;
int usepalswap = fixpalswap >= 1 ? fixpalswap - 1 : palette;
@ -180,7 +177,7 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int
else
{
// Only look up the palette if we really want to use it (i.e. when creating a true color texture of an ART tile.)
if (!hw_useindexedcolortextures) lookuppal = palmanager.LookupPalette(usepalette, usepalswap, false);
if (TextureType == TT_TRUECOLOR) lookuppal = palmanager.LookupPalette(usepalette, usepalswap, false);
}
// Load the main texture
@ -291,3 +288,21 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int
}
//===========================================================================
//
// Sets a named texture for 2D rendering. In this case the palette is
// a direct index into the palette map.
//
//===========================================================================
bool GLInstance::SetNamedTexture(FTexture* tex, int palette, int sampler)
{
auto mtex = LoadTexture(tex, palette>= 0? TT_TRUECOLOR : TT_HICREPLACE, palette);
if (!mtex) return false;
renderState.Flags &= ~RF_UsePalette;
BindTexture(0, mtex, sampler);
return true;
}

View file

@ -208,15 +208,33 @@ void GLInstance::Draw(EDrawType type, size_t start, size_t count)
if (activeShader == polymostShader)
{
renderState.Apply(polymostShader);
if (renderState.VertexBuffer != LastVertexBuffer || LastVB_Offset[0] != renderState.VB_Offset[0] || LastVB_Offset[1] != renderState.VB_Offset[1])
{
static_cast<OpenGLRenderer::GLVertexBuffer*>(renderState.VertexBuffer)->Bind(renderState.VB_Offset);
LastVertexBuffer = renderState.VertexBuffer;
LastVB_Offset[0] = renderState.VB_Offset[0];
LastVB_Offset[1] = renderState.VB_Offset[1];
}
if (renderState.IndexBuffer != LastIndexBuffer)
{
static_cast<OpenGLRenderer::GLIndexBuffer*>(renderState.IndexBuffer)->Bind();
}
}
glBegin(primtypes[type]);
auto p = &Buffer[start];
for (size_t i = 0; i < count; i++, p++)
if (!LastVertexBuffer)
{
glVertexAttrib2f(1, p->u, p->v);
glVertexAttrib3f(0, p->x, p->y, p->z);
glBegin(primtypes[type]);
auto p = &Buffer[start];
for (size_t i = 0; i < count; i++, p++)
{
glVertexAttrib2f(1, p->u, p->v);
glVertexAttrib3f(0, p->x, p->y, p->z);
}
glEnd();
}
else
{
glDrawElements(primtypes[type], count, GL_UNSIGNED_INT, (void*)(intptr_t)(start * sizeof(uint32_t)));
}
glEnd();
if (MatrixChange) RestoreTextureProps();
}
@ -281,6 +299,12 @@ void GLInstance::EnableDepthTest(bool on)
else glDisable (GL_DEPTH_TEST);
}
void GLInstance::EnableMultisampling(bool on)
{
if (on) glEnable(GL_MULTISAMPLE);
else glDisable(GL_MULTISAMPLE);
}
void GLInstance::SetMatrix(int num, const VSMatrix *mat)
{
matrices[num] = *mat;

View file

@ -8,6 +8,7 @@
#include "gl_renderstate.h"
#include "matrix.h"
#include "palentry.h"
#include "renderstyle.h"
class FSamplerManager;
class FShader;
@ -64,7 +65,6 @@ class PaletteManager
//OpenGLRenderer::GLDataBuffer* palswapBuffer = nullptr;
unsigned FindPalette(const uint8_t* paldata);
unsigned FindPalswap(const uint8_t* paldata);
public:
@ -80,6 +80,8 @@ public:
int ActivePalswap() const { return lastsindex; }
int LookupPalette(int palette, int palswap, bool brightmap);
const PalEntry *GetPaletteData(int palid) const { return palettes[palid].colors; }
unsigned FindPalette(const uint8_t* paldata);
};
@ -157,27 +159,6 @@ enum EDepthFunc
Depth_LessEqual
};
enum ERenderAlpha
{
STYLEALPHA_Zero, // Blend factor is 0.0
STYLEALPHA_One, // Blend factor is 1.0
STYLEALPHA_Src, // Blend factor is alpha
STYLEALPHA_InvSrc, // Blend factor is 1.0 - alpha
STYLEALPHA_SrcCol, // Blend factor is color (HWR only)
STYLEALPHA_InvSrcCol, // Blend factor is 1.0 - color (HWR only)
STYLEALPHA_DstCol, // Blend factor is dest. color (HWR only)
STYLEALPHA_InvDstCol, // Blend factor is 1.0 - dest. color (HWR only)
STYLEALPHA_Dst, // Blend factor is dest. alpha
STYLEALPHA_InvDst, // Blend factor is 1.0 - dest. alpha
STYLEALPHA_MAX
};
enum ERenderOp
{
STYLEOP_Add, // Add source to destination
STYLEOP_Sub, // Subtract source from destination
STYLEOP_RevSub, // Subtract destination from source
};
enum EWinding
{
@ -212,6 +193,10 @@ class GLInstance
int TextureType;
int MatrixChange = 0;
IVertexBuffer* LastVertexBuffer = nullptr;
int LastVB_Offset[2] = {};
IIndexBuffer* LastIndexBuffer = nullptr;
VSMatrix matrices[NUMMATRICES];
PolymostRenderState renderState;
@ -251,6 +236,17 @@ public:
void EnableBlend(bool on);
void EnableAlphaTest(bool on);
void EnableDepthTest(bool on);
void EnableMultisampling(bool on);
void SetVertexBuffer(IVertexBuffer* vb, int offset1, int offset2)
{
renderState.VertexBuffer = vb;
renderState.VB_Offset[0] = offset1;
renderState.VB_Offset[1] = offset2;
}
void SetIndexBuffer(IIndexBuffer* vb)
{
renderState.IndexBuffer = vb;
}
const VSMatrix &GetMatrix(int num)
{
return matrices[num];
@ -396,12 +392,18 @@ public:
{
// not yet implemented - only relevant for hires replacements.
}
int GetPaletteIndex(PalEntry* palette)
{
return palmanager.FindPalette((uint8_t*)palette);
}
FHardwareTexture* CreateIndexedTexture(FTexture* tex);
FHardwareTexture* CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false);
FHardwareTexture *LoadTexture(FTexture* tex, int texturetype, int palid);
bool SetTextureInternal(int globalpicnum, FTexture* tex, int palette, int method, int sampleroverride, float xpanning, float ypanning, FTexture *det, float detscale, FTexture *glow);
bool SetNamedTexture(FTexture* tex, int palette, int sampleroverride);
bool SetTexture(int globalpicnum, FTexture* tex, int palette, int method, int sampleroverride)
{

View file

@ -0,0 +1,196 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2018 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
/*
** 2d drawer
** Renderer interface
**
*/
#include "cmdlib.h"
#include "gl_buffers.h"
#include "v_2ddrawer.h"
#include "c_cvars.h"
#include "glbackend.h"
#include "v_draw.h"
//===========================================================================
//
// 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.
//
//===========================================================================
void Draw2D(F2DDrawer *drawer, FRenderState &state)
{
VSMatrix mat(0);
GLInterface.SetMatrix(Matrix_View, mat.get());
GLInterface.SetMatrix(Matrix_ModelView, mat.get());
GLInterface.SetMatrix(Matrix_Detail, mat.get());
mat.ortho(0, xdim, ydim, 0, -1, 1);
GLInterface.SetMatrix(Matrix_Projection, mat.get());
GLInterface.SetViewport(0, 0, xdim, ydim);
GLInterface.EnableDepthTest(false);
GLInterface.EnableMultisampling(false);
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());
GLInterface.SetVertexBuffer(vb.GetBufferObjects().first, 0, 0);
GLInterface.SetIndexBuffer(vb.GetBufferObjects().second);
GLInterface.SetFadeDisable(true);
for(auto &cmd : commands)
{
int gltrans = -1;
//state.SetRenderStyle(cmd.mRenderStyle);
//state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed));
//state.SetTextureMode(cmd.mDrawMode);
int sciX, sciY, sciW, sciH;
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!
sciX = /*screen->ScreenToWindowX*/(cmd.mScissor[0]);
sciY = /*screen->ScreenToWindowY*/(cmd.mScissor[3]);
sciW = /*screen->ScreenToWindowX*/(cmd.mScissor[2]) - sciX;
sciH = /*screen->ScreenToWindowY*/(cmd.mScissor[1]) - sciY;
}
else
{
sciX = sciY = sciW = sciH = -1;
}
//GLInterface.SetScissor(sciX, sciY, sciW, sciH);
//state.SetFog(cmd.mColor1, 0);
GLInterface.SetColor(1, 1, 1);
//state.SetColor(1, 1, 1, 1, cmd.mDesaturate);
GLInterface.SetAlphaThreshold(0.0f);
if (cmd.mTexture != nullptr)
{
auto tex = cmd.mTexture;
GLInterface.SetNamedTexture(cmd.mTexture, cmd.mRemapIndex, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY);
GLInterface.UseColorOnly(false);
}
else
{
GLInterface.UseColorOnly(true);
}
switch (cmd.mType)
{
case F2DDrawer::DrawTypeTriangles:
GLInterface.Draw(DT_TRIANGLES, cmd.mIndexIndex, cmd.mIndexCount);
break;
case F2DDrawer::DrawTypeLines:
GLInterface.Draw(DT_LINES, cmd.mVertIndex, cmd.mVertCount);
break;
case F2DDrawer::DrawTypePoints:
//GLInterface.Draw(DT_POINTS, cmd.mVertIndex, cmd.mVertCount);
break;
}
/*
state.SetObjectColor(0xffffffff);
state.SetObjectColor2(0);
state.SetAddColor(0);
state.EnableTextureMatrix(false);
state.SetEffect(EFF_NONE);
*/
}
//state.SetScissor(-1, -1, -1, -1);
//state.SetRenderStyle(STYLE_Translucent);
GLInterface.SetVertexBuffer(nullptr, 0, 0);
GLInterface.SetIndexBuffer(nullptr);
GLInterface.UseColorOnly(false);
//state.EnableBrightmap(true);
//state.SetTextureMode(TM_NORMAL);
GLInterface.SetFadeDisable(false);
GLInterface.SetColor(1, 1, 1);
//drawer->mIsFirstPass = false;
}