Add Palette LUT tonemap mode

This commit is contained in:
Magnus Norddahl 2016-08-23 09:18:18 +02:00
parent 13a583faee
commit 25645d901e
10 changed files with 102 additions and 7 deletions

View file

@ -55,6 +55,7 @@
#include "r_utility.h" #include "r_utility.h"
#include "a_hexenglobal.h" #include "a_hexenglobal.h"
#include "p_local.h" #include "p_local.h"
#include "colormatcher.h"
#include "gl/gl_functions.h" #include "gl/gl_functions.h"
#include "gl/system/gl_interface.h" #include "gl/system/gl_interface.h"
#include "gl/system/gl_framebuffer.h" #include "gl/system/gl_framebuffer.h"
@ -89,7 +90,7 @@ CVAR(Float, gl_exposure, 0.0f, 0)
CUSTOM_CVAR(Int, gl_tonemap, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CUSTOM_CVAR(Int, gl_tonemap, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{ {
if (self < 0 || self > 4) if (self < 0 || self > 5)
self = 0; self = 0;
} }
@ -222,13 +223,61 @@ void FGLRenderer::TonemapScene()
mBuffers->BindCurrentTexture(0); mBuffers->BindCurrentTexture(0);
mTonemapShader->Bind(); mTonemapShader->Bind();
mTonemapShader->SceneTexture.Set(0); mTonemapShader->SceneTexture.Set(0);
if (mTonemapShader->IsPaletteMode())
{
mTonemapShader->PaletteLUT.Set(1);
BindTonemapPalette(1);
}
else
{
mTonemapShader->Exposure.Set(mCameraExposure); mTonemapShader->Exposure.Set(mCameraExposure);
}
RenderScreenQuad(); RenderScreenQuad();
mBuffers->NextTexture(); mBuffers->NextTexture();
FGLDebug::PopGroup(); FGLDebug::PopGroup();
} }
void FGLRenderer::BindTonemapPalette(int texunit)
{
if (mTonemapPalette)
{
mTonemapPalette->Bind(texunit, 0, false);
}
else
{
TArray<unsigned char> lut;
lut.Resize(512 * 512 * 4);
for (int r = 0; r < 64; r++)
{
for (int g = 0; g < 64; g++)
{
for (int b = 0; b < 64; b++)
{
PalEntry color = GPalette.BaseColors[ColorMatcher.Pick((r << 2) | (r >> 1), (g << 2) | (g >> 1), (b << 2) | (b >> 1))];
int index = ((r * 64 + g) * 64 + b) * 4;
lut[index] = color.r;
lut[index + 1] = color.g;
lut[index + 2] = color.b;
lut[index + 3] = 255;
}
}
}
mTonemapPalette = new FHardwareTexture(512, 512, true);
mTonemapPalette->CreateTexture(&lut[0], 512, 512, texunit, false, 0, "mTonemapPalette");
glActiveTexture(GL_TEXTURE0 + texunit);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE0);
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Apply lens distortion and place the result in the HUD/2D texture // Apply lens distortion and place the result in the HUD/2D texture

View file

@ -62,8 +62,12 @@ FGLPostProcessState::FGLPostProcessState()
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
if (gl.flags & RFL_SAMPLER_OBJECTS) if (gl.flags & RFL_SAMPLER_OBJECTS)
{ {
glGetIntegerv(GL_SAMPLER_BINDING, &samplerBinding); glGetIntegerv(GL_SAMPLER_BINDING, &samplerBinding[0]);
glBindSampler(0, 0); glBindSampler(0, 0);
glActiveTexture(GL_TEXTURE0 + 1);
glGetIntegerv(GL_SAMPLER_BINDING, &samplerBinding[1]);
glBindSampler(1, 0);
glActiveTexture(GL_TEXTURE0);
} }
glGetBooleanv(GL_BLEND, &blendEnabled); glGetBooleanv(GL_BLEND, &blendEnabled);
@ -120,7 +124,10 @@ FGLPostProcessState::~FGLPostProcessState()
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
if (gl.flags & RFL_SAMPLER_OBJECTS) if (gl.flags & RFL_SAMPLER_OBJECTS)
glBindSampler(0, samplerBinding); {
glBindSampler(0, samplerBinding[0]);
glBindSampler(1, samplerBinding[1]);
}
glBindTexture(GL_TEXTURE_2D, textureBinding); glBindTexture(GL_TEXTURE_2D, textureBinding);
glActiveTexture(activeTex); glActiveTexture(activeTex);
} }

