- use the engine backend to render the scene

This commit is contained in:
Christoph Oelckers 2020-06-11 18:40:53 +02:00
parent 76884c1e18
commit 22aad4999c
19 changed files with 517 additions and 246 deletions

View file

@ -639,6 +639,7 @@ file( GLOB HEADER_FILES
common/thirdparty/math/*h
common/rendering/*.h
common/rendering/gl_load/*.h
common/rendering/hwrenderer/*.h
common/rendering/hwrenderer/data/*.h
common/rendering/polyrenderer/*.h
common/rendering/polyrenderer/math/*.h
@ -923,6 +924,7 @@ set (PCH_SOURCES
common/rendering/v_video.cpp
common/rendering/r_thread.cpp
common/rendering/r_videoscale.cpp
common/rendering/hwrenderer/hw_draw2d.cpp
common/rendering/hwrenderer/data/hw_clock.cpp
common/rendering/hwrenderer/data/hw_skydome.cpp
common/rendering/hwrenderer/data/flatvertices.cpp
@ -1093,6 +1095,7 @@ include_directories(
common/fonts
common/objects
common/rendering
common/rendering/hwrenderer
common/rendering/hwrenderer/data
common/rendering/gl_load
common/rendering/gl

View file

@ -4017,6 +4017,8 @@ int32_t videoSetGameMode(char davidoption, int32_t daupscaledxdim, int32_t daups
return 0;
}
void DrawFullscreenBlends();
//
// nextpage
//
@ -4036,6 +4038,9 @@ void videoNextPage(void)
recursion = false;
}
// Handle the final 2D overlays.
DrawFullscreenBlends();
DrawRateStuff();
if (in3dmode())
{

View file

@ -1591,7 +1591,7 @@ static int32_t polymost_md3draw(md3model_t *m, tspriteptr_t tspr)
{
double f = (double) (tspr->owner + 1) * (std::numeric_limits<double>::epsilon() * 8.0);
if (f != 0.0) f *= 1.0/(double) (sepldist(globalposx - tspr->x, globalposy - tspr->y)>>5);
GLInterface.SetDepthFunc(Depth_LessEqual);
GLInterface.SetDepthFunc(DF_LEqual);
}
int winding = ((grhalfxdown10x >= 0) ^((globalorientation&8) != 0) ^((globalorientation&4) != 0))? Winding_CW : Winding_CCW;
@ -1786,9 +1786,6 @@ static int32_t polymost_md3draw(md3model_t *m, tspriteptr_t tspr)
md3draw_handle_triangles(s, indexhandle, 1, NULL);
}
GLInterface.UseDetailMapping(false);
GLInterface.UseGlowMapping(false);
}
//------------

View file

@ -24,7 +24,6 @@ Ken Silverman's official web site: http://www.advsys.net/ken
CVAR(Bool, hw_detailmapping, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Bool, hw_glowmapping, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Bool, hw_polygonmode, 0, 0)
CVARD(Bool, hw_animsmoothing, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "enable/disable model animation smoothing")
CVARD(Bool, hw_hightile, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "enable/disable hightile texture rendering")
CVARD(Bool, hw_models, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "enable/disable model rendering")
@ -182,17 +181,6 @@ FileReader GetBaseResource(const char* fn);
static void resizeglcheck(void)
{
//FUK
if (lastglpolygonmode != hw_polygonmode)
{
lastglpolygonmode = hw_polygonmode;
GLInterface.SetWireframe(hw_polygonmode == 1);
}
if (hw_polygonmode) //FUK
{
GLInterface.ClearScreen(0xffffff, true);
}
const int32_t ourxdimen = (windowxy2.x-windowxy1.x+1);
float ratio = 1;
const int32_t fovcorrect = (int32_t)(ourxdimen*ratio - ourxdimen);
@ -490,8 +478,6 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
GLInterface.Draw(DT_TriangleFan, data.second, npoints);
GLInterface.SetTinting(-1, 0xffffff, 0xffffff);
GLInterface.UseDetailMapping(false);
GLInterface.UseGlowMapping(false);
GLInterface.SetNpotEmulation(0.f, 0.f);
if (skyzbufferhack && skyzbufferhack_pass == 0)
@ -3063,7 +3049,7 @@ void polymost_drawrooms()
GLInterface.EnableBlend(false);
GLInterface.EnableAlphaTest(false);
GLInterface.EnableDepthTest(true);
GLInterface.SetDepthFunc(Depth_LessEqual);
GLInterface.SetDepthFunc(DF_LEqual);
gvrcorrection = viewingrange*(1.f/65536.f);
//if (glprojectionhacks == 2)
@ -3168,7 +3154,7 @@ void polymost_drawrooms()
if (n < 3)
{
GLInterface.SetDepthFunc(Depth_LessEqual);
GLInterface.SetDepthFunc(DF_LEqual);
return;
}
@ -3301,7 +3287,7 @@ void polymost_drawrooms()
}
renderFinishScene();
GLInterface.SetDepthFunc(Depth_LessEqual);
GLInterface.SetDepthFunc(DF_LEqual);
}
static void polymost_drawmaskwallinternal(int32_t wallIndex)

View file

@ -1080,7 +1080,7 @@ int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr)
if (shadowHack)
{
GLInterface.SetDepthFunc(Depth_LessEqual);
GLInterface.SetDepthFunc(DF_LEqual);
}
@ -1215,7 +1215,7 @@ int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr)
if (shadowHack)
{
GLInterface.SetDepthFunc(Depth_Less);
GLInterface.SetDepthFunc(DF_Less);
}
GLInterface.SetIdentityMatrix(Matrix_Model);
GLInterface.SetFadeDisable(false);

View file

@ -651,7 +651,6 @@ void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, unsigne
dg.mTexture = img;
dg.mTranslationId = translation;
dg.mColor1 = color;
dg.mVertCount = (int)vtcount;
dg.mVertIndex = (int)mVertices.Reserve(vtcount);
dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent];

View file

@ -36,6 +36,7 @@
#include "templates.h"
#include "hw_vrmodes.h"
#include "v_draw.h"
#include "i_interface.h"
extern bool vid_hdr_active;

View file

@ -155,7 +155,7 @@ struct FVector4PalEntry
r = newvalue.r * normScale;
g = newvalue.g * normScale;
b = newvalue.b * normScale;
a = 1;
a = newvalue.a;
return *this;
}
@ -500,6 +500,12 @@ public:
mStreamData.uTextureBlendColor = texfx->BlendColor;
}
}
void SetTextureColors(float* modColor, float* addColor, float* blendColor)
{
mStreamData.uTextureAddColor.SetFlt(addColor[0], addColor[1], addColor[2], addColor[3]);
mStreamData.uTextureModulateColor.SetFlt(modColor[0], modColor[1], modColor[2], modColor[3]);
mStreamData.uTextureBlendColor.SetFlt(blendColor[0], blendColor[1], blendColor[2], blendColor[3]);
}
void SetFog(PalEntry c, float d)
{
@ -563,6 +569,8 @@ public:
mMaterial.mOverrideShader = overrideshader;
mMaterial.mChanged = true;
mTextureModeFlags = mat->GetLayerFlags();
auto scale = mat->GetDetailScale();
mStreamData.uDetailParms = { scale.X, scale.Y, 0, 0 };
}
void SetMaterial(FGameTexture* tex, EUpscaleFlags upscalemask, int scaleflags, int clampmode, int translation, int overrideshader)

View file

@ -0,0 +1,241 @@
/*
** 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.
**---------------------------------------------------------------------------
**
*/
#include "v_video.h"
#include "cmdlib.h"
#include "hwrenderer/data/buffers.h"
#include "flatvertices.h"
#include "hwrenderer/data/hw_viewpointbuffer.h"
#include "hw_clock.h"
#include "hw_cvars.h"
#include "hw_renderstate.h"
#include "r_videoscale.h"
#include "v_draw.h"
//===========================================================================
//
// Vertex buffer for 2D drawer
//
//===========================================================================
class F2DVertexBuffer
{
IVertexBuffer *mVertexBuffer;
IIndexBuffer *mIndexBuffer;
public:
F2DVertexBuffer()
{
mVertexBuffer = screen->CreateVertexBuffer();
mIndexBuffer = screen->CreateIndexBuffer();
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.
//
//===========================================================================
CVAR(Bool, gl_aalines, false, CVAR_ARCHIVE)
EXTERN_CVAR(Bool, hw_use_backend);
#include "glbackend/glbackend.h"
void Draw2D(F2DDrawer *drawer, FRenderState &state)
{
// This is still needed for testing until things are working.
if (!hw_use_backend)
{
GLInterface.Draw2D(drawer);
return;
}
twoD.Clock();
const auto &mScreenViewport = screen->mScreenViewport;
state.SetViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
screen->mViewpoints->Set2D(state, twod->GetWidth(), twod->GetHeight());
state.EnableDepthTest(false);
state.EnableMultisampling(false);
state.EnableLineSmooth(gl_aalines);
auto &vertices = drawer->mVertices;
auto &indices = drawer->mIndices;
auto &commands = drawer->mData;
if (commands.Size() == 0)
{
twoD.Unclock();
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());
state.SetVertexBuffer(&vb);
state.EnableFog(false);
for(auto &cmd : commands)
{
int gltrans = -1;
state.SetRenderStyle(cmd.mRenderStyle);
state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed));
state.EnableFog(2); // Special 2D mode 'fog'.
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;
// If coordinates turn out negative, clip to sceen here to avoid undefined behavior.
if (sciX < 0) sciW += sciX, sciX = 0;
if (sciY < 0) sciH += sciY, sciY = 0;
}
else
{
sciX = sciY = sciW = sciH = -1;
}
state.SetScissor(sciX, sciY, sciW, sciH);
if (cmd.mSpecialColormap[0].a != 0)
{
state.SetTextureMode(TM_FIXEDCOLORMAP);
state.SetObjectColor(cmd.mSpecialColormap[0]);
state.SetAddColor(cmd.mSpecialColormap[1]);
}
state.SetFog(cmd.mColor1, 0);
state.SetColor(1, 1, 1, 1, cmd.mDesaturate);
state.AlphaFunc(Alpha_GEqual, 0.f);
if (cmd.mTexture != nullptr && cmd.mTexture->isValid())
{
auto flags = cmd.mTexture->GetUseType() >= ETextureType::Special? UF_None : cmd.mTexture->GetUseType() == ETextureType::FontChar? UF_Font : UF_Texture;
state.SetMaterial(cmd.mTexture, flags, 0, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : CLAMP_XY_NOMIP, cmd.mTranslationId, -1);
state.EnableTexture(true);
// Canvas textures are stored upside down
if (cmd.mTexture->isHardwareCanvas())
{
state.mTextureMatrix.loadIdentity();
state.mTextureMatrix.scale(1.f, -1.f, 1.f);
state.mTextureMatrix.translate(0.f, 1.f, 0.0f);
state.EnableTextureMatrix(true);
}
if (cmd.mFlags & F2DDrawer::DTF_Burn)
{
state.SetEffect(EFF_BURN);
}
}
else
{
state.EnableTexture(false);
}
switch (cmd.mType)
{
default:
case F2DDrawer::DrawTypeTriangles:
state.DrawIndexed(DT_Triangles, cmd.mIndexIndex, cmd.mIndexCount);
break;
case F2DDrawer::DrawTypeLines:
state.Draw(DT_Lines, cmd.mVertIndex, cmd.mVertCount);
break;
case F2DDrawer::DrawTypePoints:
state.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);
state.SetVertexBuffer(screen->mVertexData);
state.EnableTexture(true);
state.EnableBrightmap(true);
state.SetTextureMode(TM_NORMAL);
state.EnableFog(false);
state.ResetColor();
drawer->mIsFirstPass = false;
twoD.Unclock();
}

View file

@ -11,7 +11,6 @@ class FxAddSub;
struct BuildInfo;
class FMultipatchTextureBuilder;
class FScanner;
int PalCheck(int tex);
// Texture manager
class FTextureManager

View file

@ -49,10 +49,6 @@
LookupTableInfo lookups;
uint8_t curbasepal;
int32_t globalblend;
PalEntry palfadergb;
//==========================================================================
//
// Adds a palette to the global list of base palettes
@ -418,9 +414,16 @@ void LookupTableInfo::setPaletteTint(int palnum, int r, int g, int b, int sr, in
//==========================================================================
//
//
// todo: everything below belongs elsewhere. Move it out
//
//==========================================================================
#include "v_2ddrawer.h"
uint8_t curbasepal;
PalEntry palfadergb;
static int32_t tint_blood_r = 0, tint_blood_g = 0, tint_blood_b = 0;
glblend_t glblend[MAXBLENDTABS];
void videoSetPalette(int dabrightness, int palid, ESetPalFlags flags)
{
@ -449,7 +452,6 @@ glblend_t const defaultglblend =
},
};
glblend_t glblend[MAXBLENDTABS];
FRenderStyle GetRenderStyle(int blend, int def)
{
@ -477,3 +479,33 @@ float GetAlphaFromBlend(uint32_t method, uint32_t blend)
{
return method == DAMETH_TRANS1 || method == DAMETH_TRANS2 ? glblend[blend].def[method - DAMETH_TRANS1].alpha : 1.f;
}
//==========================================================================
//
// Fullscreen blend effects
//
//==========================================================================
void DrawFullscreenBlends()
{
// These get prepended to the 2D drawer so they must be submitted in reverse order of drawing.
if (tint_blood_r | tint_blood_g | tint_blood_b)
{
PalEntry color2(255, std::max(-tint_blood_r, 0), std::max(-tint_blood_g, 0), std::max(-tint_blood_b, 0));
twod->AddColorOnlyQuad(0, 0, twod->GetWidth(), twod->GetHeight(), color2, &LegacyRenderStyles[STYLE_Subtract], true);
PalEntry color(255, std::max(tint_blood_r, 0), std::max(tint_blood_g, 0), std::max(tint_blood_b, 0));
twod->AddColorOnlyQuad(0, 0, twod->GetWidth(), twod->GetHeight(), color, &LegacyRenderStyles[STYLE_Add], true);
}
if (palfadergb.a > 0)
{
twod->AddColorOnlyQuad(0, 0, twod->GetWidth(), twod->GetHeight(), palfadergb, &LegacyRenderStyles[STYLE_Translucent], true);
}
}
void videoTintBlood(int32_t r, int32_t g, int32_t b)
{
tint_blood_r = r;
tint_blood_g = g;
tint_blood_b = b;
}

View file

@ -162,7 +162,6 @@ inline void videoFadePalette(uint8_t r, uint8_t g, uint8_t b, uint8_t offset)
void videoTintBlood(int32_t r, int32_t g, int32_t b);
extern int32_t globalpal;
extern int32_t globalblend;
extern void paletteLoadFromDisk(void);

View file

@ -74,20 +74,20 @@ bool GLInstance::SetTexture(int picnum, FGameTexture* tex, int paletteid, int sa
// This is intentionally the same value for both parameters. The shader does not use the same uniform for modulation and overlay colors.
GLInterface.SetTinting(texpick.tintFlags, texpick.tintColor, texpick.tintColor);
SetTinting(texpick.tintFlags, texpick.tintColor, texpick.tintColor);
if (texpick.translation != 0)
{
int lookuppal = texpick.translation & 0x7fffffff;
GLInterface.SetPalette(GetTranslationType(lookuppal) - Translation_Remap);
GLInterface.SetPalswap(GetTranslationIndex(lookuppal));
SetPalette(GetTranslationType(lookuppal) - Translation_Remap);
SetPalswap(GetTranslationIndex(lookuppal));
}
else
{
GLInterface.SetPalette(0);
GLInterface.SetPalswap(0);
SetPalette(0);
SetPalswap(0);
}
GLInterface.SetBasepalTint(texpick.basepalTint);
SetBasepalTint(texpick.basepalTint);
auto &mat = renderState.mMaterial;
mat.mMaterial = FMaterial::ValidateTexture(tex, 0); // todo allow scaling
mat.mClampMode = sampler;
@ -97,9 +97,6 @@ bool GLInstance::SetTexture(int picnum, FGameTexture* tex, int paletteid, int sa
if (TextureType == TT_INDEXED) renderState.Flags |= RF_UsePalette;
else renderState.Flags &= ~RF_UsePalette;
GLInterface.SetAlphaThreshold(tex->alphaThreshold);
UseBrightmaps(tex->GetBrightmap() != nullptr);
UseGlowMapping(tex->GetGlowmap() != nullptr);
UseDetailMapping(tex->GetDetailmap() != nullptr);
return true;
}
@ -109,11 +106,6 @@ bool GLInstance::SetTexture(int picnum, FGameTexture* tex, int paletteid, int sa
//
//===========================================================================
int PalCheck(int tex)
{
return tex;
}
void InitBuildTiles()
{

View file

@ -56,10 +56,14 @@
#include "hw_viewpointuniforms.h"
#include "hw_viewpointbuffer.h"
#include "gl_renderstate.h"
#include "hw_cvars.h"
F2DDrawer twodpsp;
static int BufferLock = 0;
CVAR(Bool, hw_use_backend, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
static int blendstyles[] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA };
static int renderops[] = { GL_FUNC_ADD, GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT };
int depthf[] = { GL_ALWAYS, GL_LESS, GL_EQUAL, GL_LEQUAL };
@ -160,19 +164,13 @@ void GLInstance::LoadPolymostShader()
void GLInstance::InitGLState(int fogmode, int multisample)
{
glShadeModel(GL_SMOOTH); // GL_FLAT
glEnable(GL_TEXTURE_2D);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (multisample > 0 )
{
//glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
glEnable(GL_MULTISAMPLE);
}
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
// This is a bad place to call this but without deconstructing the entire render loops in all front ends there is no way to have a well defined spot for this stuff.
// Before doing that the backend needs to work in some fashion, so we have to make sure everything is set up when the first render call is performed.
screen->BeginFrame();
@ -183,14 +181,6 @@ void GLInstance::InitGLState(int fogmode, int multisample)
void GLInstance::Deinit()
{
#if 0
if (im_ctx)
{
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext(im_ctx);
}
#endif
if (polymostShader) delete polymostShader;
polymostShader = nullptr;
activeShader = nullptr;
@ -264,11 +254,22 @@ void GLInstance::DrawElement(EDrawType type, size_t start, size_t count, Polymos
void GLInstance::DoDraw()
{
for (auto& rs : rendercommands)
if (hw_use_backend)
{
glVertexAttrib4fv(2, rs.Color);
rs.Apply(polymostShader, lastState);
glDrawArrays(primtypes[rs.primtype], rs.vindex, rs.vcount);
for (auto& rs : rendercommands)
{
rs.Apply(*screen->RenderState(), lastState);
screen->RenderState()->Draw(rs.primtype, rs.vindex, rs.vcount);
}
}
else
{
for (auto& rs : rendercommands)
{
glVertexAttrib4fv(2, rs.Color);
rs.Apply(polymostShader, lastState);
glDrawArrays(primtypes[rs.primtype], rs.vindex, rs.vcount);
}
}
rendercommands.Clear();
matrixArray.Resize(1);
@ -296,11 +297,8 @@ void GLInstance::ReadPixels(int xdim, int ydim, uint8_t* buffer)
void GLInstance::SetPolymostShader()
{
if (activeShader != polymostShader)
{
polymostShader->Bind();
activeShader = polymostShader;
}
polymostShader->Bind();
activeShader = polymostShader;
}
void GLInstance::SetPalette(int index)
@ -315,29 +313,15 @@ void GLInstance::SetPalswap(int index)
renderState.ShadeDiv = lookups.tables[index].ShadeFactor;
}
void GLInstance::DrawImGui(ImDrawData* data)
{
#if 0
ImGui_ImplOpenGL3_RenderDrawData(data);
#endif
}
//===========================================================================
//
// Binds a texture to the renderer
//
//===========================================================================
void PolymostRenderState::ApplyMaterial(FMaterial* mat, int clampmode, int translation, int overrideshader)
void PolymostRenderState::ApplyMaterial(FMaterial* mat, int clampmode, int translation, int overrideshader, PolymostShader* shader)
{
auto tex = mat->Source();
//mEffectState = overrideshader >= 0 ? overrideshader : mat->GetShaderIndex();
//mShaderTimer = tex->GetShaderSpeed();
//SetSpecular(tex->GetGlossiness(), tex->GetSpecularLevel());
//if (tex->isHardwareCanvas()) static_cast<FCanvasTexture*>(tex->GetTexture())->NeedUpdate();
clampmode = tex->GetClampMode(clampmode);
// avoid rebinding the same texture multiple times.
@ -364,24 +348,18 @@ void PolymostRenderState::ApplyMaterial(FMaterial* mat, int clampmode, int trans
scf |= layer->scaleFlags;
if (base->BindOrCreate(layer->layerTexture, 0, layer->clampflags == -1? clampmode : layer->clampflags, translation, scf))
{
int LayerFlags = 0;
for (int i = 1; i < numLayers; i++)
{
auto systex = static_cast<OpenGLRenderer::FHardwareTexture*>(mat->GetLayer(i, 0, &layer));
// fixme: Upscale flags must be disabled for certain layers.
systex->BindOrCreate(layer->layerTexture, i, layer->clampflags == -1 ? clampmode : layer->clampflags, 0, layer->scaleFlags);
maxbound = i;
LayerFlags |= 32768 << i;
}
shader->TextureMode.Set(LayerFlags);
}
// The palette lookup must be done manually.
#if 0
// unbind everything from the last texture that's still active
for (int i = maxbound + 1; i <= 16/*maxBoundMaterial*/; i++)
{
OpenGLRenderer::FHardwareTexture::Unbind(i);
//maxBoundMaterial = maxbound;
}
#endif
}
void PolymostRenderState::Apply(PolymostShader* shader, GLState& oldState)
@ -393,7 +371,7 @@ void PolymostRenderState::Apply(PolymostShader* shader, GLState& oldState)
if (mMaterial.mChanged)
{
mMaterial.mChanged = false;
ApplyMaterial(mMaterial.mMaterial, mMaterial.mClampMode, mMaterial.mTranslation, mMaterial.mOverrideShader);
ApplyMaterial(mMaterial.mMaterial, mMaterial.mClampMode, mMaterial.mTranslation, mMaterial.mOverrideShader, shader);
float buffer[] = { mMaterial.mMaterial->GetDetailScale().X, mMaterial.mMaterial->GetDetailScale().Y, 1.f, 0.f };
shader->DetailParms.Set(buffer);
}
@ -472,10 +450,6 @@ void PolymostRenderState::Apply(PolymostShader* shader, GLState& oldState)
if (StateFlags & STF_DEPTHMASK) glDepthMask(1);
else glDepthMask(0);
}
if ((StateFlags ^ oldState.Flags) & STF_WIREFRAME)
{
glPolygonMode(GL_FRONT_AND_BACK, (StateFlags & STF_WIREFRAME) ? GL_LINE : GL_FILL);
}
if (StateFlags & (STF_CLEARCOLOR | STF_CLEARDEPTH))
{
glClearColor(ClearColor.r / 255.f, ClearColor.g / 255.f, ClearColor.b / 255.f, 1.f);
@ -543,7 +517,6 @@ void PolymostRenderState::Apply(PolymostShader* shader, GLState& oldState)
else shader->muFogEnabled.Set(0);
shader->Flags.Set(Flags);
shader->TextureMode.Set(LayerFlags);
shader->NPOTEmulation.Set(&NPOTEmulation.X);
shader->AlphaThreshold.Set(AlphaTest ? AlphaThreshold : -1.f);
shader->FogColor.Set((Flags& RF_MapFog)? PalEntry(0x999999) : FogColor);
@ -584,6 +557,147 @@ void PolymostRenderState::Apply(PolymostShader* shader, GLState& oldState)
memset(matrixIndex, -1, sizeof(matrixIndex));
}
void PolymostRenderState::Apply(FRenderState& state, GLState& oldState)
{
if (Flags & RF_ColorOnly)
{
state.EnableTexture(false);
}
else
{
state.EnableTexture(true);
state.SetMaterial(mMaterial.mMaterial, mMaterial.mClampMode, mMaterial.mTranslation, mMaterial.mOverrideShader);
}
/* todo: bind indexed textures */
state.SetColor(Color[0], Color[1], Color[2], Color[3]);
if (StateFlags != oldState.Flags)
{
state.EnableDepthTest(StateFlags & STF_DEPTHTEST);
state.EnableMultisampling(StateFlags & STF_MULTISAMPLE);
state.SetTextureMode((StateFlags & STF_BLEND) ? TM_OPAQUE : TM_NORMAL);
if ((StateFlags ^ oldState.Flags) & (STF_STENCILTEST | STF_STENCILWRITE))
{
if (StateFlags & STF_STENCILWRITE)
{
state.EnableStencil(true);
state.SetEffect(EFF_STENCIL);
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff);
}
else if (StateFlags & STF_STENCILTEST)
{
state.EnableStencil(true);
state.SetEffect(EFF_NONE);
state.SetStencil(1, SOP_Keep, SF_DepthMaskOff);
}
else
{
state.EnableStencil(false);
state.SetEffect(EFF_NONE);
}
}
if ((StateFlags ^ oldState.Flags) & (STF_CULLCW | STF_CULLCCW))
{
int cull = Cull_None;
if (StateFlags & STF_CULLCCW) cull = Cull_CCW;
else if (StateFlags & STF_CULLCW) cull = Cull_CW;
state.SetCulling(cull);
}
state.SetColorMask(StateFlags & STF_COLORMASK);
state.SetDepthMask(StateFlags & STF_DEPTHMASK);
if (StateFlags & (STF_CLEARCOLOR | STF_CLEARDEPTH))
{
int clear = 0;
//if (StateFlags & STF_CLEARCOLOR) clear |= CT_Color;
if (StateFlags & STF_CLEARDEPTH) clear |= CT_Depth;
state.Clear(clear);
}
if (StateFlags & STF_VIEWPORTSET)
{
state.SetViewport(vp_x, vp_y, vp_w, vp_h);
}
if (StateFlags & STF_SCISSORSET)
{
state.SetScissor(sc_x, sc_y, sc_w, sc_h);
}
state.SetDepthBias(mBias.mFactor, mBias.mUnits);
StateFlags &= ~(STF_CLEARCOLOR | STF_CLEARDEPTH | STF_VIEWPORTSET | STF_SCISSORSET);
oldState.Flags = StateFlags;
}
state.SetRenderStyle(Style);
if (DepthFunc != oldState.DepthFunc)
{
state.SetDepthFunc(DepthFunc);
oldState.DepthFunc = DepthFunc;
}
// Disable brightmaps if non-black fog is used.
if (!(Flags & RF_FogDisabled) && ShadeDiv >= 1 / 1000.f)
{
state.EnableFog(FogColor.isBlack() && !(Flags & RF_MapFog) ? 1 : -1);
}
else state.EnableFog(0);
state.SetFog((Flags & RF_MapFog) ? PalEntry(0x999999) : FogColor, 21.f); // Fixme: The real density still needs to be implemented. 21 is a reasonable default only.
state.SetSoftLightLevel(ShadeDiv >= 1 / 1000.f ? 255 - Scale(Shade, 255, numshades) : 255);
state.SetLightParms(VisFactor, ShadeDiv / (numshades - 2));
state.SetNpotEmulation(NPOTEmulation.Y, NPOTEmulation.X);
state.AlphaFunc(Alpha_Greater, AlphaTest ? AlphaThreshold : -1.f);
FVector4 addcol(0, 0, 0, 0);
FVector4 modcol(fullscreenTint.r / 255.f, fullscreenTint.g / 255.f, fullscreenTint.b / 255.f, 1);
FVector4 blendcol(0, 0, 0, 0);
int flags = 0;
if (fullscreenTint != 0xffffff) flags |= 16;
if (hictint_flags != -1)
{
flags |= TextureManipulation::ActiveBit;
if (hictint_flags & TINTF_COLORIZE)
{
modcol.X *= hictint.r / 64.f;
modcol.Y *= hictint.g / 64.f;
modcol.Z *= hictint.b / 64.f;
}
if (hictint_flags & TINTF_GRAYSCALE)
modcol.W = 1.f;
if (hictint_flags & TINTF_INVERT)
flags |= TextureManipulation::InvertBit;
if (hictint_flags & TINTF_BLENDMASK)
{
blendcol = modcol; // WTF???, but the tinting code really uses the same color for both!
flags |= (((hictint_flags & TINTF_BLENDMASK) >> 6) + 1) & TextureManipulation::BlendMask;
}
addcol.W = flags;
}
state.SetTextureColors(&modcol.X, &addcol.X, &blendcol.X);
if (matrixIndex[Matrix_Model] != -1)
{
state.EnableModelMatrix(true);
state.mModelMatrix = matrixArray[matrixIndex[Matrix_Model]];
}
else state.EnableModelMatrix(false);
memset(matrixIndex, -1, sizeof(matrixIndex));
}
void DoWriteSavePic(FileWriter* file, ESSType ssformat, uint8_t* scr, int width, int height, bool upsidedown)
{
int pixelsize = 3;
int pitch = width * pixelsize;
if (upsidedown)
{
scr += ((height - 1) * width * pixelsize);
pitch *= -1;
}
M_CreatePNG(file, scr, nullptr, ssformat, width, height, pitch, vid_gamma);
}
//===========================================================================
//
// Render the view to a savegame picture
@ -597,15 +711,20 @@ void WriteSavePic(FileWriter* file, int width, int height)
bounds.top = 0;
bounds.width = width;
bounds.height = height;
auto& RenderState = *screen->RenderState();
// we must be sure the GPU finished reading from the buffer before we fill it with new data.
glFinish();
screen->mVertexData->Reset();
// Switch to render buffers dimensioned for the savepic
OpenGLRenderer::GLRenderer->mBuffers = OpenGLRenderer::GLRenderer->mSaveBuffers;
OpenGLRenderer::GLRenderer->mBuffers->BindSceneFB(false);
screen->SetViewportRects(&bounds);
screen->SetSaveBuffers(true);
screen->ImageTransitionScene(true);
RenderState.SetVertexBuffer(screen->mVertexData);
screen->mVertexData->Reset();
//screen->mLights->Clear();
screen->mViewpoints->Clear();
int oldx = xdim;
int oldy = ydim;
@ -625,27 +744,17 @@ void WriteSavePic(FileWriter* file, int width, int height)
// The 2D drawers can contain some garbage from the dirty render setup. Get rid of that first.
twod->Clear();
twodpsp.Clear();
OpenGLRenderer::GLRenderer->CopyToBackbuffer(&bounds, false);
// strictly speaking not needed as the glReadPixels should block until the scene is rendered, but this is to safeguard against shitty drivers
glFinish();
screen->mVertexData->Reset();
int numpixels = width * height;
uint8_t* scr = (uint8_t*)M_Malloc(numpixels * 3);
screen->CopyScreenToBuffer(width, height, scr);
if (didit)
{
int numpixels = width * height;
uint8_t* scr = (uint8_t*)Xmalloc(numpixels * 3);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, scr);
M_CreatePNG(file, scr + ((height - 1) * width * 3), nullptr, SS_RGB, width, height, -width * 3, vid_gamma);
M_FinishPNG(file);
Xfree(scr);
}
DoWriteSavePic(file, SS_RGB, scr, width, height, screen->FlipSavePic());
M_Free(scr);
// Switch back the screen render buffers
screen->SetViewportRects(nullptr);
OpenGLRenderer::GLRenderer->mBuffers = OpenGLRenderer::GLRenderer->mScreenBuffers;
bool useSSAO = (gl_ssao != 0);
OpenGLRenderer::GLRenderer->mBuffers->BindSceneFB(useSSAO);
screen->SetSaveBuffers(false);
}
@ -677,7 +786,7 @@ void renderBeginScene()
if (videoGetRenderMode() < REND_POLYMOST) return;
assert(BufferLock == 0);
vp.mPalLightLevels = numshades;
vp.mPalLightLevels = numshades | (static_cast<int>(gl_fogmode) << 8) | ((int)5 << 16);
screen->mViewpoints->SetViewpoint(OpenGLRenderer::gl_RenderState, &vp);
if (BufferLock++ == 0)
@ -726,42 +835,34 @@ void DrawRateStuff()
int32_t r_scenebrightness = 0;
void Draw2D(F2DDrawer* drawer, FRenderState& state);
void videoShowFrame(int32_t w)
{
static GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
if (gl_ssao)
{
glDrawBuffers(1, buffers);
OpenGLRenderer::GLRenderer->AmbientOccludeScene(GLInterface.GetProjectionM5());
glViewport(screen->mSceneViewport.left, screen->mSceneViewport.top, screen->mSceneViewport.width, screen->mSceneViewport.height);
OpenGLRenderer::GLRenderer->mBuffers->BindSceneFB(true);
glDrawBuffers(3, buffers);
screen->AmbientOccludeScene(GLInterface.GetProjectionM5());
// To do: the translucent part of the scene should be drawn here, but the render setup in the games is really too broken to do SSAO.
// To do: the translucent part of the scene should be drawn here
glDrawBuffers(1, buffers);
//glDrawBuffers(1, buffers);
}
float Brightness = 8.f / (r_scenebrightness + 8.f);
OpenGLRenderer::GLRenderer->mBuffers->BlitSceneToTexture(); // Copy the resulting scene to the current post process texture
screen->PostProcessScene(false, 0, Brightness, []() {
GLInterface.Draw2D(&twodpsp); // draws the weapon sprites
Draw2D(&twodpsp, *screen->RenderState()); // draws the weapon sprites
});
screen->Update();
// After finishing the frame, reset everything for the next frame. This needs to be done better.
screen->BeginFrame();
if (gl_ssao)
{
OpenGLRenderer::GLRenderer->mBuffers->BindSceneFB(true);
glDrawBuffers(3, buffers);
}
else
{
OpenGLRenderer::GLRenderer->mBuffers->BindSceneFB(false);
}
bool useSSAO = (gl_ssao != 0);
screen->SetSceneRenderTarget(useSSAO);
twodpsp.Clear();
twod->Clear();
GLInterface.ResetFrame();
}

View file

@ -20,6 +20,12 @@ class F2DDrawer;
struct palette_t;
extern int xdim, ydim;
enum
{
DM_MAINVIEW,
DM_OFFSCREEN
};
class PaletteManager
{
OpenGLRenderer::FHardwareTexture* palettetextures[256] = {};
@ -54,15 +60,6 @@ enum ECullSide
Cull_Back
};
enum EDepthFunct
{
Depth_Always,
Depth_Less,
Depth_Equal,
Depth_LessEqual
};
enum EWinding
{
Winding_CCW,
@ -89,7 +86,6 @@ class GLInstance
{
public:
TArray<PolymostRenderState> rendercommands;
int maxTextureSize;
PaletteManager palmanager;
int lastPalswapIndex = -1;
OpenGLRenderer::FHardwareTexture* texv;
@ -112,7 +108,6 @@ public:
void InitGLState(int fogmode, int multisample);
void LoadPolymostShader();
void Draw2D(F2DDrawer* drawer);
void DrawImGui(ImDrawData*);
void ResetFrame();
void Deinit();
@ -246,12 +241,6 @@ public:
else renderState.StateFlags &= ~STF_DEPTHMASK;
}
void SetWireframe(bool on)
{
if (on) renderState.StateFlags |= STF_WIREFRAME;
else renderState.StateFlags &= ~STF_WIREFRAME;
}
void ClearScreen(PalEntry pe, bool depth)
{
renderState.ClearColor = pe;
@ -335,35 +324,6 @@ public:
if (shouldUpscale(tex, upscalemask)) scaleflags |= CTF_Upscale;
SetMaterial(FMaterial::ValidateTexture(tex, scaleflags), clampmode, translation, overrideshader);
}
#if 0
void BindTexture(int texunit, OpenGLRenderer::FHardwareTexture* tex, int sampler)
{
if (!tex) return;
if (texunit == 0)
{
if (tex->numChannels() == 1)
renderState.Flags |= RF_UsePalette;
else
renderState.Flags &= ~RF_UsePalette;
}
renderState.texIds[texunit] = tex->GetTextureHandle();
renderState.samplerIds[texunit] = sampler;
}
void UnbindTexture(int texunit)
{
renderState.texIds[texunit] = 0;
renderState.samplerIds[texunit] = 0;
}
void UnbindAllTextures()
{
for (int texunit = 0; texunit < MAX_TEXTURES; texunit++)
{
UnbindTexture(texunit);
}
}
#endif
void UseColorOnly(bool yes)
{
@ -371,24 +331,6 @@ public:
else renderState.Flags &= ~RF_ColorOnly;
}
void UseDetailMapping(bool yes)
{
if (yes) renderState.LayerFlags |= TEXF_Detailmap;
else renderState.LayerFlags &= ~TEXF_Detailmap;
}
void UseGlowMapping(bool yes)
{
if (yes) renderState.LayerFlags |= TEXF_Glowmap;
else renderState.LayerFlags &= ~TEXF_Glowmap;
}
void UseBrightmaps(bool yes)
{
if (yes) renderState.LayerFlags |= TEXF_Brightmap;
else renderState.LayerFlags &= ~TEXF_Brightmap;
}
void SetNpotEmulation(float factor, float xOffset)
{
renderState.NPOTEmulation.Y = factor;
@ -466,6 +408,9 @@ public:
}
bool SetTexture(int globalpicnum, FGameTexture* tex, int palette, int sampleroverride);
void RenderScene(FRenderState& state);
void DrawScene(int drawmode);
};
extern GLInstance GLInterface;

View file

@ -155,6 +155,8 @@ void GLInstance::Draw2D(F2DDrawer *drawer)
int sciY = screen->ScreenToWindowY(cmd.mScissor[3]);
int sciW = screen->ScreenToWindowX(cmd.mScissor[2]) - sciX;
int sciH = screen->ScreenToWindowY(cmd.mScissor[1]) - sciY;
if (sciX < 0) sciW += sciX, sciX = 0;
if (sciY < 0) sciH += sciY, sciY = 0;
SetScissor(sciX, sciY, sciW, sciH);
}
else
@ -221,38 +223,3 @@ void GLInstance::Draw2D(F2DDrawer *drawer)
}
static int32_t tint_blood_r = 0, tint_blood_g = 0, tint_blood_b = 0;
extern PalEntry palfadergb;
void DrawFullscreenBlends()
{
// These get prepended to the 2D drawer so they must be submitted in reverse order of drawing.
if (tint_blood_r | tint_blood_g | tint_blood_b)
{
PalEntry color2(255, std::max(-tint_blood_r, 0), std::max(-tint_blood_g, 0), std::max(-tint_blood_b, 0));
twod->AddColorOnlyQuad(0, 0, twod->GetWidth(), twod->GetHeight(), color2, &LegacyRenderStyles[STYLE_Subtract], true);
PalEntry color(255, std::max(tint_blood_r, 0), std::max(tint_blood_g, 0), std::max(tint_blood_b, 0));
twod->AddColorOnlyQuad(0, 0, twod->GetWidth(), twod->GetHeight(), color, &LegacyRenderStyles[STYLE_Add], true);
}
if (palfadergb.a > 0)
{
twod->AddColorOnlyQuad(0, 0, twod->GetWidth(), twod->GetHeight(), palfadergb, &LegacyRenderStyles[STYLE_Translucent], true);
}
}
void DrawRateStuff();
void Draw2D(F2DDrawer* drawer, FRenderState& state)
{
::DrawFullscreenBlends();
DrawRateStuff();
GLInterface.Draw2D(twod);
}
void videoTintBlood(int32_t r, int32_t g, int32_t b)
{
tint_blood_r = r;
tint_blood_g = g;
tint_blood_b = b;
}

View file

@ -40,7 +40,6 @@ enum PRSFlags
STF_STENCILTEST = 64,
STF_CULLCW = 128,
STF_CULLCCW = 256,
STF_WIREFRAME = 512,
STF_CLEARCOLOR = 1024,
STF_CLEARDEPTH = 2048,
STF_VIEWPORTSET = 4096,
@ -54,7 +53,6 @@ struct PolymostRenderState
float ShadeDiv = 62.f;
float VisFactor = 128.f;
int Flags = 0;
int LayerFlags = 0;
FVector2 NPOTEmulation = { 0.f, 0.f };
float AlphaThreshold = 0.5f;
bool AlphaTest = true;
@ -75,6 +73,7 @@ struct PolymostRenderState
PalEntry FogColor;
void ApplyMaterial(FMaterial* mat, int clampmode, int translation, int overrideshader);
void ApplyMaterial(FMaterial* mat, int clampmode, int translation, int overrideshader, PolymostShader *shader);
void Apply(PolymostShader *shader, GLState &oldstate);
void Apply(FRenderState & state, GLState& oldState);
};

View file

@ -2168,9 +2168,6 @@ drawscreen(PLAYERp pp)
renderSetAspect(Blrintf(float(viewingrange) * tanf(r_fov * (fPI/360.f))), yxaspect);
if (FAF_DebugView)
videoClearViewableArea(255);
if (dimensionmode != 6)// && !ScreenSavePic)
{
// Cameras must be done before the main loop.

View file

@ -314,7 +314,7 @@ float R_DoomLightingEquation(float light)
// This is a lot more primitive than Doom's lighting...
float numShades = float(uPalLightLevels & 255);
float curshade = (1.0 - light) * (numShades - 1.0);
float visibility = max(uGlobVis * uLightFactor * z, 0.0);
float visibility = max(uGlobVis * uLightFactor * abs(z), 0.0);
float shade = clamp((curshade + visibility), 0.0, numShades - 1.0);
return clamp(shade * uLightDist, 0.0, 1.0);
}