- refactored all 2D drawing to use its own vertex buffer which does not need to be mapped permanently.

This commit is contained in:
Christoph Oelckers 2016-08-08 12:13:09 +02:00
parent 9a5cbbe6d8
commit def3ad7533
10 changed files with 632 additions and 394 deletions

View file

@ -1060,6 +1060,7 @@ set( FASTMATH_SOURCES
gl/utility/gl_clock.cpp
gl/utility/gl_cycler.cpp
gl/utility/gl_geometric.cpp
gl/renderer/gl_2ddrawer.cpp
gl/renderer/gl_renderer.cpp
gl/renderer/gl_renderstate.cpp
gl/renderer/gl_renderbuffers.cpp

View file

@ -77,22 +77,26 @@ void FSimpleVertexBuffer::BindVBO()
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
if (gl.glslversion > 0)
{
glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FFlatVertex), &VTO->x);
glVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, false, sizeof(FFlatVertex), &VTO->u);
glDisableVertexAttribArray(VATTR_COLOR);
glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FSimpleVertex), &VSiO->x);
glVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, false, sizeof(FSimpleVertex), &VSiO->u);
glVertexAttribPointer(VATTR_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(FSimpleVertex), &VSiO->color);
glEnableVertexAttribArray(VATTR_VERTEX);
glEnableVertexAttribArray(VATTR_TEXCOORD);
glEnableVertexAttribArray(VATTR_COLOR);
glDisableVertexAttribArray(VATTR_VERTEX2);
}
else
{
glVertexPointer(3, GL_FLOAT, sizeof(FFlatVertex), &VTO->x);
glTexCoordPointer(2, GL_FLOAT, sizeof(FFlatVertex), &VTO->u);
glVertexPointer(3, GL_FLOAT, sizeof(FSimpleVertex), &VSiO->x);
glTexCoordPointer(2, GL_FLOAT, sizeof(FSimpleVertex), &VSiO->u);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(FSimpleVertex), &VSiO->color);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
}
}
void FSimpleVertexBuffer::set(FFlatVertex *verts, int count)
void FSimpleVertexBuffer::set(FSimpleVertex *verts, int count)
{
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
gl_RenderState.SetVertexBuffer(this);

View file

@ -36,20 +36,37 @@ struct FFlatVertex
u = uu;
v = vv;
}
void BindVBO();
};
struct FSimpleVertex
{
float x, z, y; // world position
float u, v; // texture coordinates
PalEntry color;
void Set(float xx, float zz, float yy, float uu = 0, float vv = 0, PalEntry col = 0xffffffff)
{
x = xx;
z = zz;
y = yy;
u = uu;
v = vv;
color = col;
}
};
#define VTO ((FFlatVertex*)NULL)
#define VSiO ((FSimpleVertex*)NULL)
class FSimpleVertexBuffer : public FVertexBuffer
{
TArray<FFlatVertex> mBuffer;
TArray<FSimpleVertex> mBuffer;
public:
FSimpleVertexBuffer()
{
}
void BindVBO();
void set(FFlatVertex *verts, int count);
void set(FSimpleVertex *verts, int count);
};
class FFlatVertexBuffer : public FVertexBuffer

View file

