Add glsl shader version of the d3d9 shaders and get enough of it working for it to boot without errors

This commit is contained in:
Magnus Norddahl 2016-10-10 21:03:55 +02:00
parent 40df46f94e
commit f4308b3184
6 changed files with 435 additions and 454 deletions

View File

@ -71,7 +71,6 @@
#include "gl/utility/gl_templates.h"
#include "gl/gl_functions.h"
CVAR(Bool, gl_antilag, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Int, gl_showpacks, 0, 0)
#ifndef WIN32 // Defined in fb_d3d9 for Windows
CVAR(Bool, vid_hwaalines, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@ -88,63 +87,66 @@ EXTERN_CVAR(Int, vid_refreshrate)
extern cycle_t BlitCycles;
void gl_LoadExtensions();
IMPLEMENT_CLASS(OpenGLSWFrameBuffer)
const char *const OpenGLSWFrameBuffer::ShaderNames[OpenGLSWFrameBuffer::NUM_SHADERS] =
const char *const OpenGLSWFrameBuffer::ShaderDefines[OpenGLSWFrameBuffer::NUM_SHADERS] =
{
"NormalColor",
"NormalColorPal",
"NormalColorInv",
"NormalColorPalInv",
"#define ENORMALCOLOR\n#define PALTEX 0\n#define DINVERT 0", // NormalColor
"#define ENORMALCOLOR\n#define PALTEX 1\n#define INVERT 0", // NormalColorPal
"#define ENORMALCOLOR\n#define PALTEX 0\n#define INVERT 1", // NormalColorInv
"#define ENORMALCOLOR\n#define PALTEX 1\n#define INVERT 1", // NormalColorPalInv
"RedToAlpha",
"RedToAlphaInv",
"#define EREDTOALPHA\n#define INVERT 0", // RedToAlpha
"#define EREDTOALPHA\n#define INVERT 1", // RedToAlphaInv
"VertexColor",
"#define EVERTEXCOLOR", // VertexColor
"SpecialColormap",
"SpecialColorMapPal",
"#define ESPECIALCOLORMAP\n#define PALTEX 0\n#define INVERT 0", // SpecialColormap
"#define ESPECIALCOLORMAP\n#define PALTEX 1\n#define INVERT 0", // SpecialColorMapPal
"InGameColormap",
"InGameColormapDesat",
"InGameColormapInv",
"InGameColormapInvDesat",
"InGameColormapPal",
"InGameColormapPalDesat",
"InGameColormapPalInv",
"InGameColormapPalInvDesat",
"#define EINGAMECOLORMAP\n#define PALTEX 0\n#define INVERT 0\n#define DESAT 0", // InGameColormap
"#define EINGAMECOLORMAP\n#define PALTEX 0\n#define INVERT 0\n#define DESAT 1", // InGameColormapDesat
"#define EINGAMECOLORMAP\n#define PALTEX 0\n#define INVERT 1\n#define DESAT 0", // InGameColormapInv
"#define EINGAMECOLORMAP\n#define PALTEX 0\n#define INVERT 1\n#define DESAT 1", // InGameColormapInvDesat
"#define EINGAMECOLORMAP\n#define PALTEX 1\n#define INVERT 0\n#define DESAT 0", // InGameColormapPal
"#define EINGAMECOLORMAP\n#define PALTEX 1\n#define INVERT 0\n#define DESAT 1", // InGameColormapPalDesat
"#define EINGAMECOLORMAP\n#define PALTEX 1\n#define INVERT 1\n#define DESAT 0", // InGameColormapPalInv
"#define EINGAMECOLORMAP\n#define PALTEX 1\n#define INVERT 1\n#define DESAT 1", // InGameColormapPalInvDesat
"BurnWipe",
"GammaCorrection",
"#define EBURNWIPE", // BurnWipe
"#define EGAMMACORRECTION", // GammaCorrection
};
OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen) :
Super(hMonitor, width, height, bits, refreshHz, fullscreen)
{
// To do: this needs to cooperate with the same static in OpenGLFrameBuffer::InitializeState
static bool first = true;
if (first)
{
ogl_LoadFunctions();
}
gl_LoadExtensions();
Super::InitializeState();
// SetVSync needs to be at the very top to workaround a bug in Nvidia's OpenGL driver.
// If wglSwapIntervalEXT is called after glBindFramebuffer in a frame the setting is not changed!
SetVSync(vid_vsync);
//SetVSync(vid_vsync);
VertexBuffer = nullptr;
IndexBuffer = nullptr;
FBTexture = nullptr;
TempRenderTexture = nullptr;
RenderTexture[0] = nullptr;
RenderTexture[1] = nullptr;
InitialWipeScreen = nullptr;
ScreenshotTexture = nullptr;
ScreenshotSurface = nullptr;
FinalWipeScreen = nullptr;
PaletteTexture = nullptr;
GammaTexture = nullptr;
FrontCopySurface = nullptr;
for (int i = 0; i < NUM_SHADERS; ++i)
{
Shaders[i] = nullptr;
}
GammaShader = nullptr;
BlockSurface[0] = nullptr;
BlockSurface[1] = nullptr;
VSync = vid_vsync;
BlendingRect.left = 0;
BlendingRect.top = 0;
@ -160,9 +162,6 @@ OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height,
QuadExtra = new BufferedTris[MAX_QUAD_BATCH];
Atlases = nullptr;
PixelDoubling = 0;
SkipAt = -1;
CurrRenderTexture = 0;
RenderTextureToggle = 0;
Gamma = 1.0;
FlashColor0 = 0;
@ -180,7 +179,7 @@ OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height,
memcpy(SourcePalette, GPalette.BaseColors, sizeof(PalEntry) * 256);
Windowed = !(static_cast<Win32Video *>(Video)->GoFullscreen(fullscreen));
//Windowed = !(static_cast<Win32Video *>(Video)->GoFullscreen(fullscreen));
TrueHeight = height;
/*if (fullscreen)
@ -209,7 +208,56 @@ OpenGLSWFrameBuffer::~OpenGLSWFrameBuffer()
delete[] QuadExtra;
}
bool OpenGLSWFrameBuffer::CreatePixelShader(const void *vertexsrc, const void *fragmentsrc, HWPixelShader **outShader)
OpenGLSWFrameBuffer::HWTexture::~HWTexture()
{
if (Texture != 0) glDeleteTextures(1, (GLuint*)&Texture);
if (Buffer != 0) glDeleteBuffers(1, (GLuint*)&Buffer);
}
OpenGLSWFrameBuffer::HWVertexBuffer::~HWVertexBuffer()
{
if (VertexArray != 0) glDeleteVertexArrays(1, (GLuint*)&VertexArray);
if (Buffer != 0) glDeleteBuffers(1, (GLuint*)&Buffer);
}
OpenGLSWFrameBuffer::FBVERTEX *OpenGLSWFrameBuffer::HWVertexBuffer::Lock()
{
glBindBuffer(GL_ARRAY_BUFFER, Buffer);
return (FBVERTEX*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
}
void OpenGLSWFrameBuffer::HWVertexBuffer::Unlock()
{
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
OpenGLSWFrameBuffer::HWIndexBuffer::~HWIndexBuffer()
{
if (Buffer != 0) glDeleteBuffers(1, (GLuint*)&Buffer);
}
uint16_t *OpenGLSWFrameBuffer::HWIndexBuffer::Lock()
{
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &LockedOldBinding);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Buffer);
return (uint16_t*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
}
void OpenGLSWFrameBuffer::HWIndexBuffer::Unlock()
{
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, LockedOldBinding);
}
OpenGLSWFrameBuffer::HWPixelShader::~HWPixelShader()
{
if (Program != 0) glDeleteProgram(Program);
if (VertexShader != 0) glDeleteShader(VertexShader);
if (FragmentShader != 0) glDeleteShader(FragmentShader);
}
bool OpenGLSWFrameBuffer::CreatePixelShader(FString vertexsrc, FString fragmentsrc, const FString &defines, HWPixelShader **outShader)
{
auto shader = std::make_unique<HWPixelShader>();
@ -217,25 +265,34 @@ bool OpenGLSWFrameBuffer::CreatePixelShader(const void *vertexsrc, const void *f
shader->VertexShader = glCreateShader(GL_VERTEX_SHADER);
shader->FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
vertexsrc = "#version 130\n" + defines + "\n#line 0\n" + vertexsrc;
fragmentsrc = "#version 130\n" + defines + "\n#line 0\n" + fragmentsrc;
{
int lengths[1] = { (int)strlen((const char*)vertexsrc) };
const char *sources[1] = { (const char*)vertexsrc };
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)strlen((const char*)fragmentsrc) };
const char *sources[1] = { (const char*)fragmentsrc };
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) glGetShaderiv(shader->FragmentShader, GL_COMPILE_STATUS, &status);
if (status != GL_FALSE) { errorShader = shader->FragmentShader; glGetShaderiv(shader->FragmentShader, GL_COMPILE_STATUS, &status); }
if (status == GL_FALSE)
{
static char buffer[10000];
GLsizei length = 0;
buffer[0] = 0;
glGetShaderInfoLog(errorShader, 10000, &length, buffer);
*outShader = nullptr;
return false;
}
@ -308,6 +365,8 @@ bool OpenGLSWFrameBuffer::CreateTexture(int width, int height, int levels, int f
{
auto obj = std::make_unique<HWTexture>();
obj->Format = format;
GLint oldBinding = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
@ -317,7 +376,7 @@ bool OpenGLSWFrameBuffer::CreateTexture(int width, int height, int levels, int f
switch (format)
{
case GL_R8: srcformat = GL_RED; break;
case GL_RGBA8: srcformat = GL_RGBA; break;
case GL_RGBA8: srcformat = GL_BGRA; break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: srcformat = GL_RGB; break;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: srcformat = GL_RGBA; break;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: srcformat = GL_RGBA; break;
@ -327,6 +386,8 @@ bool OpenGLSWFrameBuffer::CreateTexture(int width, int height, int levels, int f
return false;
}
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, srcformat, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, oldBinding);
@ -334,16 +395,9 @@ bool OpenGLSWFrameBuffer::CreateTexture(int width, int height, int levels, int f
return true;
}
bool OpenGLSWFrameBuffer::CreateOffscreenPlainSurface(int width, int height, int format, HWSurface **outSurface) { *outSurface = nullptr; return false; }
bool OpenGLSWFrameBuffer::CreateRenderTarget(int width, int height, int format, HWSurface **outSurface) { *outSurface = nullptr; return false; }
bool OpenGLSWFrameBuffer::GetBackBuffer(HWSurface **outSurface) { *outSurface = nullptr; return false; }
bool OpenGLSWFrameBuffer::GetRenderTarget(int index, HWSurface **outSurface) { *outSurface = nullptr; return false; }
void OpenGLSWFrameBuffer::GetRenderTargetData(HWSurface *a, HWSurface *b) { }
void OpenGLSWFrameBuffer::ColorFill(HWSurface *surface, float red, float green, float blue) { }
void OpenGLSWFrameBuffer::StretchRect(HWSurface *src, const LTRBRect *srcrect, HWSurface *dest) { }
bool OpenGLSWFrameBuffer::SetRenderTarget(int index, HWSurface *surface) { return true; }
void OpenGLSWFrameBuffer::SetGammaRamp(const GammaRamp *ramp) { }
void OpenGLSWFrameBuffer::SetGammaRamp(const GammaRamp *ramp)
{
}
void OpenGLSWFrameBuffer::SetPixelShaderConstantF(int uniformIndex, const float *data, int vec4fcount)
{
@ -487,7 +541,6 @@ void OpenGLSWFrameBuffer::SetInitialState()
NeedGammaUpdate = true;
NeedPalUpdate = true;
OldRenderTarget = nullptr;
// This constant is used for grayscaling weights (.xyz) and color inversion (.w)
float weights[4] = { 77 / 256.f, 143 / 256.f, 37 / 256.f, 1 };
@ -524,7 +577,6 @@ bool OpenGLSWFrameBuffer::CreateResources()
{
return false;
}
CreateBlockSurfaces();
return true;
}
@ -539,42 +591,36 @@ bool OpenGLSWFrameBuffer::CreateResources()
bool OpenGLSWFrameBuffer::LoadShaders()
{
static const char models[][4] = { "30/", "20/", "14/" };
int lumpvert = Wads.CheckNumForFullName("shaders/glsl/swshader.vp");
int lumpfrag = Wads.CheckNumForFullName("shaders/glsl/swshader.fp");
if (lumpvert < 0 || lumpfrag < 0)
return false;
FString vertsource = Wads.ReadLump(lumpvert).GetString();
FString fragsource = Wads.ReadLump(lumpfrag).GetString();
FString shaderdir, shaderpath;
unsigned model, i;
int lump, lumpvert;
unsigned int i;
// We determine the best available model simply by trying them all in
// order of decreasing preference.
for (model = 0; model < countof(models); ++model)
for (i = 0; i < NUM_SHADERS; ++i)
{
shaderdir = "shaders/gl/sm";
shaderdir += models[model];
for (i = 0; i < NUM_SHADERS; ++i)
shaderpath = shaderdir;
if (!CreatePixelShader(vertsource, fragsource, ShaderDefines[i], &Shaders[i]) && i < SHADER_BurnWipe)
{
shaderpath = shaderdir;
lump = Wads.CheckNumForFullName(shaderpath + ShaderNames[i] + ".fp");
lumpvert = Wads.CheckNumForFullName(shaderpath + ShaderNames[i] + ".vp");
if (lump >= 0 && lumpvert >= 0)
{
FMemLump data = Wads.ReadLump(lump);
FMemLump datavert = Wads.ReadLump(lumpvert);
if (!CreatePixelShader(datavert.GetMem(), data.GetMem(), &Shaders[i]) && i < SHADER_BurnWipe)
{
break;
}
}
}
if (i == NUM_SHADERS)
{ // Success!
return true;
}
// Failure. Release whatever managed to load (which is probably nothing.)
for (i = 0; i < NUM_SHADERS; ++i)
{
SafeRelease(Shaders[i]);
break;
}
}
if (i == NUM_SHADERS)
{ // Success!
return true;
}
// Failure. Release whatever managed to load (which is probably nothing.)
for (i = 0; i < NUM_SHADERS; ++i)
{
SafeRelease(Shaders[i]);
}
return false;
}
@ -590,7 +636,6 @@ void OpenGLSWFrameBuffer::ReleaseResources()
KillNativeTexs();
KillNativePals();
ReleaseDefaultPoolItems();
SafeRelease(ScreenshotSurface);
SafeRelease(ScreenshotTexture);
SafeRelease(PaletteTexture);
for (int i = 0; i < NUM_SHADERS; ++i)
@ -616,14 +661,9 @@ void OpenGLSWFrameBuffer::ReleaseDefaultPoolItems()
{
SafeRelease(FBTexture);
SafeRelease(FinalWipeScreen);
SafeRelease(RenderTexture[0]);
SafeRelease(RenderTexture[1]);
SafeRelease(InitialWipeScreen);
SafeRelease(VertexBuffer);
SafeRelease(IndexBuffer);
SafeRelease(BlockSurface[0]);
SafeRelease(BlockSurface[1]);
SafeRelease(FrontCopySurface);
}
bool OpenGLSWFrameBuffer::Reset()
@ -633,32 +673,10 @@ bool OpenGLSWFrameBuffer::Reset()
{
return false;
}
CreateBlockSurfaces();
SetInitialState();
return true;
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: CreateBlockSurfaces
//
// Create blocking surfaces for antilag. It's okay if these can't be
// created; antilag just won't work.
//
//==========================================================================
void OpenGLSWFrameBuffer::CreateBlockSurfaces()
{
BlockNum = 0;
if (CreateOffscreenPlainSurface(16, 16, GL_RGBA8, &BlockSurface[0]))
{
if (!CreateOffscreenPlainSurface(16, 16, GL_RGBA8, &BlockSurface[1]))
{
SafeRelease(BlockSurface[0]);
}
}
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: KillNativePals
@ -691,80 +709,11 @@ void OpenGLSWFrameBuffer::KillNativeTexs()
}
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: CreateFBTexture
//
// Creates the "Framebuffer" texture. With the advent of hardware-assisted
// 2D, this is something of a misnomer now. The FBTexture is only used for
// uploading the software 3D image to video memory so that it can be drawn
// to the real frame buffer.
//
// It also creates the TempRenderTexture, since this seemed like a
// convenient place to do so.
//
//==========================================================================
bool OpenGLSWFrameBuffer::CreateFBTexture()
{
if (!CreateTexture(Width, Height, 1, GL_R8, &FBTexture))
{
int pow2width, pow2height, i;
for (i = 1; i < Width; i <<= 1) {} pow2width = i;
for (i = 1; i < Height; i <<= 1) {} pow2height = i;
if (!CreateTexture(pow2width, pow2height, 1, GL_R8, &FBTexture))
{
return false;
}
else
{
FBWidth = pow2width;
FBHeight = pow2height;
}
}
else
{
FBWidth = Width;
FBHeight = Height;
}
RenderTextureToggle = 0;
RenderTexture[0] = nullptr;
RenderTexture[1] = nullptr;
if (!CreateTexture(FBWidth, FBHeight, 1, GL_RGBA8, &RenderTexture[0]))
{
return false;
}
if (Windowed || PixelDoubling)
{
// Windowed or pixel doubling: Create another render texture so we can flip between them.
RenderTextureToggle = 1;
if (!CreateTexture(FBWidth, FBHeight, 1, GL_RGBA8, &RenderTexture[1]))
{
return false;
}
}
else
{
// Fullscreen and not pixel doubling: Create a render target to have the back buffer copied to.
if (!CreateRenderTarget(Width, Height, GL_RGBA8, &FrontCopySurface))
{
return false;
}
}
// Initialize the TempRenderTextures to black.
for (int i = 0; i <= RenderTextureToggle; ++i)
{
HWSurface *surf;
if (RenderTexture[i]->GetSurfaceLevel(0, &surf))
{
ColorFill(surf, 0.0f, 0.0f, 0.0f);
delete surf;
}
}
TempRenderTexture = RenderTexture[0];
CurrRenderTexture = 0;
CreateTexture(Width, Height, 1, GL_R8, &FBTexture);
FBWidth = Width;
FBHeight = Height;
return true;
}
@ -814,7 +763,7 @@ bool OpenGLSWFrameBuffer::CreateVertexes()
void OpenGLSWFrameBuffer::CalcFullscreenCoords(FBVERTEX verts[4], bool viewarea_only, bool can_double, uint32_t color0, uint32_t color1) const
{
float offset = OldRenderTarget != nullptr ? 0 : LBOffset;
float offset = LBOffset;//OldRenderTarget != nullptr ? 0 : LBOffset;
float top = offset - 0.5f;
float texright = float(Width) / float(FBWidth);
float texbot = float(Height) / float(FBHeight);
@ -1042,18 +991,6 @@ void OpenGLSWFrameBuffer::Update()
LOG("SetGammaRamp\n");
SetGammaRamp(&ramp);
}
else
{
if (igamma != 1)
{
UpdateGammaTexture(igamma);
GammaShader = Shaders[SHADER_GammaCorrection];
}
else
{
GammaShader = nullptr;
}
}
psgamma[2] = psgamma[1] = psgamma[0] = igamma;
psgamma[3] = 0.5; // For SM14 version
SetPixelShaderConstantF(PSCONST_Gamma, psgamma, 1);
@ -1094,21 +1031,6 @@ void OpenGLSWFrameBuffer::Flip()
DrawLetterbox();
DoWindowedGamma();
CopyNextFrontBuffer();
// Attempt to counter input lag.
if (gl_antilag && BlockSurface[0] != nullptr)
{
LockedRect lr;
volatile int dummy;
ColorFill(BlockSurface[BlockNum], 0.0f, 0x20/255.0f, 0x50/255.0f);
BlockNum ^= 1;
if (BlockSurface[BlockNum]->LockRect(&lr, nullptr, false))
{
dummy = *(int *)lr.pBits;
BlockSurface[BlockNum]->UnlockRect();
}
}
// Limiting the frame rate is as simple as waiting for the timer to signal this event.
if (FPSLimitEvent != nullptr)
{
@ -1117,13 +1039,6 @@ void OpenGLSWFrameBuffer::Flip()
Present();
InScene = false;
if (RenderTextureToggle)
{
// Flip the TempRenderTexture to the other one now.
CurrRenderTexture ^= RenderTextureToggle;
TempRenderTexture = RenderTexture[CurrRenderTexture];
}
if (Windowed)
{
int clientWidth = GetClientWidth();
@ -1143,42 +1058,6 @@ void OpenGLSWFrameBuffer::Flip()
}
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: CopyNextFrontBuffer
//
// Duplicates the contents of the back buffer that will become the front
// buffer upon Present into FrontCopySurface so that we can get the
// contents of the display without wasting time in GetFrontBufferData().
//
//==========================================================================
void OpenGLSWFrameBuffer::CopyNextFrontBuffer()
{
HWSurface *backbuff;
if (Windowed || PixelDoubling)
{
// Windowed mode or pixel doubling: TempRenderTexture has what we want
SafeRelease(FrontCopySurface);
if (TempRenderTexture->GetSurfaceLevel(0, &backbuff))
{
FrontCopySurface = backbuff;
}
}
else
{
// Fullscreen, not pixel doubled: The back buffer has what we want,
// but it might be letter boxed.
if (GetBackBuffer(&backbuff))
{
LTRBRect srcrect = { 0, LBOffsetI, Width, LBOffsetI + Height };
StretchRect(backbuff, &srcrect, FrontCopySurface);
delete backbuff;
}
}
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: PaintToWindow
@ -1207,50 +1086,49 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
{
if (copy3d)
{
LTRBRect texrect = { 0, 0, Width, Height };
LockedRect lockrect;
if ((FBWidth == Width && FBHeight == Height &&
FBTexture->LockRect(&lockrect, nullptr, true)) ||
FBTexture->LockRect(&lockrect, &texrect, false))
if (FBTexture->Buffer == 0)
{
if (lockrect.Pitch == Pitch && Pitch == Width)
glGenBuffers(1, (GLuint*)&FBTexture->Buffer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, Width * Height, nullptr, GL_STREAM_DRAW);
}
else
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, FBTexture->Buffer);
}
uint8_t *dest = (uint8_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
if (dest)
{
if (Pitch == Width)
{
memcpy(lockrect.pBits, MemBuffer, Width * Height);
memcpy(dest, MemBuffer, Width * Height);
}
else
{
uint8_t *dest = (uint8_t *)lockrect.pBits;
uint8_t *src = MemBuffer;
for (int y = 0; y < Height; y++)
{
memcpy(dest, src, Width);
dest += lockrect.Pitch;
dest += Width;
src += Pitch;
}
}
FBTexture->UnlockRect();
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
GLint oldBinding = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
glBindTexture(GL_TEXTURE_2D, FBTexture->Texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, GL_R8, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, oldBinding);
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
InScene = true;
if (vid_hwaalines)
glEnable(GL_LINE_SMOOTH);
else
glDisable(GL_LINE_SMOOTH);
assert(OldRenderTarget == nullptr);
if (TempRenderTexture != nullptr &&
((Windowed && TempRenderTexture != FinalWipeScreen) || GatheringWipeScreen || PixelDoubling))
{
HWSurface *targetsurf;
if (TempRenderTexture->GetSurfaceLevel(0, &targetsurf))
{
if (GetRenderTarget(0, &OldRenderTarget))
{
SetRenderTarget(0, targetsurf);
}
delete targetsurf;
}
}
SetTexture(0, FBTexture);
SetPaletteTexture(PaletteTexture, 256, BorderColor);
@ -1271,10 +1149,8 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
}
else
{
color0 = ColorValue(realfixedcolormap->ColorizeStart[0] / 2,
realfixedcolormap->ColorizeStart[1] / 2, realfixedcolormap->ColorizeStart[2] / 2, 0);
color1 = ColorValue(realfixedcolormap->ColorizeEnd[0] / 2,
realfixedcolormap->ColorizeEnd[1] / 2, realfixedcolormap->ColorizeEnd[2] / 2, 1);
color0 = ColorValue(realfixedcolormap->ColorizeStart[0] / 2, realfixedcolormap->ColorizeStart[1] / 2, realfixedcolormap->ColorizeStart[2] / 2, 0);
color1 = ColorValue(realfixedcolormap->ColorizeEnd[0] / 2, realfixedcolormap->ColorizeEnd[1] / 2, realfixedcolormap->ColorizeEnd[2] / 2, 1);
SetPixelShader(Shaders[SHADER_SpecialColormapPal]);
}
}
@ -1323,7 +1199,7 @@ void OpenGLSWFrameBuffer::DrawLetterbox()
void OpenGLSWFrameBuffer::DoWindowedGamma()
{
if (OldRenderTarget != nullptr)
/*if (OldRenderTarget != nullptr)
{
FBVERTEX verts[4];
@ -1336,49 +1212,28 @@ void OpenGLSWFrameBuffer::DoWindowedGamma()
DrawTriangleFans(2, verts);
delete OldRenderTarget;
OldRenderTarget = nullptr;
}
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: UpdateGammaTexture
//
// Updates the gamma texture used by the PS14 shader. We only use the first
// half of the texture so that we needn't worry about imprecision causing
// it to grab from the border.
//
//==========================================================================
void OpenGLSWFrameBuffer::UpdateGammaTexture(float igamma)
{
LockedRect lockrect;
if (GammaTexture != nullptr && GammaTexture->LockRect(&lockrect, nullptr, false))
{
uint8_t *pix = (uint8_t *)lockrect.pBits;
for (int i = 0; i <= 128; ++i)
{
pix[i * 4 + 2] = pix[i * 4 + 1] = pix[i * 4] = uint8_t(255.f * powf(i / 128.f, igamma));
pix[i * 4 + 3] = 255;
}
GammaTexture->UnlockRect();
}
}*/
}
void OpenGLSWFrameBuffer::UploadPalette()
{
LockedRect lockrect;
if (SkipAt < 0)
if (PaletteTexture->Buffer == 0)
{
SkipAt = 256;
glGenBuffers(1, (GLuint*)&PaletteTexture->Buffer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, PaletteTexture->Buffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, 256 * 4, nullptr, GL_STREAM_DRAW);
}
if (PaletteTexture->LockRect(&lockrect, nullptr, false))
else
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, PaletteTexture->Buffer);
}
uint8_t *pix = (uint8_t *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
if (pix)
{
uint8_t *pix = (uint8_t *)lockrect.pBits;
int i;
for (i = 0; i < SkipAt; ++i, pix += 4)
for (i = 0; i < 256; ++i, pix += 4)
{
pix[0] = SourcePalette[i].b;
pix[1] = SourcePalette[i].g;
@ -1394,9 +1249,16 @@ void OpenGLSWFrameBuffer::UploadPalette()
pix[2] = SourcePalette[i].r;
pix[3] = 255;
}
PaletteTexture->UnlockRect();
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
GLint oldBinding = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
glBindTexture(GL_TEXTURE_2D, PaletteTexture->Texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 1, GL_BGRA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, oldBinding);
BorderColor = ColorXRGB(SourcePalette[255].r, SourcePalette[255].g, SourcePalette[255].b);
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
PalEntry *OpenGLSWFrameBuffer::GetPalette()
@ -1484,6 +1346,8 @@ void OpenGLSWFrameBuffer::SetBlendingRect(int x1, int y1, int x2, int y2)
void OpenGLSWFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type)
{
Super::GetScreenshotBuffer(buffer, pitch, color_type);
/*
LockedRect lrect;
if (!Accel2D)
@ -1513,6 +1377,7 @@ void OpenGLSWFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch
color_type = SS_BGRA;
}
}
*/
}
//==========================================================================
@ -1527,58 +1392,9 @@ void OpenGLSWFrameBuffer::ReleaseScreenshotBuffer()
{
Super::ReleaseScreenshotBuffer();
}
if (ScreenshotSurface != nullptr)
{
ScreenshotSurface->UnlockRect();
delete ScreenshotSurface;
ScreenshotSurface = nullptr;
}
SafeRelease(ScreenshotTexture);
}
//==========================================================================
//
// OpenGLSWFrameBuffer :: GetCurrentScreen
//
// Returns a texture containing the pixels currently visible on-screen.
//
//==========================================================================
OpenGLSWFrameBuffer::HWTexture *OpenGLSWFrameBuffer::GetCurrentScreen()
{
HWTexture *tex;
HWSurface *surf;
bool hr;
if (FrontCopySurface == nullptr)
{
return nullptr;
}
hr = CreateTexture(FBWidth, FBHeight, 1, GL_RGBA8, &tex);
if (!hr)
{
return nullptr;
}
if (!tex->GetSurfaceLevel(0, &surf))
{
delete tex;
return nullptr;
}
// Video -> System memory : use GetRenderTargetData
GetRenderTargetData(FrontCopySurface, surf);
delete surf;
if (!hr)
{
delete tex;
return nullptr;
}
return tex;
}
/**************************************************************************/
/* 2D Stuff */
/**************************************************************************/
@ -2013,7 +1829,6 @@ bool OpenGLSWFrameBuffer::OpenGLTex::Create(OpenGLSWFrameBuffer *fb, bool wrappi
bool OpenGLSWFrameBuffer::OpenGLTex::Update()
{
LockedRect lrect;
LTRBRect rect;
uint8_t *dest;
@ -2025,27 +1840,44 @@ bool OpenGLSWFrameBuffer::OpenGLTex::Update()
int format = Box->Owner->Tex->Format;
rect = Box->Area;
if (!Box->Owner->Tex->LockRect(&lrect, &rect, false))
if (Box->Owner->Tex->Buffer == 0)
glGenBuffers(1, (GLuint*)&Box->Owner->Tex->Buffer);
int bytesPerPixel = 4;
switch (format)
{
case GL_R8: bytesPerPixel = 1; break;
case GL_RGBA8: bytesPerPixel = 4; break;
default: return false;
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, Box->Owner->Tex->Buffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, (rect.right - rect.left) * (rect.bottom - rect.top) * bytesPerPixel, nullptr, GL_STREAM_DRAW);
int pitch = (rect.right - rect.left) * bytesPerPixel;
uint8_t *bits = (uint8_t *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
dest = bits;
if (!dest)
{
return false;
}
dest = (uint8_t *)lrect.pBits;
if (Box->Padded)
{
dest += lrect.Pitch + (format == GL_R8 ? 1 : 4);
dest += pitch + (format == GL_R8 ? 1 : 4);
}
GameTex->FillBuffer(dest, lrect.Pitch, GameTex->GetHeight(), ToTexFmt(format));
GameTex->FillBuffer(dest, pitch, GameTex->GetHeight(), ToTexFmt(format));
if (Box->Padded)
{
// Clear top padding row.
dest = (uint8_t *)lrect.pBits;
dest = bits;
int numbytes = GameTex->GetWidth() + 2;
if (format != GL_R8)
{
numbytes <<= 2;
}
memset(dest, 0, numbytes);
dest += lrect.Pitch;
dest += pitch;
// Clear left and right padding columns.
if (format == GL_R8)
{
@ -2053,7 +1885,7 @@ bool OpenGLSWFrameBuffer::OpenGLTex::Update()
{
dest[0] = 0;
dest[numbytes - 1] = 0;
dest += lrect.Pitch;
dest += pitch;
}
}
else
@ -2062,13 +1894,20 @@ bool OpenGLSWFrameBuffer::OpenGLTex::Update()
{
*(uint32_t *)dest = 0;
*(uint32_t *)(dest + numbytes - 4) = 0;
dest += lrect.Pitch;
dest += pitch;
}
}
// Clear bottom padding row.
memset(dest, 0, numbytes);
}
Box->Owner->Tex->UnlockRect();
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
GLint oldBinding = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
glBindTexture(GL_TEXTURE_2D, Box->Owner->Tex->Texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, format == GL_RGBA8 ? GL_BGRA : GL_RED, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, oldBinding);
glBindTexture(GL_PIXEL_UNPACK_BUFFER, 0);
return true;
}
@ -2199,18 +2038,28 @@ OpenGLSWFrameBuffer::OpenGLPal::~OpenGLPal()
bool OpenGLSWFrameBuffer::OpenGLPal::Update()
{
LockedRect lrect;
uint32_t *buff;
const PalEntry *pal;
int skipat, i;
assert(Tex != nullptr);
if (!Tex->LockRect(&lrect, nullptr, 0))
if (Tex->Buffer == 0)
{
glGenBuffers(1, (GLuint*)&Tex->Buffer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, Tex->Buffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, Remap->NumEntries * 4, nullptr, GL_STREAM_DRAW);
}
else
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, Tex->Buffer);
}
buff = (uint32_t *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
if (buff == nullptr)
{
return false;
}
buff = (uint32_t *)lrect.pBits;
pal = Remap->Palette;
// See explanation in UploadPalette() for skipat rationale.
@ -2226,7 +2075,14 @@ bool OpenGLSWFrameBuffer::OpenGLPal::Update()
}
BorderColor = ColorARGB(pal[i].a, pal[i - 1].r, pal[i - 1].g, pal[i - 1].b);
Tex->UnlockRect();
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
GLint oldBinding = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
glBindTexture(GL_TEXTURE_2D, Tex->Texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Remap->NumEntries, 1, GL_BGRA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, oldBinding);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
return true;
}

