- change tonemaps to steps

This commit is contained in:
Magnus Norddahl 2018-06-23 19:25:49 +02:00
parent ebf0cef283
commit b2fad453fa
9 changed files with 114 additions and 182 deletions

View file

@ -1068,7 +1068,6 @@ set (PCH_SOURCES
hwrenderer/postprocessing/hw_presentshader.cpp hwrenderer/postprocessing/hw_presentshader.cpp
hwrenderer/postprocessing/hw_present3dRowshader.cpp hwrenderer/postprocessing/hw_present3dRowshader.cpp
hwrenderer/postprocessing/hw_ambientshader.cpp hwrenderer/postprocessing/hw_ambientshader.cpp
hwrenderer/postprocessing/hw_tonemapshader.cpp
hwrenderer/textures/hw_material.cpp hwrenderer/textures/hw_material.cpp
hwrenderer/textures/hw_precache.cpp hwrenderer/textures/hw_precache.cpp
hwrenderer/utility/hw_clock.cpp hwrenderer/utility/hw_clock.cpp

View file

@ -40,7 +40,6 @@
#include "gl/renderer/gl_postprocessstate.h" #include "gl/renderer/gl_postprocessstate.h"
#include "gl/data/gl_vertexbuffer.h" #include "gl/data/gl_vertexbuffer.h"
#include "hwrenderer/postprocessing/hw_ambientshader.h" #include "hwrenderer/postprocessing/hw_ambientshader.h"
#include "hwrenderer/postprocessing/hw_tonemapshader.h"
#include "hwrenderer/postprocessing/hw_presentshader.h" #include "hwrenderer/postprocessing/hw_presentshader.h"
#include "hwrenderer/postprocessing/hw_postprocess.h" #include "hwrenderer/postprocessing/hw_postprocess.h"
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h" #include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
@ -101,10 +100,13 @@ void FGLRenderBuffers::RenderEffect(const FString &name)
if (!gltexture) if (!gltexture)
{ {
gltexture = Create2DTexture(name.GetChars(), glformat, pair->Value.Width, pair->Value.Height); if (pair->Value.Data)
gltexture = Create2DTexture(pair->Key.GetChars(), glformat, pair->Value.Width, pair->Value.Height, pair->Value.Data.get());
else
gltexture = Create2DTexture(pair->Key.GetChars(), glformat, pair->Value.Width, pair->Value.Height);
gltexture.Width = pair->Value.Width; gltexture.Width = pair->Value.Width;
gltexture.Height = pair->Value.Height; gltexture.Height = pair->Value.Height;
glframebuffer = CreateFrameBuffer(name.GetChars(), gltexture); glframebuffer = CreateFrameBuffer(pair->Key.GetChars(), gltexture);
} }
} }
} }
@ -378,76 +380,16 @@ void FGLRenderer::BlurScene(float gameinfobluramount)
void FGLRenderer::TonemapScene() void FGLRenderer::TonemapScene()
{ {
if (gl_tonemap == 0) PPTonemap tonemap;
return; tonemap.DeclareShaders();
tonemap.UpdateTextures();
FGLDebug::PushGroup("TonemapScene"); tonemap.UpdateSteps();
mBuffers->RenderEffect("TonemapScene");
CreateTonemapPalette();
FGLPostProcessState savedState;
savedState.SaveTextureBindings(2);
mBuffers->BindNextFB();
mBuffers->BindCurrentTexture(0);
mTonemapShader->Bind(NOQUEUE);
if (mTonemapShader->IsPaletteMode())
{
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, mTonemapPalette->GetTextureHandle(0));
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);
}
else
{
//mBuffers->ExposureTexture.Bind(1);
}
RenderScreenQuad();
mBuffers->NextTexture();
FGLDebug::PopGroup();
}
void FGLRenderer::CreateTonemapPalette()
{
if (!mTonemapPalette)
{
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[(uint8_t)PTM_BestColor((uint32_t *)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4),
gl_paltonemap_reverselookup, gl_paltonemap_powtable, 0, 256)];
int index = ((r * 64 + g) * 64 + b) * 4;
lut[index] = color.b;
lut[index + 1] = color.g;
lut[index + 2] = color.r;
lut[index + 3] = 255;
}
}
}
mTonemapPalette = new FHardwareTexture(true);
mTonemapPalette->CreateTexture(&lut[0], 512, 512, 0, false, 0, "mTonemapPalette");
}
} }
void FGLRenderer::ClearTonemapPalette() void FGLRenderer::ClearTonemapPalette()
{ {
if (mTonemapPalette) hw_postprocess.Textures.Remove("Tonemap.Palette");
{
delete mTonemapPalette;
mTonemapPalette = nullptr;
}
} }
void FGLRenderer::ColormapScene(int fixedcm) void FGLRenderer::ColormapScene(int fixedcm)