@ -0,0 +1,488 @@
/*
** gl_2ddrawer.h
** Container class for drawing 2d graphics with a vertex buffer
**
**---------------------------------------------------------------------------
** Copyright 2016 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.
** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be
** covered by the terms of the GNU Lesser General Public License as published
** by the Free Software Foundation; either version 2.1 of the License, or (at
** your option) any later version.
** 5. Full disclosure of the entire project's source code, except for third
** party libraries is mandatory. (NOTE: This clause is non-negotiable!)
**
** 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.
**---------------------------------------------------------------------------
**
*/
#include "gl/system/gl_system.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_2ddrawer.h"
#include "gl/textures/gl_material.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_lightdata.h"
#include "gl/scene/gl_drawinfo.h"
#include "gl/textures/gl_translate.h"
#include "vectors.h"
//==========================================================================
//
//
//
//==========================================================================
int F2DDrawer::AddData(const F2DDrawer::DataGeneric *data)
{
int addr = mData.Reserve(data->mLen);
memcpy(&mData[addr], data, data->mLen);
mLastLineCmd = -1;
return addr;
}
//==========================================================================
//
// Draws a texture
//
//==========================================================================
void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms)
{
double xscale = parms.destwidth / parms.texwidth;
double yscale = parms.destheight / parms.texheight;
double x = parms.x - parms.left * xscale;
double y = parms.y - parms.top * yscale;
double w = parms.destwidth;
double h = parms.destheight;
float u1, v1, u2, v2;
int light = 255;
FMaterial * gltex = FMaterial::ValidateTexture(img, false);
if (gltex == nullptr) return;
DataTexture dg;
dg.mType = DrawTypeTexture;
dg.mLen = (sizeof(dg) + 7) & ~7;
dg.mVertCount = 4;
dg.mRenderStyle = parms.style;
dg.mMasked = !!parms.masked;
dg.mTexture = gltex;
if (parms.colorOverlay && (parms.colorOverlay & 0xffffff) == 0)
{
// handle black overlays as reduced light.
light = 255 - APART(parms.colorOverlay);
parms.colorOverlay = 0;
}
dg.mVertIndex = (int)mVertices.Reserve(parms.colorOverlay == 0? 4 : 8);
dg.mColorOverlay = parms.colorOverlay;
dg.mTranslation = 0;
if (!img->bHasCanvas)
{
if (!parms.alphaChannel)
{
if (parms.remap != NULL && !parms.remap->Inactive)
{
GLTranslationPalette * pal = static_cast<GLTranslationPalette*>(parms.remap->GetNative());
if (pal) dg.mTranslation = -pal->GetIndex();
}
}
dg.mAlphaTexture = !!(parms.style.Flags & STYLEF_RedIsAlpha);
u1 = gltex->GetUL();
v1 = gltex->GetVT();
u2 = gltex->GetUR();
v2 = gltex->GetVB();
}
else
{
dg.mAlphaTexture = false;
u1 = 0.f;
v1 = 1.f;
u2 = 1.f;
v2 = 0.f;
}
if (parms.flipX)
std::swap(u1, u2);
if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
{
double wi = MIN(parms.windowright, parms.texwidth);
x += parms.windowleft * xscale;
w -= (parms.texwidth - wi + parms.windowleft) * xscale;
u1 = float(u1 + parms.windowleft / parms.texwidth);
u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth);
}
PalEntry color;
if (parms.style.Flags & STYLEF_ColorIsFixed)
{
color = parms.fillcolor;
std::swap(color.r, color.b);
}
else
{
color = PalEntry(light, light, light);
}
color.a = (BYTE)(parms.Alpha * 255);
// scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates
int btm = (SCREENHEIGHT - screen->GetHeight()) / 2;
btm = SCREENHEIGHT - btm;
int space = (static_cast<OpenGLFrameBuffer*>(screen)->GetTrueHeight() - screen->GetHeight()) / 2;
dg.mScissor[0] = parms.lclip;
dg.mScissor[1] = btm - parms.dclip + space;
dg.mScissor[2] = parms.rclip - parms.lclip;
dg.mScissor[3] = parms.dclip - parms.uclip;
FSimpleVertex *ptr = &mVertices[dg.mVertIndex];
ptr->Set(x, y, 0, u1, v1, color); ptr++;
ptr->Set(x, y + h, 0, u1, v2, color); ptr++;
ptr->Set(x + w, y, 0, u2, v1, color); ptr++;
ptr->Set(x + w, y + h, 0, u2, v2, color); ptr++;
if (parms.colorOverlay != 0)
{
color = parms.colorOverlay;
std::swap(color.r, color.b);
ptr->Set(x, y, 0, u1, v1, color); ptr++;
ptr->Set(x, y + h, 0, u1, v2, color); ptr++;
ptr->Set(x + w, y, 0, u2, v1, color); ptr++;
ptr->Set(x + w, y + h, 0, u2, v2, color); ptr++;
}
AddData(&dg);
}
//==========================================================================
//
//
//
//==========================================================================
void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, FDynamicColormap *colormap, int lightlevel)
{
FMaterial *gltexture = FMaterial::ValidateTexture(texture, false);
if (gltexture == nullptr)
{
return;
}
DataSimplePoly poly;
poly.mType = DrawTypePoly;
poly.mLen = (sizeof(poly) + 7) & ~7;
poly.mTexture = gltexture;
poly.mColormap = colormap;
poly.mLightLevel = lightlevel;
poly.mVertCount = npoints;
poly.mVertIndex = (int)mVertices.Reserve(npoints);
bool dorotate = rotation != 0;
float cosrot = cos(rotation.Radians());
float sinrot = sin(rotation.Radians());
float uscale = float(1.f / (texture->GetScaledWidth() * scalex));
float vscale = float(1.f / (texture->GetScaledHeight() * scaley));
if (texture->bHasCanvas)
{
vscale = 0 - vscale;
}
float ox = float(originx);
float oy = float(originy);
for (int i = 0; i < npoints; ++i)
{
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;
}
mVertices[poly.mVertIndex+i].Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale);
}
AddData(&poly);
}
//===========================================================================
//
//
//
//===========================================================================
void F2DDrawer::AddDim(PalEntry color, float damount, int x1, int y1, int w, int h)
{
color.a = uint8_t(damount * 255);
std::swap(color.r, color.b);
DataGeneric dg;
dg.mType = DrawTypeDim;
dg.mLen = (sizeof(dg) + 7) & ~7;
dg.mVertCount = 4;
dg.mVertIndex = (int)mVertices.Reserve(4);
FSimpleVertex *ptr = &mVertices[dg.mVertIndex];
ptr->Set(x1, y1, 0, 0, 0, color); ptr++;
ptr->Set(x1, y1 + h, 0, 0, 0, color); ptr++;
ptr->Set(x1 + w, y1 + h, 0, 0, 0, color); ptr++;
ptr->Set(x1 + w, y1, 0, 0, 0, color); ptr++;
AddData(&dg);
}
//==========================================================================
//
//
//
//==========================================================================
void F2DDrawer::AddClear(int left, int top, int right, int bottom, int palcolor, uint32 color)
{
PalEntry p = palcolor == -1 || color != 0 ? (PalEntry)color : GPalette.BaseColors[palcolor];
AddDim(p, 1.f, left, top, right - left, bottom - top);
}
//==========================================================================
//
//
//
//==========================================================================
void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin)
{
float fU1, fU2, fV1, fV2;
FMaterial *gltexture = FMaterial::ValidateTexture(src, false);
if (!gltexture) return;
DataFlatFill dg;
dg.mType = DrawTypeFlatFill;
dg.mLen = (sizeof(dg) + 7) & ~7;
dg.mVertCount = 4;
dg.mVertIndex = (int)mVertices.Reserve(4);
dg.mTexture = gltexture;
// scaling is not used here.
if (!local_origin)
{
fU1 = float(left) / src->GetWidth();
fV1 = float(top) / src->GetHeight();
fU2 = float(right) / src->GetWidth();
fV2 = float(bottom) / src->GetHeight();
}
else
{
fU1 = 0;
fV1 = 0;
fU2 = float(right - left) / src->GetWidth();
fV2 = float(bottom - top) / src->GetHeight();
}
FSimpleVertex *ptr = &mVertices[dg.mVertIndex];
ptr->Set(left, top, 0, fU1, fV1); ptr++;
ptr->Set(left, bottom, 0, fU1, fV2); ptr++;
ptr->Set(right, top, 0, fU2, fV1); ptr++;
ptr->Set(right, bottom, 0, fU2, fV2); ptr++;
AddData(&dg);
}
//==========================================================================
//
//
//
//==========================================================================
void F2DDrawer::AddLine(int x1, int y1, int x2, int y2, int palcolor, uint32 color)
{
PalEntry p = color ? (PalEntry)color : GPalette.BaseColors[palcolor];
p.a = 255;
std::swap(p.r, p.b);
DataGeneric dg;
dg.mType = DrawTypeLine;
dg.mLen = (sizeof(dg) + 7) & ~7;
dg.mVertCount = 2;
dg.mVertIndex = (int)mVertices.Reserve(2);
mVertices[dg.mVertIndex].Set(x1, y1, 0, 0, 0, p);
mVertices[dg.mVertIndex+1].Set(x2, y2, 0, 0, 0, p);
// Test if we can batch multiple line commands
if (mLastLineCmd == -1)
{
mLastLineCmd = AddData(&dg);
}
else
{
DataGeneric *dg = (DataGeneric *)&mData[mLastLineCmd];
dg->mVertCount += 2;
}
}
//==========================================================================
//
//
//
//==========================================================================
void F2DDrawer::AddPixel(int x1, int y1, int palcolor, uint32 color)
{
PalEntry p = color ? (PalEntry)color : GPalette.BaseColors[palcolor];
p.a = 255;
std::swap(p.r, p.b);
DataGeneric dg;
dg.mType = DrawTypePixel;
dg.mLen = (sizeof(dg) + 7) & ~7;
dg.mVertCount = 2;
dg.mVertIndex = (int)mVertices.Reserve(1);
mVertices[dg.mVertIndex].Set(x1, y1, 0, 0, 0, p);
AddData(&dg);
}
//==========================================================================
//
//
//
//==========================================================================
void F2DDrawer::Flush()
{
if (mData.Size() == 0) return;
SBYTE savedlightmode = glset.lightmode;
// lightmode is only relevant for automap subsectors,
// but We cannot use the software light mode here because it doesn't properly calculate the light for 2D rendering.
if (glset.lightmode == 8) glset.lightmode = 0;
set(&mVertices[0], mVertices.Size());
for (unsigned i = 0; i < mData.Size();)
{
DataGeneric *dg = (DataGeneric *)&mData[i];
switch (dg->mType)
{
default:
break;
case DrawTypeTexture:
{
DataTexture *dt = static_cast<DataTexture*>(dg);
gl_SetRenderStyle(dt->mRenderStyle, !dt->mMasked, false);
gl_RenderState.SetMaterial(dt->mTexture, CLAMP_XY_NOMIP, dt->mTranslation, -1, dt->mAlphaTexture);
if (dt->mTexture->tex->bHasCanvas) gl_RenderState.SetTextureMode(TM_OPAQUE);
glEnable(GL_SCISSOR_TEST);
glScissor(dt->mScissor[0], dt->mScissor[1], dt->mScissor[2], dt->mScissor[3]);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.Apply();
glDrawArrays(GL_TRIANGLE_STRIP, dt->mVertIndex, 4);
gl_RenderState.BlendEquation(GL_FUNC_ADD);
if (dt->mVertCount > 4)
{
gl_RenderState.SetTextureMode(TM_MASK);
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_RenderState.Apply();
glDrawArrays(GL_TRIANGLE_STRIP, dt->mVertIndex + 4, 4);
}
glScissor(0, 0, screen->GetWidth(), screen->GetHeight());
glDisable(GL_SCISSOR_TEST);
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_RenderState.SetTextureMode(TM_MODULATE);
break;
}
case DrawTypePoly:
{
DataSimplePoly *dsp = static_cast<DataSimplePoly*>(dg);
FColormap cm;
cm = dsp->mColormap;
gl_SetColor(dsp->mLightLevel, 0, cm, 1.f);
gl_RenderState.SetMaterial(dsp->mTexture, CLAMP_NONE, 0, -1, false);
gl_RenderState.Apply();
glDrawArrays(GL_TRIANGLE_FAN, dsp->mVertIndex, dsp->mVertCount);
break;
}
case DrawTypeFlatFill:
{
DataFlatFill *dff = static_cast<DataFlatFill*>(dg);
gl_RenderState.SetMaterial(dff->mTexture, CLAMP_NONE, 0, -1, false);
gl_RenderState.Apply();
glDrawArrays(GL_TRIANGLE_STRIP, dg->mVertIndex, dg->mVertCount);
break;
}
case DrawTypeDim:
gl_RenderState.EnableTexture(false);
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_RenderState.AlphaFunc(GL_GREATER, 0);
gl_RenderState.Apply();
glDrawArrays(GL_TRIANGLE_FAN, dg->mVertIndex, dg->mVertCount);
gl_RenderState.EnableTexture(true);
break;
case DrawTypeLine:
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
glDrawArrays(GL_LINES, dg->mVertIndex, dg->mVertCount);
gl_RenderState.EnableTexture(true);
break;
case DrawTypePixel:
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
glDrawArrays(GL_POINTS, dg->mVertIndex, dg->mVertCount);
gl_RenderState.EnableTexture(true);
break;
}
i += dg->mLen;
}
mVertices.Clear();
mData.Clear();
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
glset.lightmode = savedlightmode;
}