View File

@ -85,32 +85,18 @@ private:
uint16_t red[256], green[256], blue[256];
};
struct LockedRect
{
int Pitch;
void *pBits;
};
struct LTRBRect
{
int left, top, right, bottom;
};
class HWSurface
{
public:
bool LockRect(LockedRect *outRect, LTRBRect *srcRect, bool discard) { outRect->Pitch = 0; outRect->pBits = nullptr; return false; }
void UnlockRect() { }
};
class HWTexture
{
public:
bool LockRect(LockedRect *outRect, LTRBRect *srcRect, bool discard) { outRect->Pitch = 0; outRect->pBits = nullptr; return false; }
void UnlockRect() { }
bool GetSurfaceLevel(int level, HWSurface **outSurface) { *outSurface = nullptr; return false; }
~HWTexture();
int Texture = 0;
int Buffer = 0;
int WrapS = 0;
int WrapT = 0;
int Format = 0;
@ -119,60 +105,43 @@ private:
class HWVertexBuffer
{
public:
~HWVertexBuffer()
{
if (Buffer != 0) glDeleteVertexArrays(1, (GLuint*)&VertexArray);
if (Buffer != 0) glDeleteBuffers(1, (GLuint*)&Buffer);
}
~HWVertexBuffer();
FBVERTEX *Lock() { return nullptr; }
void Unlock() { }
FBVERTEX *Lock();
void Unlock();
int Buffer = 0;
int VertexArray = 0;
int Buffer = 0;
};
class HWIndexBuffer
{
public:
~HWIndexBuffer()
{
if (Buffer != 0) glDeleteBuffers(1, (GLuint*)&Buffer);
}
~HWIndexBuffer();
uint16_t *Lock() { return nullptr; }
void Unlock() { }
uint16_t *Lock();
void Unlock();
int Buffer = 0;
private:
int LockedOldBinding = 0;
};
class HWPixelShader
{
public:
~HWPixelShader()
{
if (Program != 0) glDeleteProgram(Program);
if (VertexShader != 0) glDeleteShader(VertexShader);
if (FragmentShader != 0) glDeleteShader(FragmentShader);
}
~HWPixelShader();
int Program = 0;
int VertexShader = 0;
int FragmentShader = 0;
};
bool CreatePixelShader(const void *vertexsrc, const void *fragmentsrc, HWPixelShader **outShader);
bool CreatePixelShader(FString vertexsrc, FString fragmentsrc, const FString &defines, HWPixelShader **outShader);
bool CreateVertexBuffer(int size, HWVertexBuffer **outVertexBuffer);
bool CreateIndexBuffer(int size, HWIndexBuffer **outIndexBuffer);
bool CreateOffscreenPlainSurface(int width, int height, int format, HWSurface **outSurface);
bool CreateTexture(int width, int height, int levels, int format, HWTexture **outTexture);
bool CreateRenderTarget(int width, int height, int format, HWSurface **outSurface);
bool GetBackBuffer(HWSurface **outSurface);
bool GetRenderTarget(int index, HWSurface **outSurface);
void GetRenderTargetData(HWSurface *a, HWSurface *b);
void ColorFill(HWSurface *surface, float red, float green, float blue);
void StretchRect(HWSurface *src, const LTRBRect *srcrect, HWSurface *dest);
bool SetRenderTarget(int index, HWSurface *surface);
void SetGammaRamp(const GammaRamp *ramp);
void SetPixelShaderConstantF(int uniformIndex, const float *data, int vec4fcount);
void SetHWPixelShader(HWPixelShader *shader);
@ -362,19 +331,17 @@ private:
NUM_SHADERS
};
static const char *const ShaderNames[NUM_SHADERS];
static const char *const ShaderDefines[NUM_SHADERS];
void Flip();
void SetInitialState();
bool CreateResources();
void ReleaseResources();
bool LoadShaders();
void CreateBlockSurfaces();
bool CreateFBTexture();
bool CreatePaletteTexture();
bool CreateVertexes();
void UploadPalette();
void UpdateGammaTexture(float igamma);
void CalcFullscreenCoords(FBVERTEX verts[4], bool viewarea_only, bool can_double, uint32_t color0, uint32_t color1) const;
bool Reset();
HWTexture *GetCurrentScreen();
@ -397,7 +364,6 @@ private:
void BeginLineBatch();
void EndLineBatch();
void EndBatch();
void CopyNextFrontBuffer();
// State
void EnableAlphaTest(BOOL enabled);
@ -431,10 +397,7 @@ private:
int FlashAmount;
int TrueHeight;
int PixelDoubling;
int SkipAt;
int LBOffsetI;
int RenderTextureToggle;
int CurrRenderTexture;
float LBOffset;
float Gamma;
bool UpdatePending;
@ -448,34 +411,28 @@ private:
bool GatheringWipeScreen;
bool AALines;
uint8_t BlockNum;
OpenGLPal *Palettes;
OpenGLTex *Textures;
Atlas *Atlases;
OpenGLPal *Palettes = nullptr;
OpenGLTex *Textures = nullptr;
Atlas *Atlases = nullptr;
HWTexture *FBTexture;
HWTexture *TempRenderTexture, *RenderTexture[2];
HWTexture *PaletteTexture;
HWTexture *GammaTexture;
HWTexture *ScreenshotTexture;
HWSurface *ScreenshotSurface;
HWSurface *FrontCopySurface;
HWTexture *FBTexture = nullptr;
HWTexture *PaletteTexture = nullptr;
HWTexture *ScreenshotTexture = nullptr;
HWVertexBuffer *VertexBuffer;
FBVERTEX *VertexData;
HWIndexBuffer *IndexBuffer;
uint16_t *IndexData;
BufferedTris *QuadExtra;
HWVertexBuffer *VertexBuffer = nullptr;
FBVERTEX *VertexData = nullptr;
HWIndexBuffer *IndexBuffer = nullptr;
uint16_t *IndexData = nullptr;
BufferedTris *QuadExtra = nullptr;
int VertexPos;
int IndexPos;
int QuadBatchPos;
enum { BATCH_None, BATCH_Quads, BATCH_Lines } BatchType;
HWPixelShader *Shaders[NUM_SHADERS];
HWPixelShader *GammaShader;
HWPixelShader *GammaShader = nullptr;
HWSurface *BlockSurface[2];
HWSurface *OldRenderTarget;
HWTexture *InitialWipeScreen, *FinalWipeScreen;
HWTexture *InitialWipeScreen = nullptr, *FinalWipeScreen = nullptr;
class Wiper
{

View File

@ -137,8 +137,9 @@ void I_InitGraphics ()
ticker.SetGenericRepDefault (val, CVAR_Bool);
//currentrenderer = vid_renderer;
if (currentrenderer==1) Video = gl_CreateVideo();
else Video = new Win32Video (0);
Video = gl_CreateVideo();
//if (currentrenderer==1) Video = gl_CreateVideo();
//else Video = new Win32Video (0);
if (Video == NULL)
I_FatalError ("Failed to initialize display");

View File

@ -25,6 +25,7 @@
#include "gl/renderer/gl_renderer.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/system/gl_swframebuffer.h"
extern "C" {
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
@ -386,7 +387,10 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer(int width, int height, bool fs, DF
//old->GetFlash(flashColor, flashAmount);
delete old;
}
fb = new OpenGLFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs);
if (vid_renderer == 1)
fb = new OpenGLFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs);
else
fb = new OpenGLSWFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs);
return fb;
}