View file

@ -51,7 +51,6 @@
#include "gl/scene/gl_drawinfo.h" #include "gl/scene/gl_drawinfo.h"
#include "gl/scene/gl_scenedrawer.h" #include "gl/scene/gl_scenedrawer.h"
#include "hwrenderer/postprocessing/hw_ambientshader.h" #include "hwrenderer/postprocessing/hw_ambientshader.h"
#include "hwrenderer/postprocessing/hw_tonemapshader.h"
#include "hwrenderer/postprocessing/hw_presentshader.h" #include "hwrenderer/postprocessing/hw_presentshader.h"
#include "hwrenderer/postprocessing/hw_present3dRowshader.h" #include "hwrenderer/postprocessing/hw_present3dRowshader.h"
#include "hwrenderer/postprocessing/hw_shadowmapshader.h" #include "hwrenderer/postprocessing/hw_shadowmapshader.h"
@ -90,7 +89,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mSkyVBO = nullptr; mSkyVBO = nullptr;
mShaderManager = nullptr; mShaderManager = nullptr;
mLights = nullptr; mLights = nullptr;
mTonemapPalette = nullptr;
mBuffers = nullptr; mBuffers = nullptr;
mScreenBuffers = nullptr; mScreenBuffers = nullptr;
mSaveBuffers = nullptr; mSaveBuffers = nullptr;
@ -98,8 +96,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mPresent3dCheckerShader = nullptr; mPresent3dCheckerShader = nullptr;
mPresent3dColumnShader = nullptr; mPresent3dColumnShader = nullptr;
mPresent3dRowShader = nullptr; mPresent3dRowShader = nullptr;
mTonemapShader = nullptr;
mTonemapPalette = nullptr;
mLinearDepthShader = nullptr; mLinearDepthShader = nullptr;
mDepthBlurShader = nullptr; mDepthBlurShader = nullptr;
mSSAOShader = nullptr; mSSAOShader = nullptr;
@ -117,8 +113,6 @@ void FGLRenderer::Initialize(int width, int height)
mDepthBlurShader = new FDepthBlurShader(); mDepthBlurShader = new FDepthBlurShader();
mSSAOShader = new FSSAOShader(); mSSAOShader = new FSSAOShader();
mSSAOCombineShader = new FSSAOCombineShader(); mSSAOCombineShader = new FSSAOCombineShader();
mTonemapShader = new FTonemapShader();
mTonemapPalette = nullptr;
mPresentShader = new FPresentShader(); mPresentShader = new FPresentShader();
mPresent3dCheckerShader = new FPresent3DCheckerShader(); mPresent3dCheckerShader = new FPresent3DCheckerShader();
mPresent3dColumnShader = new FPresent3DColumnShader(); mPresent3dColumnShader = new FPresent3DColumnShader();
@ -173,8 +167,6 @@ FGLRenderer::~FGLRenderer()
if (mPresent3dCheckerShader) delete mPresent3dCheckerShader; if (mPresent3dCheckerShader) delete mPresent3dCheckerShader;
if (mPresent3dColumnShader) delete mPresent3dColumnShader; if (mPresent3dColumnShader) delete mPresent3dColumnShader;
if (mPresent3dRowShader) delete mPresent3dRowShader; if (mPresent3dRowShader) delete mPresent3dRowShader;
if (mTonemapShader) delete mTonemapShader;
if (mTonemapPalette) delete mTonemapPalette;
if (mShadowMapShader) delete mShadowMapShader; if (mShadowMapShader) delete mShadowMapShader;
delete mCustomPostProcessShaders; delete mCustomPostProcessShaders;
} }

View file