View file

@ -0,0 +1,73 @@
#ifndef __2DDRAWER_H
#define __2DDRAWER_H
#include "tarray.h"
#include "gl/data/gl_vertexbuffer.h"
class F2DDrawer : public FSimpleVertexBuffer
{
enum EDrawType
{
DrawTypeTexture,
DrawTypeDim,
DrawTypeFlatFill,
DrawTypePoly,
DrawTypeLine,
DrawTypePixel
};
struct DataGeneric
{
EDrawType mType;
uint32_t mLen;
int mVertIndex;
int mVertCount;
};
struct DataTexture : public DataGeneric
{
FMaterial *mTexture;
int mScissor[4];
uint32_t mColorOverlay;
int mTranslation;
FRenderStyle mRenderStyle;
bool mMasked;
bool mAlphaTexture;
};
struct DataFlatFill : public DataGeneric
{
FMaterial *mTexture;
};
struct DataSimplePoly : public DataGeneric
{
FMaterial *mTexture;
int mLightLevel;
FDynamicColormap *mColormap;
};
TArray<FSimpleVertex> mVertices;
TArray<uint8_t> mData;
int mLastLineCmd = -1; // consecutive lines can be batched into a single draw call so keep this info around.
int AddData(const DataGeneric *data);
public:
void AddTexture(FTexture *img, DrawParms &parms);
void AddDim(PalEntry color, float damount, int x1, int y1, int w, int h);
void AddClear(int left, int top, int right, int bottom, int palcolor, uint32 color);
void AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin);
void AddPoly(FTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, FDynamicColormap *colormap, int lightlevel);
void AddLine(int x1, int y1, int x2, int y2, int palcolor, uint32 color);
void AddPixel(int x1, int y1, int palcolor, uint32 color);
void Flush();
};
#endif