View File

@ -0,0 +1,146 @@
in vec4 PixelColor0;
in vec4 PixelColor1;
in vec4 PixelTexCoord0;
out vec4 FragColor;
uniform sampler2D Image;// : register(s0);
uniform sampler2D Palette;// : register(s1);
uniform sampler2D NewScreen;// : register(s0);
uniform sampler2D Burn;// : register(s1);
uniform vec4 Desaturation;// : register(c1); // { Desat, 1 - Desat }
uniform vec4 PaletteMod;// : register(c2);
uniform vec4 Weights;// : register(c6); // RGB->Gray weighting { 77/256.0, 143/256.0, 37/256.0, 1 }
uniform vec4 Gamma;// : register(c7);
vec4 TextureLookup(vec2 tex_coord)
{
#if PALTEX
float index = texture(Image, tex_coord).x;
index = index * PaletteMod.x + PaletteMod.y;
return texture(Palette, vec2(index, 0.5));
#else
return texture(Image, tex_coord);
#endif
}
vec4 Invert(vec4 rgb)
{
#if INVERT
rgb.rgb = Weights.www - rgb.xyz;
#endif
return rgb;
}
float Grayscale(vec4 rgb)
{
return dot(rgb.rgb, Weights.rgb);
}
vec4 SampleTexture(vec2 tex_coord)
{
return Invert(TextureLookup(tex_coord));
}
// Normal color calculation for most drawing modes.
vec4 NormalColor(vec2 tex_coord, vec4 Flash, vec4 InvFlash)
{
return Flash + SampleTexture(tex_coord) * InvFlash;
}
// Copy the red channel to the alpha channel. Pays no attention to palettes.
vec4 RedToAlpha(vec2 tex_coord, vec4 Flash, vec4 InvFlash)
{
vec4 color = Invert(texture(Image, tex_coord));
color.a = color.r;
return Flash + color * InvFlash;
}
// Just return the value of c0.
vec4 VertexColor(vec4 color)
{
return color;
}
// Emulate one of the special colormaps. (Invulnerability, gold, etc.)
vec4 SpecialColormap(vec2 tex_coord, vec4 start, vec4 end)
{
vec4 color = SampleTexture(tex_coord);
vec4 range = end - start;
// We can't store values greater than 1.0 in a color register, so we multiply
// the final result by 2 and expect the caller to divide the start and end by 2.
color.rgb = 2 * (start + Grayscale(color) * range).rgb;
// Duplicate alpha semantics of NormalColor.
color.a = start.a + color.a * end.a;
return color;
}
// In-game colormap effect: fade to a particular color and multiply by another, with
// optional desaturation of the original color. Desaturation is stored in c1.
// Fade level is packed int fade.a. Fade.rgb has been premultiplied by alpha.
// Overall alpha is in color.a.
vec4 InGameColormap(vec2 tex_coord, vec4 color, vec4 fade)
{
vec4 rgb = SampleTexture(tex_coord);
// Desaturate
#if DESAT
vec3 intensity;
intensity.rgb = vec3(Grayscale(rgb) * Desaturation.x);
rgb.rgb = intensity.rgb + rgb.rgb * Desaturation.y;
#endif
// Fade
rgb.rgb = rgb.rgb * fade.aaa + fade.rgb;
// Shade and Alpha
rgb = rgb * color;
return rgb;
}
// Windowed gamma correction.
vec4 GammaCorrection(vec2 tex_coord)
{
vec4 color = texture(Image, tex_coord);
color.rgb = pow(color.rgb, Gamma.rgb);
return color;
}
// The burn wipe effect.
vec4 BurnWipe(vec4 coord)
{
vec4 color = texture(NewScreen, coord.xy);
vec4 alpha = texture(Burn, coord.zw);
color.a = alpha.r * 2;
return color;
}
void main()
{
#if defined(ENORMALCOLOR)
FragColor = NormalColor(PixelTexCoord0.xy, PixelColor0, PixelColor1);
#elif defined(EREDTOALPHA)
FragColor = RedToAlpha(PixelTexCoord0.xy, PixelColor0, PixelColor1);
#elif defined(EVERTEXCOLOR)
FragColor = VertexColor(PixelColor0);
#elif defined(ESPECIALCOLORMAP)
FragColor = SpecialColormap(PixelTexCoord0.xy, PixelColor0, PixelColor1);
#elif defined(EINGAMECOLORMAP)
FragColor = InGameColormap(PixelTexCoord0.xy, PixelColor0, PixelColor1);
#elif defined(EBURNWIPE)
FragColor = BurnWipe(PixelTexCoord0);
#elif defined(EGAMMACORRECTION)
FragColor = GammaCorrection(PixelTexCoord0.xy);
#else
#error Entry point define is missing
#endif
}

View File

@ -0,0 +1,17 @@
in vec4 AttrPosition;
in vec4 AttrColor0;
in vec4 AttrColor1;
in vec4 AttrTexCoord0;
out vec4 PixelColor0;
out vec4 PixelColor1;
out vec4 PixelTexCoord0;
void main()
{
gl_Position = AttrPosition;
PixelColor0 = AttrColor0;
PixelColor1 = AttrColor1;
PixelTexCoord0 = AttrTexCoord0;
}