@ -29,7 +29,6 @@ class FLinearDepthShader;
class FDepthBlurShader; class FDepthBlurShader;
class FSSAOShader; class FSSAOShader;
class FSSAOCombineShader; class FSSAOCombineShader;
class FTonemapShader;
class FPresentShader; class FPresentShader;
class FPresent3DCheckerShader; class FPresent3DCheckerShader;
class FPresent3DColumnShader; class FPresent3DColumnShader;
@ -74,8 +73,6 @@ public:
FSSAOShader *mSSAOShader; FSSAOShader *mSSAOShader;
FDepthBlurShader *mDepthBlurShader; FDepthBlurShader *mDepthBlurShader;
FSSAOCombineShader *mSSAOCombineShader; FSSAOCombineShader *mSSAOCombineShader;
FTonemapShader *mTonemapShader;
FHardwareTexture *mTonemapPalette;
FPresentShader *mPresentShader; FPresentShader *mPresentShader;
FPresent3DCheckerShader *mPresent3dCheckerShader; FPresent3DCheckerShader *mPresent3dCheckerShader;
FPresent3DColumnShader *mPresent3dColumnShader; FPresent3DColumnShader *mPresent3dColumnShader;
@ -118,7 +115,6 @@ public:
void BloomScene(int fixedcm); void BloomScene(int fixedcm);
void TonemapScene(); void TonemapScene();
void ColormapScene(int fixedcm); void ColormapScene(int fixedcm);
void CreateTonemapPalette();
void ClearTonemapPalette(); void ClearTonemapPalette();
void LensDistortScene(); void LensDistortScene();
void ApplyFXAA(); void ApplyFXAA();

View file

@ -514,3 +514,79 @@ void PPColormap::UpdateSteps(int fixedcm)
steps.Push(step); steps.Push(step);
hw_postprocess.Effects["ColormapScene"] = steps; hw_postprocess.Effects["ColormapScene"] = steps;
} }
/////////////////////////////////////////////////////////////////////////////
void PPTonemap::DeclareShaders()
{
hw_postprocess.Shaders["Tonemap.Linear"] = { "shaders/glsl/tonemap.fp", "#define LINEAR\n", {} };
hw_postprocess.Shaders["Tonemap.Reinhard"] = { "shaders/glsl/tonemap.fp", "#define REINHARD\n", {} };
hw_postprocess.Shaders["Tonemap.HejlDawson"] = { "shaders/glsl/tonemap.fp", "#define HEJLDAWSON\n", {} };
hw_postprocess.Shaders["Tonemap.Uncharted2"] = { "shaders/glsl/tonemap.fp", "#define UNCHARTED2\n", {} };
hw_postprocess.Shaders["Tonemap.Palette"] = { "shaders/glsl/tonemap.fp", "#define PALETTE\n", {} };
}
void PPTonemap::UpdateTextures()
{
if (gl_tonemap == Palette)
{
auto &texture = hw_postprocess.Textures["Tonemap.Palette"];
if (!texture.Data)
{
std::shared_ptr<void> data(new uint32_t[512 * 512], [](void *p) { delete[](uint32_t*)p; });
uint8_t *lut = (uint8_t *)data.get();
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[(uint8_t)PTM_BestColor((uint32_t *)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4),
gl_paltonemap_reverselookup, gl_paltonemap_powtable, 0, 256)];
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;
}
}
}
texture = { 512, 512, PixelFormat::Rgba8, data };
}
}
}
void PPTonemap::UpdateSteps()
{
if (gl_tonemap == 0)
{
hw_postprocess.Effects["TonemapScene"] = {};
return;
}
PPShaderName shader;
switch (gl_tonemap)
{
default:
case Linear: shader = "Tonemap.Linear"; break;
case Reinhard: shader = "Tonemap.Reinhard"; break;
case HejlDawson: shader = "Tonemap.HejlDawson"; break;
case Uncharted2: shader = "Tonemap.Uncharted2"; break;
case Palette: shader = "Tonemap.Palette"; break;
}
PPStep step;
step.ShaderName = shader;
step.Viewport = screen->mScreenViewport;
step.SetInputCurrent(0);
if (gl_tonemap == Palette)
step.SetInputTexture(1, "Tonemap.Palette");
step.SetOutputNext();
step.SetNoBlend();
TArray<PPStep> steps;
steps.Push(step);
hw_postprocess.Effects["TonemapScene"] = steps;
}

View file