View file

@ -71,6 +71,7 @@
#include "gl/shaders/gl_tonemapshader.h"
#include "gl/shaders/gl_lensshader.h"
#include "gl/shaders/gl_presentshader.h"
#include "gl/renderer/gl_2ddrawer.h"
//==========================================================================
//
@ -283,6 +284,7 @@ void FGLRenderer::LensDistortScene()
void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
{
m2DDrawer->Flush(); // draw all pending 2D stuff before copying the buffer
if (FGLRenderBuffers::IsEnabled())
{
FGLPostProcessState savedState;

View file

@ -58,6 +58,7 @@
#include "gl/renderer/gl_lightdata.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/renderer/gl_2ddrawer.h"
#include "gl/data/gl_data.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl/scene/gl_drawinfo.h"
@ -106,6 +107,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mShaderManager = NULL;
gllight = glpart2 = glpart = mirrortexture = NULL;
mLights = NULL;
m2DDrawer = nullptr;
}
void gl_LoadModels();
@ -120,6 +122,7 @@ void FGLRenderer::Initialize()
mTonemapShader = new FTonemapShader();
mLensShader = new FLensShader();
mPresentShader = new FPresentShader();
m2DDrawer = new F2DDrawer;
// Only needed for the core profile, because someone decided it was a good idea to remove the default VAO.
if (gl.version >= 4.0)
@ -153,6 +156,7 @@ FGLRenderer::~FGLRenderer()
gl_FlushModels();
gl_DeleteAllAttachedLights();
FMaterial::FlushAll();
if (m2DDrawer != nullptr) delete m2DDrawer;
if (mShaderManager != NULL) delete mShaderManager;
if (mSamplerManager != NULL) delete mSamplerManager;
if (mVBO != NULL) delete mVBO;
@ -378,366 +382,13 @@ void FGLRenderer::ClearBorders()
int borderHeight = (trueHeight - height) / 2;
glViewport(0, 0, width, trueHeight);
gl_RenderState.mProjectionMatrix.loadIdentity();
gl_RenderState.mProjectionMatrix.ortho(0.0f, width * 1.0f, 0.0f, trueHeight, -1.0f, 1.0f);
gl_RenderState.SetColor(0.f ,0.f ,0.f ,1.f);
gl_RenderState.Set2DMode(true);
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
gl_RenderState.ApplyMatrices();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(0, borderHeight, 0, 0, 0); ptr++;
ptr->Set(0, 0, 0, 0, 0); ptr++;
ptr->Set(width, 0, 0, 0, 0); ptr++;
ptr->Set(width, borderHeight, 0, 0, 0); ptr++;
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
ptr->Set(0, trueHeight, 0, 0, 0); ptr++;
ptr->Set(0, trueHeight - borderHeight, 0, 0, 0); ptr++;
ptr->Set(width, trueHeight - borderHeight, 0, 0, 0); ptr++;
ptr->Set(width, trueHeight, 0, 0, 0); ptr++;
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
gl_RenderState.EnableTexture(true);
glClearColor(0, 0, 0, 1);
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, width, borderHeight);
glClear(GL_COLOR_BUFFER_BIT);
glScissor(0, trueHeight-borderHeight, width, borderHeight);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
glViewport(0, (trueHeight - height) / 2, width, height);
}
//==========================================================================
//
// Draws a texture
//
//==========================================================================
void FGLRenderer::DrawTexture(FTexture *img, DrawParms &parms)
{
double xscale = parms.destwidth / parms.texwidth;
double yscale = parms.destheight / parms.texheight;
double x = parms.x - parms.left * xscale;
double y = parms.y - parms.top * yscale;
double w = parms.destwidth;
double h = parms.destheight;
float u1, v1, u2, v2;
int light = 255;
FMaterial * gltex = FMaterial::ValidateTexture(img, false);
if (parms.colorOverlay && (parms.colorOverlay & 0xffffff) == 0)
{
// Right now there's only black. Should be implemented properly later
light = 255 - APART(parms.colorOverlay);
parms.colorOverlay = 0;
}
gl_SetRenderStyle(parms.style, !parms.masked, false);
if (!img->bHasCanvas)
{
int translation = 0;
if (!parms.alphaChannel)
{
if (parms.remap != NULL && !parms.remap->Inactive)
{
GLTranslationPalette * pal = static_cast<GLTranslationPalette*>(parms.remap->GetNative());
if (pal) translation = -pal->GetIndex();
}
}
gl_RenderState.SetMaterial(gltex, CLAMP_XY_NOMIP, translation, -1, !!(parms.style.Flags & STYLEF_RedIsAlpha));
u1 = gltex->GetUL();
v1 = gltex->GetVT();
u2 = gltex->GetUR();
v2 = gltex->GetVB();
}
else
{
gl_RenderState.SetMaterial(gltex, CLAMP_XY_NOMIP, 0, -1, false);
u1 = 0.f;
v1 = 1.f;
u2 = 1.f;
v2 = 0.f;
gl_RenderState.SetTextureMode(TM_OPAQUE);
}
if (parms.flipX)
{
float temp = u1;
u1 = u2;
u2 = temp;
}
if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
{
double wi = MIN(parms.windowright, parms.texwidth);
x += parms.windowleft * xscale;
w -= (parms.texwidth - wi + parms.windowleft) * xscale;
u1 = float(u1 + parms.windowleft / parms.texwidth);
u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth);
}
PalEntry color;
if (parms.style.Flags & STYLEF_ColorIsFixed)
{
color = parms.fillcolor;
}
else
{
color = PalEntry(light, light, light);
}
color.a = (BYTE)(parms.Alpha * 255);
// scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates
int btm = (SCREENHEIGHT - screen->GetHeight()) / 2;
btm = SCREENHEIGHT - btm;
glEnable(GL_SCISSOR_TEST);
int space = (static_cast<OpenGLFrameBuffer*>(screen)->GetTrueHeight()-screen->GetHeight())/2;
glScissor(parms.lclip, btm - parms.dclip + space, parms.rclip - parms.lclip, parms.dclip - parms.uclip);
gl_RenderState.SetColor(color);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.Apply();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(x, y, 0, u1, v1); ptr++;
ptr->Set(x, y + h, 0, u1, v2); ptr++;
ptr->Set(x + w, y, 0, u2, v1); ptr++;
ptr->Set(x + w, y + h, 0, u2, v2); ptr++;
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
if (parms.colorOverlay)
{
gl_RenderState.SetTextureMode(TM_MASK);
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_RenderState.BlendEquation(GL_FUNC_ADD);
gl_RenderState.SetColor(PalEntry(parms.colorOverlay));
gl_RenderState.Apply();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(x, y, 0, u1, v1); ptr++;
ptr->Set(x, y + h, 0, u1, v2); ptr++;
ptr->Set(x + w, y, 0, u2, v1); ptr++;
ptr->Set(x + w, y + h, 0, u2, v2); ptr++;
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
}
glScissor(0, 0, screen->GetWidth(), screen->GetHeight());
glDisable(GL_SCISSOR_TEST);
gl_RenderState.SetTextureMode(TM_MODULATE);
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_RenderState.BlendEquation(GL_FUNC_ADD);
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::DrawLine(int x1, int y1, int x2, int y2, int palcolor, uint32 color)
{
PalEntry p = color? (PalEntry)color : GPalette.BaseColors[palcolor];
gl_RenderState.EnableTexture(false);
gl_RenderState.SetColorAlpha(p, 1.f);
gl_RenderState.Apply();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(x1, y1, 0, 0, 0); ptr++;
ptr->Set(x2, y2, 0, 0, 0); ptr++;
GLRenderer->mVBO->RenderCurrent(ptr, GL_LINES);
gl_RenderState.EnableTexture(true);
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::DrawPixel(int x1, int y1, int palcolor, uint32 color)
{
PalEntry p = color? (PalEntry)color : GPalette.BaseColors[palcolor];
gl_RenderState.EnableTexture(false);
gl_RenderState.SetColorAlpha(p, 1.f);
gl_RenderState.Apply();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(x1, y1, 0, 0, 0); ptr++;
GLRenderer->mVBO->RenderCurrent(ptr, GL_POINTS);
gl_RenderState.EnableTexture(true);
}
//===========================================================================
//
//
//
//===========================================================================
void FGLRenderer::Dim(PalEntry color, float damount, int x1, int y1, int w, int h)
{
gl_RenderState.EnableTexture(false);
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_RenderState.AlphaFunc(GL_GREATER,0);
gl_RenderState.SetColorAlpha(color, damount);
gl_RenderState.Apply();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(x1, y1, 0, 0, 0); ptr++;
ptr->Set(x1, y1+h, 0, 0, 0); ptr++;
ptr->Set(x1+w, y1+h, 0, 0, 0); ptr++;
ptr->Set(x1+w, y1, 0, 0, 0); ptr++;
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);
gl_RenderState.EnableTexture(true);
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin)
{
float fU1,fU2,fV1,fV2;
FMaterial *gltexture=FMaterial::ValidateTexture(src, false);
if (!gltexture) return;
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
// scaling is not used here.
if (!local_origin)
{
fU1 = float(left) / src->GetWidth();
fV1 = float(top) / src->GetHeight();
fU2 = float(right) / src->GetWidth();
fV2 = float(bottom) / src->GetHeight();
}
else
{
fU1 = 0;
fV1 = 0;
fU2 = float(right-left) / src->GetWidth();
fV2 = float(bottom-top) / src->GetHeight();
}
gl_RenderState.ResetColor();
gl_RenderState.Apply();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
ptr->Set(left, top, 0, fU1, fV1); ptr++;
ptr->Set(left, bottom, 0, fU1, fV2); ptr++;
ptr->Set(right, top, 0, fU2, fV1); ptr++;
ptr->Set(right, bottom, 0, fU2, fV2); ptr++;
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP);
}
//==========================================================================
//
//
//
//==========================================================================
void FGLRenderer::Clear(int left, int top, int right, int bottom, int palcolor, uint32 color)
{
int rt;
int offY = 0;
PalEntry p = palcolor==-1 || color != 0? (PalEntry)color : GPalette.BaseColors[palcolor];
int width = right-left;
int height= bottom-top;
rt = screen->GetHeight() - top;
int space = (static_cast<OpenGLFrameBuffer*>(screen)->GetTrueHeight()-screen->GetHeight())/2; // ugh...
rt += space;
/*
if (!m_windowed && (m_trueHeight != m_height))
{
offY = (m_trueHeight - m_height) / 2;
rt += offY;
}
*/
glEnable(GL_SCISSOR_TEST);
glScissor(left, rt - height, width, height);
glClearColor(p.r/255.0f, p.g/255.0f, p.b/255.0f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.f, 0.f, 0.f, 0.f);
glDisable(GL_SCISSOR_TEST);
}
//==========================================================================
//
// D3DFB :: FillSimplePoly
//
// Here, "simple" means that a simple triangle fan can draw it.
//
//==========================================================================
void FGLRenderer::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, FDynamicColormap *colormap, int lightlevel)
{
if (npoints < 3)
{ // This is no polygon.
return;
}
FMaterial *gltexture = FMaterial::ValidateTexture(texture, false);
if (gltexture == NULL)
{
return;
}
FColormap cm;
cm = colormap;
// We cannot use the software light mode here because it doesn't properly calculate the light for 2D rendering.
SBYTE savedlightmode = glset.lightmode;
if (glset.lightmode == 8) glset.lightmode = 0;
gl_SetColor(lightlevel, 0, cm, 1.f);
glset.lightmode = savedlightmode;
gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
int i;
bool dorotate = rotation != 0;
float cosrot = cos(rotation.Radians());
float sinrot = sin(rotation.Radians());
//float yoffs = GatheringWipeScreen ? 0 : LBOffset;
float uscale = float(1.f / (texture->GetScaledWidth() * scalex));
float vscale = float(1.f / (texture->GetScaledHeight() * scaley));
if (gltexture->tex->bHasCanvas)
{
vscale = 0 - vscale;
}
float ox = float(originx);
float oy = float(originy);
gl_RenderState.Apply();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
for (i = 0; i < npoints; ++i)
{
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;
}
ptr->Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale);
ptr++;
}
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);
}