View file

@ -20,7 +20,7 @@ private:
GLint activeTex; GLint activeTex;
GLint textureBinding; GLint textureBinding;
GLint samplerBinding; GLint samplerBinding[2];
GLboolean blendEnabled; GLboolean blendEnabled;
GLboolean scissorEnabled; GLboolean scissorEnabled;
GLboolean depthEnabled; GLboolean depthEnabled;

View file

@ -123,6 +123,7 @@ void FGLRenderer::Initialize(int width, int height)
mBloomCombineShader = new FBloomCombineShader(); mBloomCombineShader = new FBloomCombineShader();
mBlurShader = new FBlurShader(); mBlurShader = new FBlurShader();
mTonemapShader = new FTonemapShader(); mTonemapShader = new FTonemapShader();
mTonemapPalette = nullptr;
mLensShader = new FLensShader(); mLensShader = new FLensShader();
mPresentShader = new FPresentShader(); mPresentShader = new FPresentShader();
m2DDrawer = new F2DDrawer; m2DDrawer = new F2DDrawer;
@ -181,6 +182,7 @@ FGLRenderer::~FGLRenderer()
if (mBloomCombineShader) delete mBloomCombineShader; if (mBloomCombineShader) delete mBloomCombineShader;
if (mBlurShader) delete mBlurShader; if (mBlurShader) delete mBlurShader;
if (mTonemapShader) delete mTonemapShader; if (mTonemapShader) delete mTonemapShader;
if (mTonemapPalette) delete mTonemapPalette;
if (mLensShader) delete mLensShader; if (mLensShader) delete mLensShader;
} }

View file

@ -26,6 +26,7 @@ class FTonemapShader;
class FLensShader; class FLensShader;
class FPresentShader; class FPresentShader;
class F2DDrawer; class F2DDrawer;
class FHardwareTexture;
inline float DEG2RAD(float deg) inline float DEG2RAD(float deg)
{ {
@ -92,6 +93,7 @@ public:
FBloomCombineShader *mBloomCombineShader; FBloomCombineShader *mBloomCombineShader;
FBlurShader *mBlurShader; FBlurShader *mBlurShader;
FTonemapShader *mTonemapShader; FTonemapShader *mTonemapShader;
FHardwareTexture *mTonemapPalette;
FLensShader *mLensShader; FLensShader *mLensShader;
FPresentShader *mPresentShader; FPresentShader *mPresentShader;
@ -164,6 +166,7 @@ public:
void EndDrawScene(sector_t * viewsector); void EndDrawScene(sector_t * viewsector);
void BloomScene(); void BloomScene();
void TonemapScene(); void TonemapScene();
void BindTonemapPalette(int texunit);
void LensDistortScene(); void LensDistortScene();
void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma); void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma);
void Flush() { CopyToBackbuffer(nullptr, true); } void Flush() { CopyToBackbuffer(nullptr, true); }

View file