@ -179,11 +179,12 @@ class PPTextureDesc
{ {
public: public:
PPTextureDesc() { } PPTextureDesc() { }
PPTextureDesc(int width, int height, PixelFormat format) : Width(width), Height(height), Format(format) { } PPTextureDesc(int width, int height, PixelFormat format, std::shared_ptr<void> data = {}) : Width(width), Height(height), Format(format), Data(data) { }
int Width; int Width;
int Height; int Height;
PixelFormat Format; PixelFormat Format;
std::shared_ptr<void> Data;
}; };
class PPShader class PPShader
@ -411,3 +412,24 @@ public:
void DeclareShaders(); void DeclareShaders();
void UpdateSteps(int fixedcm); void UpdateSteps(int fixedcm);
}; };
/////////////////////////////////////////////////////////////////////////////
class PPTonemap
{
public:
void DeclareShaders();
void UpdateTextures();
void UpdateSteps();
enum TonemapMode
{
None,
Uncharted2,
HejlDawson,
Reinhard,
Linear,
Palette,
NumTonemapModes
};
};

View file

@ -1,63 +0,0 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2016 Magnus Norddahl
// 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_tonemapshader.cpp
** Converts a HDR texture to 0-1 range by applying a tonemap operator
**
*/
#include "v_video.h"
#include "hwrenderer/utility/hw_cvars.h"
#include "hw_tonemapshader.h"
void FTonemapShader::Bind(IRenderQueue *q)
{
auto &shader = mShader[gl_tonemap];
if (!shader)
{
auto prolog = GetDefines(gl_tonemap);
shader.reset(screen->CreateShaderProgram());
shader->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
shader->Compile(IShaderProgram::Fragment, "shaders/glsl/tonemap.fp", prolog, 330);
shader->Link("shaders/glsl/tonemap");
}
shader->Bind(q);
}
bool FTonemapShader::IsPaletteMode()
{
return gl_tonemap == Palette;
}
const char *FTonemapShader::GetDefines(int mode)
{
switch (mode)
{
default:
case Linear: return "#define LINEAR\n";
case Reinhard: return "#define REINHARD\n";
case HejlDawson: return "#define HEJLDAWSON\n";
case Uncharted2: return "#define UNCHARTED2\n";
case Palette: return "#define PALETTE\n";
}
}

View file

@ -1,30 +0,0 @@
#ifndef __GL_TONEMAPSHADER_H
#define __GL_TONEMAPSHADER_H
#include "hwrenderer/postprocessing/hw_shaderprogram.h"
class FTonemapShader
{
public:
void Bind(IRenderQueue *q);
static bool IsPaletteMode();
private:
enum TonemapMode
{
None,
Uncharted2,
HejlDawson,
Reinhard,
Linear,
Palette,
NumTonemapModes
};
static const char *GetDefines(int mode);
std::unique_ptr<IShaderProgram> mShader[NumTonemapModes];
};
#endif

View file

@ -3,7 +3,6 @@ in vec2 TexCoord;
layout(location=0) out vec4 FragColor; layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D InputTexture; layout(binding=0) uniform sampler2D InputTexture;
layout(binding=1) uniform sampler2D ExposureTexture;
vec3 Linear(vec3 c) vec3 Linear(vec3 c)
{ {
@ -65,15 +64,16 @@ vec3 Tonemap(vec3 color)
#elif defined(PALETTE) #elif defined(PALETTE)
layout(binding=2) uniform sampler2D PaletteLUT; layout(binding=1) uniform sampler2D PaletteLUT;
vec3 Tonemap(vec3 color) vec3 Tonemap(vec3 color)
{ {
ivec3 c = ivec3(clamp(color.rgb, vec3(0.0), vec3(1.0)) * 63.0 + 0.5); /*ivec3 c = ivec3(clamp(color.rgb, vec3(0.0), vec3(1.0)) * 63.0 + 0.5);
int index = (c.r * 64 + c.g) * 64 + c.b; int index = (c.r * 64 + c.g) * 64 + c.b;
int tx = index % 512; int tx = index % 512;
int ty = index / 512; int ty = index / 512;
return texelFetch(PaletteLUT, ivec2(tx, ty), 0).rgb; return texelFetch(PaletteLUT, ivec2(tx, ty), 0).rgb;*/
return texture(PaletteLUT, TexCoord).rgb;
} }
#else #else
@ -84,8 +84,6 @@ void main()
{ {
vec3 color = texture(InputTexture, TexCoord).rgb; vec3 color = texture(InputTexture, TexCoord).rgb;
#ifndef PALETTE #ifndef PALETTE
float exposureAdjustment = texture(ExposureTexture, vec2(0.5)).x;
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 #endif
FragColor = vec4(Tonemap(color), 1.0); FragColor = vec4(Tonemap(color), 1.0);