View file

@ -25,6 +25,7 @@ class FBlurShader;
class FTonemapShader;
class FLensShader;
class FPresentShader;
class F2DDrawer;
inline float DEG2RAD(float deg)
{
@ -107,6 +108,7 @@ public:
FFlatVertexBuffer *mVBO;
FSkyVertexBuffer *mSkyVBO;
FLightBuffer *mLights;
F2DDrawer *m2DDrawer;
GL_IRECT mScreenViewport;
GL_IRECT mOutputViewportLB;
@ -142,12 +144,6 @@ public:
void Begin2D();
void ClearBorders();
void DrawTexture(FTexture *img, DrawParms &parms);
void DrawLine(int x1, int y1, int x2, int y2, int palcolor, uint32 color);
void DrawPixel(int x1, int y1, int palcolor, uint32 color);
void Dim(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);
void Clear(int left, int top, int right, int bottom, int palcolor, uint32 color);
void ProcessLowerMiniseg(seg_t *seg, sector_t * frontsector, sector_t * backsector);
void ProcessSprite(AActor *thing, sector_t *sector, bool thruportal);
@ -175,6 +171,9 @@ public:
bool StartOffscreen();
void EndOffscreen();
void StartSimplePolys();
void FinishSimplePolys();
void FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley,
DAngle rotation, FDynamicColormap *colormap, int lightlevel);

