- added the code for legacy shaders.

- force texture filtering for 2D to off when in software rendering.
This commit is contained in:
Christoph Oelckers 2018-04-08 12:11:51 +02:00
parent 5eb898107f
commit b12a6fded9
14 changed files with 288 additions and 27 deletions

View file

@ -1043,6 +1043,7 @@ set (PCH_SOURCES
g_statusbar/sbar_mugshot.cpp
g_statusbar/shared_sbar.cpp
gl/compatibility/gl_20.cpp
gl/compatibility/gl_swshader20.cpp
gl/data/gl_vertexbuffer.cpp
gl/dynlights/gl_lightbuffer.cpp
gl/dynlights/gl_shadowmap.cpp

View file

@ -2637,7 +2637,7 @@ void D_DoomMain (void)
}
V_Init2();
gl_PatchMenu();
gl_PatchMenu(); // removes unapplicable entries for old hardware. This cannot be done in MENUDEF because at the point it gets parsed it doesn't have the needed info.
UpdateJoystickMenu(NULL);
v = Args->CheckValue ("-loadgame");

View file

@ -52,7 +52,6 @@
CVAR(Bool, gl_lights_additive, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Bool, gl_legacy_mode, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET)
//==========================================================================
//
@ -64,7 +63,7 @@ CVAR(Bool, gl_legacy_mode, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET)
void gl_PatchMenu()
{
// Radial fog and Doom lighting are not available without full shader support.
if (!gl_legacy_mode) return;
if (!gl.legacyMode) return;
FOptionValues **opt = OptionValues.CheckKey("LightingModes");
if (opt != NULL)

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/
//
//--------------------------------------------------------------------------
//
/*
** gl_swshader20.cpp
**
** Implements the shaders used to render the software renderer's
** 3D output to the screen,
**
*/
#include "gl/system/gl_system.h"
#include "tarray.h"
#include "doomtype.h"
#include "zstring.h"
#include "i_system.h"
#include "r_utility.h"
#include "w_wad.h"
#include "gl/dynlights/gl_dynlight.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/system/gl_interface.h"
#include "gl/renderer/gl_renderstate.h"
class LegacyShader
{
public:
~LegacyShader()
{
if (Program != 0) glDeleteProgram(Program);
if (VertexShader != 0) glDeleteShader(VertexShader);
if (FragmentShader != 0) glDeleteShader(FragmentShader);
}
int Program = 0;
int VertexShader = 0;
int FragmentShader = 0;
int ConstantLocations[2];
int ImageLocation = -1;
int PaletteLocation = -1;
};
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
LegacyShaderContainer::LegacyShaderContainer()
{
if (!LoadShaders())
{
Printf("Unable to compile shaders for software rendering\n");
}
}
LegacyShaderContainer::~LegacyShaderContainer()
{
for (auto p : Shaders) if (p) delete p;
}
LegacyShader* LegacyShaderContainer::CreatePixelShader(const FString& vertexsrc, const FString& fragmentsrc, const FString &defines)
{
auto shader = new LegacyShader();
char buffer[10000];
shader->Program = glCreateProgram();
if (shader->Program == 0) { Printf("glCreateProgram failed. Disabling OpenGL hardware acceleration.\n"); return nullptr; }
shader->VertexShader = glCreateShader(GL_VERTEX_SHADER);
if (shader->VertexShader == 0) { Printf("glCreateShader(GL_VERTEX_SHADER) failed. Disabling OpenGL hardware acceleration.\n"); return nullptr; }
shader->FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
if (shader->FragmentShader == 0) { Printf("glCreateShader(GL_FRAGMENT_SHADER) failed. Disabling OpenGL hardware acceleration.\n"); return nullptr; }
{
int lengths[1] = { (int)vertexsrc.Len() };
const char *sources[1] = { vertexsrc.GetChars() };
glShaderSource(shader->VertexShader, 1, sources, lengths);
glCompileShader(shader->VertexShader);
}
{
int lengths[1] = { (int)fragmentsrc.Len() };
const char *sources[1] = { fragmentsrc.GetChars() };
glShaderSource(shader->FragmentShader, 1, sources, lengths);
glCompileShader(shader->FragmentShader);
}
GLint status = 0;
int errorShader = shader->VertexShader;
glGetShaderiv(shader->VertexShader, GL_COMPILE_STATUS, &status);
if (status != GL_FALSE)
{
errorShader = shader->FragmentShader;
glGetShaderiv(shader->FragmentShader, GL_COMPILE_STATUS, &status);
}
if (status == GL_FALSE)
{
GLsizei length = 0;
buffer[0] = 0;
glGetShaderInfoLog(errorShader, 10000, &length, buffer);
Printf("Shader compile failed: %s", buffer);
delete shader;
return nullptr;
}
glAttachShader(shader->Program, shader->VertexShader);
glAttachShader(shader->Program, shader->FragmentShader);
glLinkProgram(shader->Program);
glGetProgramiv(shader->Program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
GLsizei length = 0;
buffer[0] = 0;
glGetProgramInfoLog(shader->Program, 10000, &length, buffer);
Printf("Shader link failed: %s", buffer);
delete shader;
return nullptr;
}
shader->ConstantLocations[0] = glGetUniformLocation(shader->Program, "uColor1");
shader->ConstantLocations[1] = glGetUniformLocation(shader->Program, "uColor2");
shader->ImageLocation = glGetUniformLocation(shader->Program, "Image");
shader->PaletteLocation = glGetUniformLocation(shader->Program, "Palette");
return shader;
}
//==========================================================================
//
// SWSceneDrawer :: LoadShaders
//
// Returns true if all required shaders were loaded. (Gamma and burn wipe
// are the only ones not considered "required".)
//
//==========================================================================
static const char * const ShaderDefines[] = {
"#define PAL_TEX\n",
"#define PAL_TEX\n#define SPECIALCM\n",
"",
"#define SPECIALCM\n",
};
bool LegacyShaderContainer::LoadShaders()
{
int lumpvert = Wads.CheckNumForFullName("shaders/swgl/swshadergl2.vp");
int lumpfrag = Wads.CheckNumForFullName("shaders/swgl/swshadergl2.fp");
if (lumpvert < 0 || lumpfrag < 0)
return false;
FString vertsource = Wads.ReadLump(lumpvert).GetString();
FString fragsource = Wads.ReadLump(lumpfrag).GetString();
FString shaderdir, shaderpath;
unsigned int i;
for (i = 0; i < NUM_SHADERS; ++i)
{
shaderpath = shaderdir;
Shaders[i] = CreatePixelShader(vertsource, fragsource, ShaderDefines[i]);
if (!Shaders[i])
{
break;
}
glUseProgram(Shaders[i]->Program);
if (Shaders[i]->ImageLocation != -1) glUniform1i(Shaders[i]->ImageLocation, 0);
if (Shaders[i]->PaletteLocation != -1) glUniform1i(Shaders[i]->PaletteLocation, 1);
glUseProgram(0);
}
if (i == NUM_SHADERS)
{ // Success!
return true;
}
// Failure. Release whatever managed to load (which is probably nothing.)
for (i = 0; i < NUM_SHADERS; ++i)
{
if (Shaders[i]) delete Shaders[i];
}
return false;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void LegacyShaderContainer::BindShader(int num, const float *p1, const float *p2)
{
if (num >= 0 && num < 4)
{
auto shader = Shaders[num];
glUseProgram(shader->Program);
glUniform4fv(shader->ConstantLocations[0], 1, p1);
glUniform4fv(shader->ConstantLocations[1], 1, p2);
}
}

View file

@ -163,6 +163,11 @@ void FGLRenderer::Initialize(int width, int height)
mShadowMapShader = new FShadowMapShader();
mCustomPostProcessShaders = new FCustomPostProcessShaders();
if (gl.legacyMode)
{
legacyShaders = new LegacyShaderContainer;
}
GetSpecialTextures();
// needed for the core profile, because someone decided it was a good idea to remove the default VAO.
@ -197,6 +202,7 @@ FGLRenderer::~FGLRenderer()
gl_FlushModels();
AActor::DeleteAllAttachedLights();
FMaterial::FlushAll();
if (legacyShaders) delete legacyShaders;
if (mShaderManager != NULL) delete mShaderManager;
if (mSamplerManager != NULL) delete mSamplerManager;
if (mVBO != NULL) delete mVBO;
@ -830,6 +836,12 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer)
auto mat = FMaterial::ValidateTexture(cmd.mTexture, false);
if (mat == nullptr) continue;
// This requires very special handling
if (gl.legacyMode && cmd.mTexture->UseType == ETextureType::SWCanvas)
{
gl_RenderState.SetTextureMode(TM_SWCANVAS);
}
if (gltrans == -1 && cmd.mTranslation != nullptr) gltrans = cmd.mTranslation->GetUniqueIndex();
gl_RenderState.SetMaterial(mat, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : CLAMP_XY_NOMIP, -gltrans, -1, cmd.mDrawMode == F2DDrawer::DTM_AlphaTexture);
gl_RenderState.EnableTexture(true);

View file

@ -89,6 +89,29 @@ enum
DM_SKYPORTAL
};
// Helper baggage to draw the paletted software renderer output on old hardware.
// This must be here because the 2D drawer needs to access it, not the scene drawer.
class LegacyShader;
struct LegacyShaderContainer
{
enum
{
NUM_SHADERS = 4
};
LegacyShader *Shaders[NUM_SHADERS];
LegacyShader* CreatePixelShader(const FString& vertexsrc, const FString& fragmentsrc, const FString &defines);
LegacyShaderContainer();
~LegacyShaderContainer();
bool LoadShaders();
void BindShader(int num, const float *p1, const float *p2);
};
class FGLRenderer
{
public:
@ -148,6 +171,7 @@ public:
FSkyVertexBuffer *mSkyVBO;
FLightBuffer *mLights;
SWSceneDrawer *swdrawer = nullptr;
LegacyShaderContainer *legacyShaders = nullptr;
GL_IRECT mScreenViewport;
GL_IRECT mSceneViewport;

View file

@ -80,7 +80,6 @@ CVAR(Bool, gl_sort_textures, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
EXTERN_CVAR (Bool, cl_capfps)
EXTERN_CVAR (Bool, r_deathcamera)
EXTERN_CVAR (Float, r_visibility)
EXTERN_CVAR (Bool, gl_legacy_mode)
EXTERN_CVAR (Bool, r_drawvoxels)
//-----------------------------------------------------------------------------

View file

@ -44,6 +44,7 @@
#include "gl/renderer/gl_renderstate.h"
#include "gl/renderer/gl_lightdata.h"
#include "gl/textures/gl_hwtexture.h"
#include "gl/textures/gl_samplers.h"
#include "gl/utility/gl_clock.h"
#include "gl/data/gl_vertexbuffer.h"
#include "gl_debug.h"
@ -391,6 +392,11 @@ void OpenGLFrameBuffer::CleanForRestart()
GLRenderer->ResetSWScene();
}
void OpenGLFrameBuffer::SetTextureFilterMode()
{
if (GLRenderer != nullptr && GLRenderer->mSamplerManager != nullptr) GLRenderer->mSamplerManager->SetTextureFilterMode();
}
void OpenGLFrameBuffer::UpdatePalette()
{
if (GLRenderer)

View file

@ -53,6 +53,7 @@ public:
void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV) override;
void WriteSavePic(player_t *player, FileWriter *file, int width, int height) override;
void RenderView(player_t *player) override;
void SetTextureFilterMode() override;
// Retrieves a buffer containing image data for a screenshot.
// Hint: Pitch can be negative for upside-down images, in which case buffer

View file

@ -43,9 +43,6 @@ static TArray<FString> m_Extensions;
RenderContext gl;
static double realglversion; // this is public so the statistics code can access it.
EXTERN_CVAR(Bool, gl_legacy_mode)
CVAR(Bool, gl_riskymodernpath, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
//==========================================================================
//
//
@ -322,7 +319,6 @@ void gl_LoadExtensions()
UCVarValue value;
value.Bool = gl.legacyMode;
gl_legacy_mode.ForceSet (value, CVAR_Bool);
}
//==========================================================================

View file

@ -29,6 +29,7 @@ enum RenderFlags
enum TexMode
{
TM_SWCANVAS = -1, // special case for the legacy renderer, do not use for anything but the SW renderer's canvas.
TM_MODULATE = 0, // (r, g, b, a)
TM_MASK, // (1, 1, 1, a)
TM_OPAQUE, // (r, g, b, 1)

View file

@ -94,6 +94,7 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval)
}
else
{
int filter = V_IsHardwareRenderer() ? gl_texture_filter : 0;
glActiveTexture(GL_TEXTURE0 + texunit);
switch (num)
{
@ -102,8 +103,8 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
if (lastval >= CLAMP_XY_NOMIP)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic);
}
break;
@ -113,8 +114,8 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
if (lastval >= CLAMP_XY_NOMIP)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic);
}
break;
@ -124,8 +125,8 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (lastval >= CLAMP_XY_NOMIP)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic);
}
break;
@ -135,8 +136,8 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (lastval >= CLAMP_XY_NOMIP)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic);
}
break;
@ -144,8 +145,8 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval)
case CLAMP_XY_NOMIP:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
break;
@ -160,8 +161,8 @@ uint8_t FSamplerManager::Bind(int texunit, int num, int lastval)
case CLAMP_CAMTEX:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
break;
}
@ -176,17 +177,18 @@ void FSamplerManager::SetTextureFilterMode()
if (gl.flags & RFL_SAMPLER_OBJECTS)
{
UnbindAll();
int filter = V_IsHardwareRenderer() ? gl_texture_filter : 0;
for (int i = 0; i < 4; i++)
{
glSamplerParameteri(mSamplers[i], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter);
glSamplerParameteri(mSamplers[i], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter);
glSamplerParameteri(mSamplers[i], GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter);
glSamplerParameteri(mSamplers[i], GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
glSamplerParameterf(mSamplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic);
}
glSamplerParameteri(mSamplers[4], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter);
glSamplerParameteri(mSamplers[4], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter);
glSamplerParameteri(mSamplers[6], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter);
glSamplerParameteri(mSamplers[6], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter);
glSamplerParameteri(mSamplers[4], GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter);
glSamplerParameteri(mSamplers[4], GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
glSamplerParameteri(mSamplers[6], GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter);
glSamplerParameteri(mSamplers[6], GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter);
}
else
{

View file

@ -111,6 +111,8 @@ CUSTOM_CVAR(Int, vid_rendermode, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOIN
// [SP] Update pitch limits to the netgame/gamesim.
players[consoleplayer].SendPitchLimits();
}
screen->SetTextureFilterMode();
// No further checks needed. All this changes now is which scene drawer the render backend calls.
}

View file

@ -357,6 +357,7 @@ public:
// Delete any resources that need to be deleted after restarting with a different IWAD
virtual void CleanForRestart() {}
virtual void SetTextureFilterMode() {}
// Begin 2D drawing operations.
// Returns true if hardware-accelerated 2D has been entered, false if not.
@ -366,7 +367,6 @@ public:
// Returns true if Begin2D has been called and 2D drawing is now active
bool HasBegun2D() { return isIn2D; }
// DrawTexture calls after Begin2D use native textures.
// Report a game restart
virtual void GameRestart();