@ -61,10 +61,16 @@ void FTonemapShader::Bind()
shader.SetAttribLocation(0, "PositionInProjection"); shader.SetAttribLocation(0, "PositionInProjection");
SceneTexture.Init(shader, "InputTexture"); SceneTexture.Init(shader, "InputTexture");
Exposure.Init(shader, "ExposureAdjustment"); Exposure.Init(shader, "ExposureAdjustment");
PaletteLUT.Init(shader, "PaletteLUT");
} }
shader.Bind(); shader.Bind();
} }
bool FTonemapShader::IsPaletteMode()
{
return gl_tonemap == Palette;
}
const char *FTonemapShader::GetDefines(int mode) const char *FTonemapShader::GetDefines(int mode)
{ {
switch (mode) switch (mode)
@ -74,5 +80,6 @@ const char *FTonemapShader::GetDefines(int mode)
case Reinhard: return "#define REINHARD\n"; case Reinhard: return "#define REINHARD\n";
case HejlDawson: return "#define HEJLDAWSON\n"; case HejlDawson: return "#define HEJLDAWSON\n";
case Uncharted2: return "#define UNCHARTED2\n"; case Uncharted2: return "#define UNCHARTED2\n";
case Palette: return "#define PALETTE\n";
} }
} }

View file

@ -10,6 +10,9 @@ public:
FBufferedUniform1i SceneTexture; FBufferedUniform1i SceneTexture;
FBufferedUniform1f Exposure; FBufferedUniform1f Exposure;
FBufferedUniform1i PaletteLUT;
static bool IsPaletteMode();
private: private:
enum TonemapMode enum TonemapMode
@ -19,6 +22,7 @@ private:
HejlDawson, HejlDawson,
Reinhard, Reinhard,
Linear, Linear,
Palette,
NumTonemapModes NumTonemapModes
}; };

View file

@ -2700,3 +2700,4 @@ OPTVAL_QUADBUFFERED = "Quad-buffered";
OPTVAL_UNCHARTED2 = "Uncharted 2"; OPTVAL_UNCHARTED2 = "Uncharted 2";
OPTVAL_HEJLDAWSON = "Hejl Dawson"; OPTVAL_HEJLDAWSON = "Hejl Dawson";
OPTVAL_REINHARD = "Reinhard"; OPTVAL_REINHARD = "Reinhard";
OPTVAL_PALETTE = "Palette";

View file

@ -39,6 +39,7 @@ OptionValue "TonemapModes"
2, "$OPTVAL_HEJLDAWSON" 2, "$OPTVAL_HEJLDAWSON"
3, "$OPTVAL_REINHARD" 3, "$OPTVAL_REINHARD"
4, "$OPTVAL_LINEAR" 4, "$OPTVAL_LINEAR"
5, "$OPTVAL_PALETTE"
} }
OptionValue "TextureFormats" OptionValue "TextureFormats"

View file

@ -42,7 +42,7 @@ vec3 Tonemap(vec3 color)
return (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); // no sRGB needed return (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); // no sRGB needed
} }
#else #elif defined(UNCHARTED2)
vec3 Uncharted2Tonemap(vec3 x) vec3 Uncharted2Tonemap(vec3 x)
{ {
@ -63,12 +63,33 @@ vec3 Tonemap(vec3 color)
return sRGB(curr * whiteScale); return sRGB(curr * whiteScale);
} }
#elif defined(PALETTE)
uniform sampler2D PaletteLUT;
vec3 Tonemap(vec3 color)
{
ivec3 c = ivec3(clamp(color.rgb, vec3(0.0), vec3(1.0)) * 255.0 + 0.5);
int index = ((c.r >> 2) * 64 + (c.g >> 2)) * 64 + (c.b >> 2);
int tx = index % 512;
int ty = index / 512;
#if __VERSION__ < 130
return texture2D(PaletteLUT, vec2(float(tx) / 512.0, float(ty) / 512.0))).rgb;
#else
return texelFetch(PaletteLUT, ivec2(tx, ty), 0).rgb;
#endif
}
#else
#error "Tonemap mode define is missing"
#endif #endif
void main() void main()
{ {
vec3 color = texture(InputTexture, TexCoord).rgb; vec3 color = texture(InputTexture, TexCoord).rgb;
#ifndef PALETTE
color = color * ExposureAdjustment; color = color * ExposureAdjustment;
color = Linear(color); // needed because gzdoom's scene texture is not linear at the moment color = Linear(color); // needed because gzdoom's scene texture is not linear at the moment
#endif
FragColor = vec4(Tonemap(color), 1.0); FragColor = vec4(Tonemap(color), 1.0);
} }