View file

@ -64,6 +64,7 @@
#include "gl/utility/gl_clock.h"
#include "gl/utility/gl_templates.h"
#include "gl/gl_functions.h"
#include "gl/renderer/gl_2ddrawer.h"
IMPLEMENT_CLASS(OpenGLFrameBuffer)
EXTERN_CVAR (Float, vid_brightness)
@ -386,7 +387,8 @@ bool OpenGLFrameBuffer::Begin2D(bool)
void OpenGLFrameBuffer::DrawTextureParms(FTexture *img, DrawParms &parms)
{
if (GLRenderer != NULL) GLRenderer->DrawTexture(img, parms);
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddTexture(img, parms);
}
//==========================================================================
@ -396,8 +398,8 @@ void OpenGLFrameBuffer::DrawTextureParms(FTexture *img, DrawParms &parms)
//==========================================================================
void OpenGLFrameBuffer::DrawLine(int x1, int y1, int x2, int y2, int palcolor, uint32 color)
{
if (GLRenderer != NULL)
GLRenderer->DrawLine(x1, y1, x2, y2, palcolor, color);
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddLine(x1, y1, x2, y2, palcolor, color);
}
//==========================================================================
@ -407,8 +409,8 @@ void OpenGLFrameBuffer::DrawLine(int x1, int y1, int x2, int y2, int palcolor, u
//==========================================================================
void OpenGLFrameBuffer::DrawPixel(int x1, int y1, int palcolor, uint32 color)
{
if (GLRenderer != NULL)
GLRenderer->DrawPixel(x1, y1, palcolor, color);
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddPixel(x1, y1, palcolor, color);
}
//==========================================================================
@ -425,8 +427,8 @@ void OpenGLFrameBuffer::Dim(PalEntry)
void OpenGLFrameBuffer::Dim(PalEntry color, float damount, int x1, int y1, int w, int h)
{
if (GLRenderer != NULL)
GLRenderer->Dim(color, damount, x1, y1, w, h);
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddDim(color, damount, x1, y1, w, h);
}
//==========================================================================
@ -437,8 +439,8 @@ void OpenGLFrameBuffer::Dim(PalEntry color, float damount, int x1, int y1, int w
void OpenGLFrameBuffer::FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin)
{
if (GLRenderer != NULL)
GLRenderer->FlatFill(left, top, right, bottom, src, local_origin);
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddFlatFill(left, top, right, bottom, src, local_origin);
}
//==========================================================================
@ -448,8 +450,8 @@ void OpenGLFrameBuffer::FlatFill (int left, int top, int right, int bottom, FTex
//==========================================================================
void OpenGLFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor, uint32 color)
{
if (GLRenderer != NULL)
GLRenderer->Clear(left, top, right, bottom, palcolor, color);
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr)
GLRenderer->m2DDrawer->AddClear(left, top, right, bottom, palcolor, color);
}
//==========================================================================
@ -464,10 +466,9 @@ void OpenGLFrameBuffer::FillSimplePoly(FTexture *texture, FVector2 *points, int
double originx, double originy, double scalex, double scaley,
DAngle rotation, FDynamicColormap *colormap, int lightlevel)
{
if (GLRenderer != NULL)
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr && npoints >= 3)
{
GLRenderer->FillSimplePoly(texture, points, npoints, originx, originy, scalex, scaley,
rotation, colormap, lightlevel);
GLRenderer->m2DDrawer->AddPoly(texture, points, npoints, originx, originy, scalex, scaley, rotation, colormap, lightlevel);
}
}

View file

@ -61,6 +61,7 @@
#include "gl/textures/gl_samplers.h"
#include "gl/utility/gl_templates.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl/renderer/gl_2ddrawer.h"
#ifndef _WIN32
struct POINT {
@ -187,6 +188,7 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type)
void OpenGLFrameBuffer::WipeEndScreen()
{
GLRenderer->m2DDrawer->Flush();
wipeendscreen = new FHardwareTexture(Width, Height, true);
wipeendscreen->CreateTexture(NULL, Width, Height, 0, false, 0);
GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1);
@ -288,8 +290,8 @@ OpenGLFrameBuffer::Wiper::~Wiper()
void OpenGLFrameBuffer::Wiper::MakeVBO(OpenGLFrameBuffer *fb)
{
FFlatVertex make[4];
FFlatVertex *ptr = make;
FSimpleVertex make[4];
FSimpleVertex *ptr = make;
float ur = fb->GetWidth() / FHardwareTexture::GetTexDimension(fb->GetWidth());
float vb = fb->GetHeight() / FHardwareTexture::GetTexDimension(fb->GetHeight());
@ -380,8 +382,8 @@ OpenGLFrameBuffer::Wiper_Melt::Wiper_Melt()
int OpenGLFrameBuffer::Wiper_Melt::MakeVBO(int ticks, OpenGLFrameBuffer *fb, bool &done)
{
FFlatVertex *make = new FFlatVertex[321*4];
FFlatVertex *ptr = make;
FSimpleVertex *make = new FSimpleVertex[321*4];
FSimpleVertex *ptr = make;
int dy;
float ur = fb->GetWidth() / FHardwareTexture::GetTexDimension(fb->GetWidth());