mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-13 07:57:51 +00:00
- port bloom, blur and camera exposure to postprocess steps and remove the old implementation
This commit is contained in:
parent
fd2037bd6c
commit
83f50f5808
14 changed files with 302 additions and 738 deletions
|
@ -1067,9 +1067,7 @@ set (PCH_SOURCES
|
||||||
hwrenderer/postprocessing/hw_shadowmapshader.cpp
|
hwrenderer/postprocessing/hw_shadowmapshader.cpp
|
||||||
hwrenderer/postprocessing/hw_presentshader.cpp
|
hwrenderer/postprocessing/hw_presentshader.cpp
|
||||||
hwrenderer/postprocessing/hw_present3dRowshader.cpp
|
hwrenderer/postprocessing/hw_present3dRowshader.cpp
|
||||||
hwrenderer/postprocessing/hw_bloomshader.cpp
|
|
||||||
hwrenderer/postprocessing/hw_ambientshader.cpp
|
hwrenderer/postprocessing/hw_ambientshader.cpp
|
||||||
hwrenderer/postprocessing/hw_blurshader.cpp
|
|
||||||
hwrenderer/postprocessing/hw_colormapshader.cpp
|
hwrenderer/postprocessing/hw_colormapshader.cpp
|
||||||
hwrenderer/postprocessing/hw_tonemapshader.cpp
|
hwrenderer/postprocessing/hw_tonemapshader.cpp
|
||||||
hwrenderer/textures/hw_material.cpp
|
hwrenderer/textures/hw_material.cpp
|
||||||
|
|
|
@ -40,8 +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_bloomshader.h"
|
|
||||||
#include "hwrenderer/postprocessing/hw_blurshader.h"
|
|
||||||
#include "hwrenderer/postprocessing/hw_tonemapshader.h"
|
#include "hwrenderer/postprocessing/hw_tonemapshader.h"
|
||||||
#include "hwrenderer/postprocessing/hw_colormapshader.h"
|
#include "hwrenderer/postprocessing/hw_colormapshader.h"
|
||||||
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
||||||
|
@ -91,6 +89,7 @@ void FGLRenderBuffers::RenderEffect(const FString &name)
|
||||||
default:
|
default:
|
||||||
case PixelFormat::Rgba8: glformat = GL_RGBA8; break;
|
case PixelFormat::Rgba8: glformat = GL_RGBA8; break;
|
||||||
case PixelFormat::Rgba16f: glformat = GL_RGBA16F; break;
|
case PixelFormat::Rgba16f: glformat = GL_RGBA16F; break;
|
||||||
|
case PixelFormat::R32f: glformat = GL_R32F; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gltexture && (gltexture.Width != pair->Value.Width || gltexture.Height != pair->Value.Height))
|
if (gltexture && (gltexture.Width != pair->Value.Width || gltexture.Height != pair->Value.Height))
|
||||||
|
@ -345,125 +344,17 @@ void FGLRenderer::AmbientOccludeScene()
|
||||||
FGLDebug::PopGroup();
|
FGLDebug::PopGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Extracts light average from the scene and updates the camera exposure texture
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void FGLRenderer::UpdateCameraExposure()
|
void FGLRenderer::UpdateCameraExposure()
|
||||||
{
|
{
|
||||||
if (!gl_bloom && gl_tonemap == 0)
|
PPCameraExposure exposure;
|
||||||
return;
|
exposure.DeclareShaders();
|
||||||
|
exposure.UpdateTextures(mBuffers->GetSceneWidth(), mBuffers->GetSceneHeight());
|
||||||
FGLDebug::PushGroup("UpdateCameraExposure");
|
exposure.UpdateSteps();
|
||||||
|
mBuffers->RenderEffect("UpdateCameraExposure");
|
||||||
FGLPostProcessState savedState;
|
|
||||||
savedState.SaveTextureBindings(2);
|
|
||||||
|
|
||||||
// Extract light level from scene texture:
|
|
||||||
auto &level0 = mBuffers->ExposureLevels[0];
|
|
||||||
level0.Framebuffer.Bind();
|
|
||||||
glViewport(0, 0, level0.Width, level0.Height);
|
|
||||||
mBuffers->BindCurrentTexture(0, GL_LINEAR);
|
|
||||||
mExposureExtractShader->Bind(NOQUEUE);
|
|
||||||
mExposureExtractShader->Uniforms->Scale = screen->SceneScale();
|
|
||||||
mExposureExtractShader->Uniforms->Offset = screen->SceneOffset();
|
|
||||||
mExposureExtractShader->Uniforms.Set();
|
|
||||||
RenderScreenQuad();
|
|
||||||
|
|
||||||
// Find the average value:
|
|
||||||
for (unsigned int i = 0; i + 1 < mBuffers->ExposureLevels.Size(); i++)
|
|
||||||
{
|
|
||||||
auto &level = mBuffers->ExposureLevels[i];
|
|
||||||
auto &next = mBuffers->ExposureLevels[i + 1];
|
|
||||||
|
|
||||||
next.Framebuffer.Bind();
|
|
||||||
glViewport(0, 0, next.Width, next.Height);
|
|
||||||
level.Texture.Bind(0);
|
|
||||||
mExposureAverageShader->Bind(NOQUEUE);
|
|
||||||
RenderScreenQuad();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combine average value with current camera exposure:
|
|
||||||
mBuffers->ExposureFB.Bind();
|
|
||||||
glViewport(0, 0, 1, 1);
|
|
||||||
if (!mBuffers->FirstExposureFrame)
|
|
||||||
{
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mBuffers->FirstExposureFrame = false;
|
|
||||||
}
|
|
||||||
mBuffers->ExposureLevels.Last().Texture.Bind(0);
|
|
||||||
mExposureCombineShader->Bind(NOQUEUE);
|
|
||||||
mExposureCombineShader->Uniforms->ExposureBase = gl_exposure_base;
|
|
||||||
mExposureCombineShader->Uniforms->ExposureMin = gl_exposure_min;
|
|
||||||
mExposureCombineShader->Uniforms->ExposureScale = gl_exposure_scale;
|
|
||||||
mExposureCombineShader->Uniforms->ExposureSpeed = gl_exposure_speed;
|
|
||||||
mExposureCombineShader->Uniforms.Set();
|
|
||||||
RenderScreenQuad();
|
|
||||||
|
|
||||||
const auto &mScreenViewport = screen->mScreenViewport;
|
|
||||||
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
|
|
||||||
|
|
||||||
FGLDebug::PopGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Adds bloom contribution to scene texture
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static float ComputeBlurGaussian(float n, float theta) // theta = Blur Amount
|
|
||||||
{
|
|
||||||
return (float)((1.0f / sqrtf(2 * (float)M_PI * theta)) * expf(-(n * n) / (2.0f * theta * theta)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ComputeBlurSamples(int sampleCount, float blurAmount, float *sampleWeights)
|
|
||||||
{
|
|
||||||
sampleWeights[0] = ComputeBlurGaussian(0, blurAmount);
|
|
||||||
|
|
||||||
float totalWeights = sampleWeights[0];
|
|
||||||
|
|
||||||
for (int i = 0; i < sampleCount / 2; i++)
|
|
||||||
{
|
|
||||||
float weight = ComputeBlurGaussian(i + 1.0f, blurAmount);
|
|
||||||
|
|
||||||
sampleWeights[i * 2 + 1] = weight;
|
|
||||||
sampleWeights[i * 2 + 2] = weight;
|
|
||||||
|
|
||||||
totalWeights += weight * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < sampleCount; i++)
|
|
||||||
{
|
|
||||||
sampleWeights[i] /= totalWeights;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void RenderBlur(FGLRenderer *renderer, float blurAmount, PPTexture input, PPFrameBuffer output, int width, int height, bool vertical)
|
|
||||||
{
|
|
||||||
ComputeBlurSamples(7, blurAmount, renderer->mBlurShader->Uniforms[vertical]->SampleWeights);
|
|
||||||
|
|
||||||
renderer->mBlurShader->Bind(NOQUEUE, vertical);
|
|
||||||
renderer->mBlurShader->Uniforms[vertical].Set(POSTPROCESS_BINDINGPOINT);
|
|
||||||
|
|
||||||
input.Bind(0);
|
|
||||||
output.Bind();
|
|
||||||
glViewport(0, 0, width, height);
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
renderer->RenderScreenQuad();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderer::BloomScene(int fixedcm)
|
void FGLRenderer::BloomScene(int fixedcm)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
|
|
||||||
if (mBuffers->GetSceneWidth() <= 0 || mBuffers->GetSceneHeight() <= 0)
|
if (mBuffers->GetSceneWidth() <= 0 || mBuffers->GetSceneHeight() <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -471,157 +362,21 @@ void FGLRenderer::BloomScene(int fixedcm)
|
||||||
bloom.DeclareShaders();
|
bloom.DeclareShaders();
|
||||||
bloom.UpdateTextures(mBuffers->GetSceneWidth(), mBuffers->GetSceneHeight());
|
bloom.UpdateTextures(mBuffers->GetSceneWidth(), mBuffers->GetSceneHeight());
|
||||||
bloom.UpdateSteps(fixedcm);
|
bloom.UpdateSteps(fixedcm);
|
||||||
mBuffers->RenderEffect("Bloom");
|
mBuffers->RenderEffect("BloomScene");
|
||||||
|
|
||||||
#else
|
|
||||||
// Only bloom things if enabled and no special fixed light mode is active
|
|
||||||
if (!gl_bloom || fixedcm != CM_DEFAULT || gl_ssao_debug)
|
|
||||||
return;
|
|
||||||
|
|
||||||
FGLDebug::PushGroup("BloomScene");
|
|
||||||
|
|
||||||
FGLPostProcessState savedState;
|
|
||||||
savedState.SaveTextureBindings(2);
|
|
||||||
|
|
||||||
const float blurAmount = gl_bloom_amount;
|
|
||||||
|
|
||||||
auto &level0 = mBuffers->BloomLevels[0];
|
|
||||||
|
|
||||||
// Extract blooming pixels from scene texture:
|
|
||||||
level0.VFramebuffer.Bind();
|
|
||||||
glViewport(0, 0, level0.Width, level0.Height);
|
|
||||||
mBuffers->BindCurrentTexture(0, GL_LINEAR);
|
|
||||||
mBuffers->ExposureTexture.Bind(1);
|
|
||||||
mBloomExtractShader->Bind(NOQUEUE);
|
|
||||||
mBloomExtractShader->Uniforms->Scale = screen->SceneScale();
|
|
||||||
mBloomExtractShader->Uniforms->Offset = screen->SceneOffset();
|
|
||||||
mBloomExtractShader->Uniforms.Set();
|
|
||||||
RenderScreenQuad();
|
|
||||||
|
|
||||||
// Blur and downscale:
|
|
||||||
for (int i = 0; i < FGLRenderBuffers::NumBloomLevels - 1; i++)
|
|
||||||
{
|
|
||||||
auto &level = mBuffers->BloomLevels[i];
|
|
||||||
auto &next = mBuffers->BloomLevels[i + 1];
|
|
||||||
RenderBlur(this, blurAmount, level.VTexture, level.HFramebuffer, level.Width, level.Height, false);
|
|
||||||
RenderBlur(this, blurAmount, level.HTexture, next.VFramebuffer, next.Width, next.Height, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blur and upscale:
|
|
||||||
for (int i = FGLRenderBuffers::NumBloomLevels - 1; i > 0; i--)
|
|
||||||
{
|
|
||||||
auto &level = mBuffers->BloomLevels[i];
|
|
||||||
auto &next = mBuffers->BloomLevels[i - 1];
|
|
||||||
|
|
||||||
RenderBlur(this, blurAmount, level.VTexture, level.HFramebuffer, level.Width, level.Height, false);
|
|
||||||
RenderBlur(this, blurAmount, level.HTexture, level.VFramebuffer, level.Width, level.Height, true);
|
|
||||||
|
|
||||||
// Linear upscale:
|
|
||||||
next.VFramebuffer.Bind();
|
|
||||||
glViewport(0, 0, next.Width, next.Height);
|
|
||||||
level.VTexture.Bind(0, GL_LINEAR);
|
|
||||||
mBloomCombineShader->Bind(NOQUEUE);
|
|
||||||
RenderScreenQuad();
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderBlur(this, blurAmount, level0.VTexture, level0.HFramebuffer, level0.Width, level0.Height, false);
|
|
||||||
RenderBlur(this, blurAmount, level0.HTexture, level0.VFramebuffer, level0.Width, level0.Height, true);
|
|
||||||
|
|
||||||
const auto &mSceneViewport = screen->mSceneViewport;
|
|
||||||
const auto &mScreenViewport = screen->mScreenViewport;
|
|
||||||
|
|
||||||
// Add bloom back to scene texture:
|
|
||||||
mBuffers->BindCurrentFB();
|
|
||||||
glViewport(mSceneViewport.left, mSceneViewport.top, mSceneViewport.width, mSceneViewport.height);
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
|
||||||
glBlendFunc(GL_ONE, GL_ONE);
|
|
||||||
level0.VTexture.Bind(0, GL_LINEAR);
|
|
||||||
mBloomCombineShader->Bind(NOQUEUE);
|
|
||||||
RenderScreenQuad();
|
|
||||||
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
|
|
||||||
|
|
||||||
FGLDebug::PopGroup();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Blur the scene
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void FGLRenderer::BlurScene(float gameinfobluramount)
|
void FGLRenderer::BlurScene(float gameinfobluramount)
|
||||||
{
|
{
|
||||||
// first, respect the CVar
|
if (mBuffers->GetSceneWidth() <= 0 || mBuffers->GetSceneHeight() <= 0)
|
||||||
float blurAmount = gl_menu_blur;
|
|
||||||
|
|
||||||
// if CVar is negative, use the gameinfo entry
|
|
||||||
if (gl_menu_blur < 0)
|
|
||||||
blurAmount = gameinfobluramount;
|
|
||||||
|
|
||||||
// if blurAmount == 0 or somehow still returns negative, exit to prevent a crash, clearly we don't want this
|
|
||||||
if (blurAmount <= 0.0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FGLDebug::PushGroup("BlurScene");
|
PPBloom blur;
|
||||||
|
blur.DeclareShaders();
|
||||||
FGLPostProcessState savedState;
|
blur.UpdateTextures(mBuffers->GetSceneWidth(), mBuffers->GetSceneHeight());
|
||||||
savedState.SaveTextureBindings(2);
|
blur.UpdateBlurSteps(gameinfobluramount);
|
||||||
|
mBuffers->RenderEffect("BlurScene");
|
||||||
int numLevels = 3; // Must be 4 or less (since FGLRenderBuffers::NumBloomLevels is 4 and we are using its buffers).
|
|
||||||
assert(numLevels <= FGLRenderBuffers::NumBloomLevels);
|
|
||||||
|
|
||||||
const auto &viewport = screen->mScreenViewport; // The area we want to blur. Could also be mSceneViewport if only the scene area is to be blured
|
|
||||||
|
|
||||||
const auto &level0 = mBuffers->BloomLevels[0];
|
|
||||||
|
|
||||||
// Grab the area we want to bloom:
|
|
||||||
mBuffers->BlitLinear(mBuffers->GetCurrentFB(), level0.VFramebuffer, viewport.left, viewport.top, viewport.width, viewport.height, 0, 0, level0.Width, level0.Height);
|
|
||||||
|
|
||||||
// Blur and downscale:
|
|
||||||
for (int i = 0; i < numLevels - 1; i++)
|
|
||||||
{
|
|
||||||
auto &level = mBuffers->BloomLevels[i];
|
|
||||||
auto &next = mBuffers->BloomLevels[i + 1];
|
|
||||||
RenderBlur(this, blurAmount, level.VTexture, level.HFramebuffer, level.Width, level.Height, false);
|
|
||||||
RenderBlur(this, blurAmount, level.HTexture, next.VFramebuffer, next.Width, next.Height, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blur and upscale:
|
|
||||||
for (int i = numLevels - 1; i > 0; i--)
|
|
||||||
{
|
|
||||||
auto &level = mBuffers->BloomLevels[i];
|
|
||||||
auto &next = mBuffers->BloomLevels[i - 1];
|
|
||||||
|
|
||||||
RenderBlur(this, blurAmount, level.VTexture, level.HFramebuffer, level.Width, level.Height, false);
|
|
||||||
RenderBlur(this, blurAmount, level.HTexture, level.VFramebuffer, level.Width, level.Height, true);
|
|
||||||
|
|
||||||
// Linear upscale:
|
|
||||||
next.VFramebuffer.Bind();
|
|
||||||
glViewport(0, 0, next.Width, next.Height);
|
|
||||||
level.VTexture.Bind(0, GL_LINEAR);
|
|
||||||
mBloomCombineShader->Bind(NOQUEUE);
|
|
||||||
RenderScreenQuad();
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderBlur(this, blurAmount, level0.VTexture, level0.HFramebuffer, level0.Width, level0.Height, false);
|
|
||||||
RenderBlur(this, blurAmount, level0.HTexture, level0.VFramebuffer, level0.Width, level0.Height, true);
|
|
||||||
|
|
||||||
// Copy blur back to scene texture:
|
|
||||||
mBuffers->BlitLinear(level0.VFramebuffer, mBuffers->GetCurrentFB(), 0, 0, level0.Width, level0.Height, viewport.left, viewport.top, viewport.width, viewport.height);
|
|
||||||
|
|
||||||
glViewport(viewport.left, viewport.top, viewport.width, viewport.height);
|
|
||||||
|
|
||||||
FGLDebug::PopGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Tonemap scene texture and place the result in the HUD/2D texture
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void FGLRenderer::TonemapScene()
|
void FGLRenderer::TonemapScene()
|
||||||
{
|
{
|
||||||
if (gl_tonemap == 0)
|
if (gl_tonemap == 0)
|
||||||
|
@ -650,7 +405,7 @@ void FGLRenderer::TonemapScene()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mBuffers->ExposureTexture.Bind(1);
|
//mBuffers->ExposureTexture.Bind(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
|
|
|
@ -58,8 +58,6 @@ FGLRenderBuffers::~FGLRenderBuffers()
|
||||||
ClearScene();
|
ClearScene();
|
||||||
ClearPipeline();
|
ClearPipeline();
|
||||||
ClearEyeBuffers();
|
ClearEyeBuffers();
|
||||||
ClearBloom();
|
|
||||||
ClearExposureLevels();
|
|
||||||
ClearAmbientOcclusion();
|
ClearAmbientOcclusion();
|
||||||
ClearShadowMap();
|
ClearShadowMap();
|
||||||
}
|
}
|
||||||
|
@ -93,31 +91,6 @@ void FGLRenderBuffers::ClearPipeline()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderBuffers::ClearBloom()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < NumBloomLevels; i++)
|
|
||||||
{
|
|
||||||
auto &level = BloomLevels[i];
|
|
||||||
DeleteFrameBuffer(level.HFramebuffer);
|
|
||||||
DeleteFrameBuffer(level.VFramebuffer);
|
|
||||||
DeleteTexture(level.HTexture);
|
|
||||||
DeleteTexture(level.VTexture);
|
|
||||||
level = FGLBloomTextureLevel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FGLRenderBuffers::ClearExposureLevels()
|
|
||||||
{
|
|
||||||
for (auto &level : ExposureLevels)
|
|
||||||
{
|
|
||||||
DeleteTexture(level.Texture);
|
|
||||||
DeleteFrameBuffer(level.Framebuffer);
|
|
||||||
}
|
|
||||||
ExposureLevels.Clear();
|
|
||||||
DeleteTexture(ExposureTexture);
|
|
||||||
DeleteFrameBuffer(ExposureFB);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FGLRenderBuffers::ClearEyeBuffers()
|
void FGLRenderBuffers::ClearEyeBuffers()
|
||||||
{
|
{
|
||||||
for (auto handle : mEyeFBs)
|
for (auto handle : mEyeFBs)
|
||||||
|
@ -198,8 +171,6 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
|
||||||
// Bloom bluring buffers need to match the scene to avoid bloom bleeding artifacts
|
// Bloom bluring buffers need to match the scene to avoid bloom bleeding artifacts
|
||||||
if (mSceneWidth != sceneWidth || mSceneHeight != sceneHeight)
|
if (mSceneWidth != sceneWidth || mSceneHeight != sceneHeight)
|
||||||
{
|
{
|
||||||
CreateBloom(sceneWidth, sceneHeight);
|
|
||||||
CreateExposureLevels(sceneWidth, sceneHeight);
|
|
||||||
CreateAmbientOcclusion(sceneWidth, sceneHeight);
|
CreateAmbientOcclusion(sceneWidth, sceneHeight);
|
||||||
mSceneWidth = sceneWidth;
|
mSceneWidth = sceneWidth;
|
||||||
mSceneHeight = sceneHeight;
|
mSceneHeight = sceneHeight;
|
||||||
|
@ -215,8 +186,6 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
|
||||||
ClearScene();
|
ClearScene();
|
||||||
ClearPipeline();
|
ClearPipeline();
|
||||||
ClearEyeBuffers();
|
ClearEyeBuffers();
|
||||||
ClearBloom();
|
|
||||||
ClearExposureLevels();
|
|
||||||
mWidth = 0;
|
mWidth = 0;
|
||||||
mHeight = 0;
|
mHeight = 0;
|
||||||
mSamples = 0;
|
mSamples = 0;
|
||||||
|
@ -294,38 +263,6 @@ void FGLRenderBuffers::CreatePipeline(int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// Creates bloom pass working buffers
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void FGLRenderBuffers::CreateBloom(int width, int height)
|
|
||||||
{
|
|
||||||
ClearBloom();
|
|
||||||
|
|
||||||
// No scene, no bloom!
|
|
||||||
if (width <= 0 || height <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int bloomWidth = (width + 1) / 2;
|
|
||||||
int bloomHeight = (height + 1) / 2;
|
|
||||||
for (int i = 0; i < NumBloomLevels; i++)
|
|
||||||
{
|
|
||||||
auto &level = BloomLevels[i];
|
|
||||||
level.Width = (bloomWidth + 1) / 2;
|
|
||||||
level.Height = (bloomHeight + 1) / 2;
|
|
||||||
|
|
||||||
level.VTexture = Create2DTexture("Bloom.VTexture", GL_RGBA16F, level.Width, level.Height);
|
|
||||||
level.HTexture = Create2DTexture("Bloom.HTexture", GL_RGBA16F, level.Width, level.Height);
|
|
||||||
level.VFramebuffer = CreateFrameBuffer("Bloom.VFramebuffer", level.VTexture);
|
|
||||||
level.HFramebuffer = CreateFrameBuffer("Bloom.HFramebuffer", level.HTexture);
|
|
||||||
|
|
||||||
bloomWidth = level.Width;
|
|
||||||
bloomHeight = level.Height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Creates ambient occlusion working buffers
|
// Creates ambient occlusion working buffers
|
||||||
|
@ -375,41 +312,6 @@ void FGLRenderBuffers::CreateAmbientOcclusion(int width, int height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// Creates camera exposure level buffers
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void FGLRenderBuffers::CreateExposureLevels(int width, int height)
|
|
||||||
{
|
|
||||||
ClearExposureLevels();
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
width = MAX(width / 2, 1);
|
|
||||||
height = MAX(height / 2, 1);
|
|
||||||
|
|
||||||
FString textureName, fbName;
|
|
||||||
textureName.Format("Exposure.Texture%d", i);
|
|
||||||
fbName.Format("Exposure.Framebuffer%d", i);
|
|
||||||
i++;
|
|
||||||
|
|
||||||
FGLExposureTextureLevel level;
|
|
||||||
level.Width = width;
|
|
||||||
level.Height = height;
|
|
||||||
level.Texture = Create2DTexture(textureName.GetChars(), GL_R32F, level.Width, level.Height);
|
|
||||||
level.Framebuffer = CreateFrameBuffer(fbName.GetChars(), level.Texture);
|
|
||||||
ExposureLevels.Push(level);
|
|
||||||
} while (width > 1 || height > 1);
|
|
||||||
|
|
||||||
ExposureTexture = Create2DTexture("Exposure.CameraTexture", GL_R32F, 1, 1);
|
|
||||||
ExposureFB = CreateFrameBuffer("Exposure.CameraFB", ExposureTexture);
|
|
||||||
|
|
||||||
FirstExposureFrame = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Creates eye buffers if needed
|
// Creates eye buffers if needed
|
||||||
|
|
|
@ -54,26 +54,6 @@ private:
|
||||||
friend class FGLRenderBuffers;
|
friend class FGLRenderBuffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FGLBloomTextureLevel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PPTexture VTexture;
|
|
||||||
PPFrameBuffer VFramebuffer;
|
|
||||||
PPTexture HTexture;
|
|
||||||
PPFrameBuffer HFramebuffer;
|
|
||||||
int Width = 0;
|
|
||||||
int Height = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FGLExposureTextureLevel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PPTexture Texture;
|
|
||||||
PPFrameBuffer Framebuffer;
|
|
||||||
int Width = 0;
|
|
||||||
int Height = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FShaderProgram;
|
class FShaderProgram;
|
||||||
|
|
||||||
class FGLRenderBuffers
|
class FGLRenderBuffers
|
||||||
|
@ -115,14 +95,6 @@ public:
|
||||||
void BindShadowMapFB();
|
void BindShadowMapFB();
|
||||||
void BindShadowMapTexture(int index);
|
void BindShadowMapTexture(int index);
|
||||||
|
|
||||||
enum { NumBloomLevels = 4 };
|
|
||||||
FGLBloomTextureLevel BloomLevels[NumBloomLevels];
|
|
||||||
|
|
||||||
TArray<FGLExposureTextureLevel> ExposureLevels;
|
|
||||||
PPTexture ExposureTexture;
|
|
||||||
PPFrameBuffer ExposureFB;
|
|
||||||
bool FirstExposureFrame = true;
|
|
||||||
|
|
||||||
// Ambient occlusion buffers
|
// Ambient occlusion buffers
|
||||||
PPTexture LinearDepthTexture;
|
PPTexture LinearDepthTexture;
|
||||||
PPFrameBuffer LinearDepthFB;
|
PPFrameBuffer LinearDepthFB;
|
||||||
|
@ -147,14 +119,10 @@ private:
|
||||||
void ClearScene();
|
void ClearScene();
|
||||||
void ClearPipeline();
|
void ClearPipeline();
|
||||||
void ClearEyeBuffers();
|
void ClearEyeBuffers();
|
||||||
void ClearBloom();
|
|
||||||
void ClearExposureLevels();
|
|
||||||
void ClearAmbientOcclusion();
|
void ClearAmbientOcclusion();
|
||||||
void ClearShadowMap();
|
void ClearShadowMap();
|
||||||
void CreateScene(int width, int height, int samples, bool needsSceneTextures);
|
void CreateScene(int width, int height, int samples, bool needsSceneTextures);
|
||||||
void CreatePipeline(int width, int height);
|
void CreatePipeline(int width, int height);
|
||||||
void CreateBloom(int width, int height);
|
|
||||||
void CreateExposureLevels(int width, int height);
|
|
||||||
void CreateEyeBuffers(int eye);
|
void CreateEyeBuffers(int eye);
|
||||||
void CreateShadowMap();
|
void CreateShadowMap();
|
||||||
void CreateAmbientOcclusion(int width, int height);
|
void CreateAmbientOcclusion(int width, int height);
|
||||||
|
|
|
@ -51,8 +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_bloomshader.h"
|
|
||||||
#include "hwrenderer/postprocessing/hw_blurshader.h"
|
|
||||||
#include "hwrenderer/postprocessing/hw_tonemapshader.h"
|
#include "hwrenderer/postprocessing/hw_tonemapshader.h"
|
||||||
#include "hwrenderer/postprocessing/hw_colormapshader.h"
|
#include "hwrenderer/postprocessing/hw_colormapshader.h"
|
||||||
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
||||||
|
@ -101,12 +99,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
|
||||||
mPresent3dCheckerShader = nullptr;
|
mPresent3dCheckerShader = nullptr;
|
||||||
mPresent3dColumnShader = nullptr;
|
mPresent3dColumnShader = nullptr;
|
||||||
mPresent3dRowShader = nullptr;
|
mPresent3dRowShader = nullptr;
|
||||||
mBloomExtractShader = nullptr;
|
|
||||||
mBloomCombineShader = nullptr;
|
|
||||||
mExposureExtractShader = nullptr;
|
|
||||||
mExposureAverageShader = nullptr;
|
|
||||||
mExposureCombineShader = nullptr;
|
|
||||||
mBlurShader = nullptr;
|
|
||||||
mTonemapShader = nullptr;
|
mTonemapShader = nullptr;
|
||||||
mTonemapPalette = nullptr;
|
mTonemapPalette = nullptr;
|
||||||
mColormapShader = nullptr;
|
mColormapShader = nullptr;
|
||||||
|
@ -127,12 +119,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();
|
||||||
mBloomExtractShader = new FBloomExtractShader();
|
|
||||||
mBloomCombineShader = new FBloomCombineShader();
|
|
||||||
mExposureExtractShader = new FExposureExtractShader();
|
|
||||||
mExposureAverageShader = new FExposureAverageShader();
|
|
||||||
mExposureCombineShader = new FExposureCombineShader();
|
|
||||||
mBlurShader = new FBlurShader();
|
|
||||||
mTonemapShader = new FTonemapShader();
|
mTonemapShader = new FTonemapShader();
|
||||||
mColormapShader = new FColormapShader();
|
mColormapShader = new FColormapShader();
|
||||||
mTonemapPalette = nullptr;
|
mTonemapPalette = nullptr;
|
||||||
|
@ -190,12 +176,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 (mBloomExtractShader) delete mBloomExtractShader;
|
|
||||||
if (mBloomCombineShader) delete mBloomCombineShader;
|
|
||||||
if (mExposureExtractShader) delete mExposureExtractShader;
|
|
||||||
if (mExposureAverageShader) delete mExposureAverageShader;
|
|
||||||
if (mExposureCombineShader) delete mExposureCombineShader;
|
|
||||||
if (mBlurShader) delete mBlurShader;
|
|
||||||
if (mTonemapShader) delete mTonemapShader;
|
if (mTonemapShader) delete mTonemapShader;
|
||||||
if (mTonemapPalette) delete mTonemapPalette;
|
if (mTonemapPalette) delete mTonemapPalette;
|
||||||
if (mColormapShader) delete mColormapShader;
|
if (mColormapShader) delete mColormapShader;
|
||||||
|
|
|
@ -29,12 +29,6 @@ class FLinearDepthShader;
|
||||||
class FDepthBlurShader;
|
class FDepthBlurShader;
|
||||||
class FSSAOShader;
|
class FSSAOShader;
|
||||||
class FSSAOCombineShader;
|
class FSSAOCombineShader;
|
||||||
class FBloomExtractShader;
|
|
||||||
class FBloomCombineShader;
|
|
||||||
class FExposureExtractShader;
|
|
||||||
class FExposureAverageShader;
|
|
||||||
class FExposureCombineShader;
|
|
||||||
class FBlurShader;
|
|
||||||
class FTonemapShader;
|
class FTonemapShader;
|
||||||
class FColormapShader;
|
class FColormapShader;
|
||||||
class FPresentShader;
|
class FPresentShader;
|
||||||
|
@ -81,12 +75,6 @@ public:
|
||||||
FSSAOShader *mSSAOShader;
|
FSSAOShader *mSSAOShader;
|
||||||
FDepthBlurShader *mDepthBlurShader;
|
FDepthBlurShader *mDepthBlurShader;
|
||||||
FSSAOCombineShader *mSSAOCombineShader;
|
FSSAOCombineShader *mSSAOCombineShader;
|
||||||
FBloomExtractShader *mBloomExtractShader;
|
|
||||||
FBloomCombineShader *mBloomCombineShader;
|
|
||||||
FExposureExtractShader *mExposureExtractShader;
|
|
||||||
FExposureAverageShader *mExposureAverageShader;
|
|
||||||
FExposureCombineShader *mExposureCombineShader;
|
|
||||||
FBlurShader *mBlurShader;
|
|
||||||
FTonemapShader *mTonemapShader;
|
FTonemapShader *mTonemapShader;
|
||||||
FColormapShader *mColormapShader;
|
FColormapShader *mColormapShader;
|
||||||
FHardwareTexture *mTonemapPalette;
|
FHardwareTexture *mTonemapPalette;
|
||||||
|
|
|
@ -1,57 +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_bloomshader.cpp
|
|
||||||
** Shaders used to do bloom
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "v_video.h"
|
|
||||||
#include "hw_bloomshader.h"
|
|
||||||
|
|
||||||
void FBloomExtractShader::Bind(IRenderQueue *q)
|
|
||||||
{
|
|
||||||
if (!mShader)
|
|
||||||
{
|
|
||||||
FString prolog = Uniforms.CreateDeclaration("Uniforms", UniformBlock::Desc());
|
|
||||||
|
|
||||||
mShader.reset(screen->CreateShaderProgram());
|
|
||||||
mShader->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
|
|
||||||
mShader->Compile(IShaderProgram::Fragment, "shaders/glsl/bloomextract.fp", prolog, 330);
|
|
||||||
mShader->Link("shaders/glsl/bloomextract");
|
|
||||||
mShader->SetUniformBufferLocation(Uniforms.BindingPoint(), "Uniforms");
|
|
||||||
Uniforms.Init();
|
|
||||||
}
|
|
||||||
mShader->Bind(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FBloomCombineShader::Bind(IRenderQueue *q)
|
|
||||||
{
|
|
||||||
if (!mShader)
|
|
||||||
{
|
|
||||||
mShader.reset(screen->CreateShaderProgram());
|
|
||||||
mShader->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
|
|
||||||
mShader->Compile(IShaderProgram::Fragment, "shaders/glsl/bloomcombine.fp", "", 330);
|
|
||||||
mShader->Link("shaders/glsl/bloomcombine");
|
|
||||||
}
|
|
||||||
mShader->Bind(q);
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
#ifndef __GL_BLOOMSHADER_H
|
|
||||||
#define __GL_BLOOMSHADER_H
|
|
||||||
|
|
||||||
#include "hwrenderer/postprocessing/hw_shaderprogram.h"
|
|
||||||
|
|
||||||
class FBloomExtractShader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Bind(IRenderQueue *q);
|
|
||||||
|
|
||||||
struct UniformBlock
|
|
||||||
{
|
|
||||||
FVector2 Scale;
|
|
||||||
FVector2 Offset;
|
|
||||||
|
|
||||||
static std::vector<UniformFieldDesc> Desc()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
|
||||||
{ "Scale", UniformType::Vec2, offsetof(UniformBlock, Scale) },
|
|
||||||
{ "Offset", UniformType::Vec2, offsetof(UniformBlock, Offset) }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ShaderUniforms<UniformBlock, POSTPROCESS_BINDINGPOINT> Uniforms;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<IShaderProgram> mShader;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FBloomCombineShader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Bind(IRenderQueue *q);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<IShaderProgram> mShader;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,50 +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_blurshader.cpp
|
|
||||||
** Gaussian blur shader
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "v_video.h"
|
|
||||||
#include "hw_blurshader.h"
|
|
||||||
|
|
||||||
void FBlurShader::Bind(IRenderQueue *q, bool vertical)
|
|
||||||
{
|
|
||||||
if (!mShader[vertical])
|
|
||||||
{
|
|
||||||
FString prolog = Uniforms[vertical].CreateDeclaration("Uniforms", UniformBlock::Desc());
|
|
||||||
if (vertical)
|
|
||||||
prolog += "#define BLUR_VERTICAL\n";
|
|
||||||
else
|
|
||||||
prolog += "#define BLUR_HORIZONTAL\n";
|
|
||||||
|
|
||||||
mShader[vertical].reset(screen->CreateShaderProgram());
|
|
||||||
mShader[vertical]->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
|
|
||||||
mShader[vertical]->Compile(IShaderProgram::Fragment, "shaders/glsl/blur.fp", prolog, 330);
|
|
||||||
mShader[vertical]->Link("shaders/glsl/blur");
|
|
||||||
mShader[vertical]->SetUniformBufferLocation(POSTPROCESS_BINDINGPOINT, "Uniforms");
|
|
||||||
Uniforms[vertical].Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
mShader[vertical]->Bind(q);
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hwrenderer/postprocessing/hw_shaderprogram.h"
|
|
||||||
|
|
||||||
class FGLRenderer;
|
|
||||||
class PPFrameBuffer;
|
|
||||||
class PPTexture;
|
|
||||||
|
|
||||||
class FBlurShader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Bind(IRenderQueue *q, bool vertical);
|
|
||||||
|
|
||||||
struct UniformBlock
|
|
||||||
{
|
|
||||||
float SampleWeights[8];
|
|
||||||
|
|
||||||
static std::vector<UniformFieldDesc> Desc()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
|
||||||
{ "SampleWeights0", UniformType::Float, offsetof(UniformBlock, SampleWeights[0]) },
|
|
||||||
{ "SampleWeights1", UniformType::Float, offsetof(UniformBlock, SampleWeights[1]) },
|
|
||||||
{ "SampleWeights2", UniformType::Float, offsetof(UniformBlock, SampleWeights[2]) },
|
|
||||||
{ "SampleWeights3", UniformType::Float, offsetof(UniformBlock, SampleWeights[3]) },
|
|
||||||
{ "SampleWeights4", UniformType::Float, offsetof(UniformBlock, SampleWeights[4]) },
|
|
||||||
{ "SampleWeights5", UniformType::Float, offsetof(UniformBlock, SampleWeights[5]) },
|
|
||||||
{ "SampleWeights6", UniformType::Float, offsetof(UniformBlock, SampleWeights[6]) },
|
|
||||||
{ "SampleWeights7", UniformType::Float, offsetof(UniformBlock, SampleWeights[7]) },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ShaderUniforms<UniformBlock, POSTPROCESS_BINDINGPOINT> Uniforms[2];
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<IShaderProgram> mShader[2];
|
|
||||||
};
|
|
|
@ -61,11 +61,11 @@ void PPBloom::UpdateSteps(int fixedcm)
|
||||||
auto &level0 = levels[0];
|
auto &level0 = levels[0];
|
||||||
|
|
||||||
// Extract blooming pixels from scene texture:
|
// Extract blooming pixels from scene texture:
|
||||||
step.Viewport = level0.Viewport;
|
|
||||||
step.SetInputCurrent(0, PPFilterMode::Linear);
|
|
||||||
step.SetInputTexture(1, "ExposureTexture");
|
|
||||||
step.ShaderName = "BloomExtract";
|
step.ShaderName = "BloomExtract";
|
||||||
step.Uniforms.Set(extractUniforms);
|
step.Uniforms.Set(extractUniforms);
|
||||||
|
step.Viewport = level0.Viewport;
|
||||||
|
step.SetInputCurrent(0, PPFilterMode::Linear);
|
||||||
|
step.SetInputTexture(1, "Exposure.CameraTexture");
|
||||||
step.SetOutputTexture(level0.VTexture);
|
step.SetOutputTexture(level0.VTexture);
|
||||||
step.SetNoBlend();
|
step.SetNoBlend();
|
||||||
steps.Push(step);
|
steps.Push(step);
|
||||||
|
@ -93,10 +93,12 @@ void PPBloom::UpdateSteps(int fixedcm)
|
||||||
steps.Push(BlurStep(blurUniforms, level.HTexture, level.VTexture, level.Viewport, true));
|
steps.Push(BlurStep(blurUniforms, level.HTexture, level.VTexture, level.Viewport, true));
|
||||||
|
|
||||||
// Linear upscale:
|
// Linear upscale:
|
||||||
step.SetInputTexture(0, next.VTexture, PPFilterMode::Linear);
|
|
||||||
step.SetOutputTexture(next.HTexture);
|
|
||||||
step.Viewport = next.Viewport;
|
|
||||||
step.ShaderName = "BloomCombine";
|
step.ShaderName = "BloomCombine";
|
||||||
|
step.Uniforms.Clear();
|
||||||
|
step.Viewport = next.Viewport;
|
||||||
|
step.SetInputTexture(0, level.VTexture, PPFilterMode::Linear);
|
||||||
|
step.SetOutputTexture(next.VTexture);
|
||||||
|
step.SetNoBlend();
|
||||||
steps.Push(step);
|
steps.Push(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,23 +106,103 @@ void PPBloom::UpdateSteps(int fixedcm)
|
||||||
steps.Push(BlurStep(blurUniforms, level0.HTexture, level0.VTexture, level0.Viewport, true));
|
steps.Push(BlurStep(blurUniforms, level0.HTexture, level0.VTexture, level0.Viewport, true));
|
||||||
|
|
||||||
// Add bloom back to scene texture:
|
// Add bloom back to scene texture:
|
||||||
|
step.ShaderName = "BloomCombine";
|
||||||
|
step.Uniforms.Clear();
|
||||||
|
step.Viewport = screen->mSceneViewport;
|
||||||
step.SetInputTexture(0, level0.VTexture, PPFilterMode::Linear);
|
step.SetInputTexture(0, level0.VTexture, PPFilterMode::Linear);
|
||||||
step.SetOutputCurrent();
|
step.SetOutputCurrent();
|
||||||
step.Viewport = screen->mSceneViewport;
|
|
||||||
step.ShaderName = "BloomCombine";
|
|
||||||
step.SetAdditiveBlend();
|
step.SetAdditiveBlend();
|
||||||
steps.Push(step);
|
steps.Push(step);
|
||||||
|
|
||||||
hw_postprocess.Effects["BloomScene"] = steps;
|
hw_postprocess.Effects["BloomScene"] = steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PPBloom::UpdateBlurSteps(float gameinfobluramount)
|
||||||
|
{
|
||||||
|
// first, respect the CVar
|
||||||
|
float blurAmount = gl_menu_blur;
|
||||||
|
|
||||||
|
// if CVar is negative, use the gameinfo entry
|
||||||
|
if (gl_menu_blur < 0)
|
||||||
|
blurAmount = gameinfobluramount;
|
||||||
|
|
||||||
|
// if blurAmount == 0 or somehow still returns negative, exit to prevent a crash, clearly we don't want this
|
||||||
|
if (blurAmount <= 0.0)
|
||||||
|
{
|
||||||
|
hw_postprocess.Effects["BlurScene"] = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<PPStep> steps;
|
||||||
|
PPStep step;
|
||||||
|
|
||||||
|
int numLevels = 3;
|
||||||
|
assert(numLevels <= NumBloomLevels);
|
||||||
|
|
||||||
|
const auto &level0 = levels[0];
|
||||||
|
|
||||||
|
// Grab the area we want to bloom:
|
||||||
|
step.ShaderName = "BloomCombine";
|
||||||
|
step.Uniforms.Clear();
|
||||||
|
step.Viewport = level0.Viewport;
|
||||||
|
step.SetInputCurrent(0, PPFilterMode::Linear);
|
||||||
|
step.SetOutputTexture(level0.VTexture);
|
||||||
|
step.SetNoBlend();
|
||||||
|
steps.Push(step);
|
||||||
|
|
||||||
|
BlurUniforms blurUniforms;
|
||||||
|
ComputeBlurSamples(7, blurAmount, blurUniforms.SampleWeights);
|
||||||
|
|
||||||
|
// Blur and downscale:
|
||||||
|
for (int i = 0; i < numLevels - 1; i++)
|
||||||
|
{
|
||||||
|
auto &level = levels[i];
|
||||||
|
auto &next = levels[i + 1];
|
||||||
|
steps.Push(BlurStep(blurUniforms, level.VTexture, level.HTexture, level.Viewport, false));
|
||||||
|
steps.Push(BlurStep(blurUniforms, level.HTexture, next.VTexture, next.Viewport, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blur and upscale:
|
||||||
|
for (int i = numLevels - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
auto &level = levels[i];
|
||||||
|
auto &next = levels[i - 1];
|
||||||
|
|
||||||
|
steps.Push(BlurStep(blurUniforms, level.VTexture, level.HTexture, level.Viewport, false));
|
||||||
|
steps.Push(BlurStep(blurUniforms, level.HTexture, level.VTexture, level.Viewport, true));
|
||||||
|
|
||||||
|
// Linear upscale:
|
||||||
|
step.ShaderName = "BloomCombine";
|
||||||
|
step.Uniforms.Clear();
|
||||||
|
step.Viewport = next.Viewport;
|
||||||
|
step.SetInputTexture(0, level.VTexture, PPFilterMode::Linear);
|
||||||
|
step.SetOutputTexture(next.VTexture);
|
||||||
|
step.SetNoBlend();
|
||||||
|
steps.Push(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
steps.Push(BlurStep(blurUniforms, level0.VTexture, level0.HTexture, level0.Viewport, false));
|
||||||
|
steps.Push(BlurStep(blurUniforms, level0.HTexture, level0.VTexture, level0.Viewport, true));
|
||||||
|
|
||||||
|
// Copy blur back to scene texture:
|
||||||
|
step.ShaderName = "BloomCombine";
|
||||||
|
step.Uniforms.Clear();
|
||||||
|
step.Viewport = screen->mScreenViewport;
|
||||||
|
step.SetInputTexture(0, level0.VTexture, PPFilterMode::Linear);
|
||||||
|
step.SetOutputCurrent();
|
||||||
|
step.SetNoBlend();
|
||||||
|
steps.Push(step);
|
||||||
|
|
||||||
|
hw_postprocess.Effects["BlurScene"] = steps;
|
||||||
|
}
|
||||||
|
|
||||||
PPStep PPBloom::BlurStep(const BlurUniforms &blurUniforms, PPTextureName input, PPTextureName output, PPViewport viewport, bool vertical)
|
PPStep PPBloom::BlurStep(const BlurUniforms &blurUniforms, PPTextureName input, PPTextureName output, PPViewport viewport, bool vertical)
|
||||||
{
|
{
|
||||||
PPStep step;
|
PPStep step;
|
||||||
step.Viewport = viewport;
|
|
||||||
step.SetInputTexture(0, input);
|
|
||||||
step.ShaderName = vertical ? "BlurVertical" : "BlurHorizontal";
|
step.ShaderName = vertical ? "BlurVertical" : "BlurHorizontal";
|
||||||
step.Uniforms.Set(blurUniforms);
|
step.Uniforms.Set(blurUniforms);
|
||||||
|
step.Viewport = viewport;
|
||||||
|
step.SetInputTexture(0, input);
|
||||||
step.SetOutputTexture(output);
|
step.SetOutputTexture(output);
|
||||||
step.SetNoBlend();
|
step.SetNoBlend();
|
||||||
return step;
|
return step;
|
||||||
|
@ -202,12 +284,12 @@ void PPLensDistort::UpdateSteps()
|
||||||
TArray<PPStep> steps;
|
TArray<PPStep> steps;
|
||||||
|
|
||||||
PPStep step;
|
PPStep step;
|
||||||
|
step.ShaderName = "Lens";
|
||||||
|
step.Uniforms.Set(uniforms);
|
||||||
|
step.Viewport = screen->mScreenViewport;
|
||||||
step.SetInputCurrent(0, PPFilterMode::Linear);
|
step.SetInputCurrent(0, PPFilterMode::Linear);
|
||||||
step.SetOutputNext();
|
step.SetOutputNext();
|
||||||
step.SetNoBlend();
|
step.SetNoBlend();
|
||||||
step.Uniforms.Set(uniforms);
|
|
||||||
step.Viewport = screen->mScreenViewport;
|
|
||||||
step.ShaderName = "Lens";
|
|
||||||
steps.Push(step);
|
steps.Push(step);
|
||||||
|
|
||||||
hw_postprocess.Effects["LensDistortScene"] = steps;
|
hw_postprocess.Effects["LensDistortScene"] = steps;
|
||||||
|
@ -235,16 +317,20 @@ void PPFXAA::UpdateSteps()
|
||||||
TArray<PPStep> steps;
|
TArray<PPStep> steps;
|
||||||
|
|
||||||
PPStep step;
|
PPStep step;
|
||||||
|
step.ShaderName = "FXAALuma";
|
||||||
|
step.Uniforms.Clear();
|
||||||
|
step.Viewport = screen->mScreenViewport;
|
||||||
step.SetInputCurrent(0, PPFilterMode::Nearest);
|
step.SetInputCurrent(0, PPFilterMode::Nearest);
|
||||||
step.SetOutputNext();
|
step.SetOutputNext();
|
||||||
step.SetNoBlend();
|
step.SetNoBlend();
|
||||||
step.Viewport = screen->mScreenViewport;
|
|
||||||
step.ShaderName = "FXAALuma";
|
|
||||||
steps.Push(step);
|
steps.Push(step);
|
||||||
|
|
||||||
step.SetInputCurrent(0, PPFilterMode::Linear);
|
|
||||||
step.Uniforms.Set(uniforms);
|
|
||||||
step.ShaderName = "FXAA";
|
step.ShaderName = "FXAA";
|
||||||
|
step.Uniforms.Set(uniforms);
|
||||||
|
step.Viewport = screen->mScreenViewport;
|
||||||
|
step.SetInputCurrent(0, PPFilterMode::Linear);
|
||||||
|
step.SetOutputNext();
|
||||||
|
step.SetNoBlend();
|
||||||
steps.Push(step);
|
steps.Push(step);
|
||||||
|
|
||||||
hw_postprocess.Effects["ApplyFXAA"] = steps;
|
hw_postprocess.Effects["ApplyFXAA"] = steps;
|
||||||
|
@ -281,3 +367,114 @@ FString PPFXAA::GetDefines()
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void PPCameraExposure::DeclareShaders()
|
||||||
|
{
|
||||||
|
hw_postprocess.Shaders["ExposureExtract"] = { "shaders/glsl/exposureextract.fp", "", ExposureExtractUniforms::Desc() };
|
||||||
|
hw_postprocess.Shaders["ExposureAverage"] = { "shaders/glsl/exposureaverage.fp", "", {}, 400 };
|
||||||
|
hw_postprocess.Shaders["ExposureCombine"] = { "shaders/glsl/exposurecombine.fp", "", ExposureCombineUniforms::Desc() };
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPCameraExposure::UpdateTextures(int width, int height)
|
||||||
|
{
|
||||||
|
if (ExposureLevels.Size() > 0 && ExposureLevels[0].Viewport.width == width && ExposureLevels[0].Viewport.height == height)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExposureLevels.Clear();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
width = MAX(width / 2, 1);
|
||||||
|
height = MAX(height / 2, 1);
|
||||||
|
|
||||||
|
PPExposureLevel level;
|
||||||
|
level.Viewport.left = 0;
|
||||||
|
level.Viewport.top = 0;
|
||||||
|
level.Viewport.width = width;
|
||||||
|
level.Viewport.height = height;
|
||||||
|
level.Texture.Format("Exposure.Level.%d", i);
|
||||||
|
ExposureLevels.Push(level);
|
||||||
|
|
||||||
|
PPTextureDesc texture = { level.Viewport.width, level.Viewport.height, PixelFormat::R32f };
|
||||||
|
hw_postprocess.Textures[level.Texture] = texture;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
} while (width > 1 || height > 1);
|
||||||
|
|
||||||
|
hw_postprocess.Textures["Exposure.CameraTexture"] = { 1, 1, PixelFormat::R32f };
|
||||||
|
|
||||||
|
FirstExposureFrame = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPCameraExposure::UpdateSteps()
|
||||||
|
{
|
||||||
|
if (!gl_bloom && gl_tonemap == 0)
|
||||||
|
{
|
||||||
|
hw_postprocess.Effects["UpdateCameraExposure"] = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<PPStep> steps;
|
||||||
|
PPStep step;
|
||||||
|
|
||||||
|
ExposureExtractUniforms extractUniforms;
|
||||||
|
extractUniforms.Scale = screen->SceneScale();
|
||||||
|
extractUniforms.Offset = screen->SceneOffset();
|
||||||
|
|
||||||
|
ExposureCombineUniforms combineUniforms;
|
||||||
|
combineUniforms.ExposureBase = gl_exposure_base;
|
||||||
|
combineUniforms.ExposureMin = gl_exposure_min;
|
||||||
|
combineUniforms.ExposureScale = gl_exposure_scale;
|
||||||
|
combineUniforms.ExposureSpeed = gl_exposure_speed;
|
||||||
|
|
||||||
|
auto &level0 = ExposureLevels[0];
|
||||||
|
|
||||||
|
// Extract light level from scene texture:
|
||||||
|
step.ShaderName = "ExposureExtract";
|
||||||
|
step.Uniforms.Set(extractUniforms);
|
||||||
|
step.Viewport = level0.Viewport;
|
||||||
|
step.SetInputCurrent(0, PPFilterMode::Linear);
|
||||||
|
step.SetOutputTexture(level0.Texture);
|
||||||
|
step.SetNoBlend();
|
||||||
|
steps.Push(step);
|
||||||
|
|
||||||
|
// Find the average value:
|
||||||
|
for (unsigned int i = 0; i + 1 < ExposureLevels.Size(); i++)
|
||||||
|
{
|
||||||
|
auto &level = ExposureLevels[i];
|
||||||
|
auto &next = ExposureLevels[i + 1];
|
||||||
|
|
||||||
|
step.ShaderName = "ExposureAverage";
|
||||||
|
step.Uniforms.Clear();
|
||||||
|
step.Viewport = next.Viewport;
|
||||||
|
step.SetInputTexture(0, level.Texture, PPFilterMode::Linear);
|
||||||
|
step.SetOutputTexture(next.Texture);
|
||||||
|
step.SetNoBlend();
|
||||||
|
steps.Push(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine average value with current camera exposure:
|
||||||
|
step.ShaderName = "ExposureCombine";
|
||||||
|
step.Uniforms.Set(combineUniforms);
|
||||||
|
step.Viewport.left = 0;
|
||||||
|
step.Viewport.top = 0;
|
||||||
|
step.Viewport.width = 1;
|
||||||
|
step.Viewport.height = 1;
|
||||||
|
step.SetInputTexture(0, ExposureLevels.Last().Texture, PPFilterMode::Linear);
|
||||||
|
step.SetOutputTexture("Exposure.CameraTexture");
|
||||||
|
if (!FirstExposureFrame)
|
||||||
|
step.SetAlphaBlend();
|
||||||
|
else
|
||||||
|
step.SetNoBlend();
|
||||||
|
steps.Push(step);
|
||||||
|
|
||||||
|
FirstExposureFrame = false;
|
||||||
|
|
||||||
|
hw_postprocess.Effects["UpdateCameraExposure"] = steps;
|
||||||
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
|
|
||||||
~PPUniforms()
|
~PPUniforms()
|
||||||
{
|
{
|
||||||
delete[] Data;
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
PPUniforms &operator=(const PPUniforms &src)
|
PPUniforms &operator=(const PPUniforms &src)
|
||||||
|
@ -69,6 +69,13 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
delete[] Data;
|
||||||
|
Data = nullptr;
|
||||||
|
Size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Set(const T &v)
|
void Set(const T &v)
|
||||||
{
|
{
|
||||||
|
@ -145,6 +152,14 @@ public:
|
||||||
BlendMode.Flags = 0;
|
BlendMode.Flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetAlphaBlend()
|
||||||
|
{
|
||||||
|
BlendMode.BlendOp = STYLEOP_Add;
|
||||||
|
BlendMode.SrcAlpha = STYLEALPHA_Src;
|
||||||
|
BlendMode.DestAlpha = STYLEALPHA_InvSrc;
|
||||||
|
BlendMode.Flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
PPShaderName ShaderName;
|
PPShaderName ShaderName;
|
||||||
TArray<PPTextureInput> Textures;
|
TArray<PPTextureInput> Textures;
|
||||||
PPUniforms Uniforms;
|
PPUniforms Uniforms;
|
||||||
|
@ -156,7 +171,8 @@ public:
|
||||||
enum class PixelFormat
|
enum class PixelFormat
|
||||||
{
|
{
|
||||||
Rgba8,
|
Rgba8,
|
||||||
Rgba16f
|
Rgba16f,
|
||||||
|
R32f
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPTextureDesc
|
class PPTextureDesc
|
||||||
|
@ -246,6 +262,7 @@ public:
|
||||||
void DeclareShaders();
|
void DeclareShaders();
|
||||||
void UpdateTextures(int sceneWidth, int sceneHeight);
|
void UpdateTextures(int sceneWidth, int sceneHeight);
|
||||||
void UpdateSteps(int fixedcm);
|
void UpdateSteps(int fixedcm);
|
||||||
|
void UpdateBlurSteps(float gameinfobluramount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PPStep BlurStep(const BlurUniforms &blurUniforms, PPTextureName input, PPTextureName output, PPViewport viewport, bool vertical);
|
PPStep BlurStep(const BlurUniforms &blurUniforms, PPTextureName input, PPTextureName output, PPViewport viewport, bool vertical);
|
||||||
|
@ -315,3 +332,58 @@ private:
|
||||||
int GetMaxVersion();
|
int GetMaxVersion();
|
||||||
FString GetDefines();
|
FString GetDefines();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct ExposureExtractUniforms
|
||||||
|
{
|
||||||
|
FVector2 Scale;
|
||||||
|
FVector2 Offset;
|
||||||
|
|
||||||
|
static std::vector<UniformFieldDesc> Desc()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
{
|
||||||
|
{ "Scale", UniformType::Vec2, offsetof(ExposureExtractUniforms, Scale) },
|
||||||
|
{ "Offset", UniformType::Vec2, offsetof(ExposureExtractUniforms, Offset) }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExposureCombineUniforms
|
||||||
|
{
|
||||||
|
float ExposureBase;
|
||||||
|
float ExposureMin;
|
||||||
|
float ExposureScale;
|
||||||
|
float ExposureSpeed;
|
||||||
|
|
||||||
|
static std::vector<UniformFieldDesc> Desc()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
{
|
||||||
|
{ "ExposureBase", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureBase) },
|
||||||
|
{ "ExposureMin", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureMin) },
|
||||||
|
{ "ExposureScale", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureScale) },
|
||||||
|
{ "ExposureSpeed", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureSpeed) }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PPExposureLevel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PPViewport Viewport;
|
||||||
|
PPTextureName Texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PPCameraExposure
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void DeclareShaders();
|
||||||
|
void UpdateTextures(int sceneWidth, int sceneHeight);
|
||||||
|
void UpdateSteps();
|
||||||
|
|
||||||
|
private:
|
||||||
|
TArray<PPExposureLevel> ExposureLevels;
|
||||||
|
bool FirstExposureFrame = true;
|
||||||
|
};
|
||||||
|
|
|
@ -61,47 +61,3 @@ const char *FTonemapShader::GetDefines(int mode)
|
||||||
case Palette: return "#define PALETTE\n";
|
case Palette: return "#define PALETTE\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FExposureExtractShader::Bind(IRenderQueue *q)
|
|
||||||
{
|
|
||||||
if (!mShader)
|
|
||||||
{
|
|
||||||
FString prolog = Uniforms.CreateDeclaration("Uniforms", UniformBlock::Desc());
|
|
||||||
|
|
||||||
mShader.reset(screen->CreateShaderProgram());
|
|
||||||
mShader->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
|
|
||||||
mShader->Compile(IShaderProgram::Fragment, "shaders/glsl/exposureextract.fp", prolog, 330);
|
|
||||||
mShader->Link("shaders/glsl/exposureextract");
|
|
||||||
mShader->SetUniformBufferLocation(Uniforms.BindingPoint(), "Uniforms");
|
|
||||||
Uniforms.Init();
|
|
||||||
}
|
|
||||||
mShader->Bind(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FExposureAverageShader::Bind(IRenderQueue *q)
|
|
||||||
{
|
|
||||||
if (!mShader)
|
|
||||||
{
|
|
||||||
mShader.reset(screen->CreateShaderProgram());
|
|
||||||
mShader->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 400);
|
|
||||||
mShader->Compile(IShaderProgram::Fragment, "shaders/glsl/exposureaverage.fp", "", 400);
|
|
||||||
mShader->Link("shaders/glsl/exposureaverage");
|
|
||||||
}
|
|
||||||
mShader->Bind(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FExposureCombineShader::Bind(IRenderQueue *q)
|
|
||||||
{
|
|
||||||
if (!mShader)
|
|
||||||
{
|
|
||||||
FString prolog = Uniforms.CreateDeclaration("Uniforms", UniformBlock::Desc());
|
|
||||||
|
|
||||||
mShader.reset(screen->CreateShaderProgram());
|
|
||||||
mShader->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
|
|
||||||
mShader->Compile(IShaderProgram::Fragment, "shaders/glsl/exposurecombine.fp", prolog, 330);
|
|
||||||
mShader->Link("shaders/glsl/exposurecombine");
|
|
||||||
mShader->SetUniformBufferLocation(Uniforms.BindingPoint(), "Uniforms");
|
|
||||||
Uniforms.Init();
|
|
||||||
}
|
|
||||||
mShader->Bind(q);
|
|
||||||
}
|
|
|
@ -27,69 +27,4 @@ private:
|
||||||
std::unique_ptr<IShaderProgram> mShader[NumTonemapModes];
|
std::unique_ptr<IShaderProgram> mShader[NumTonemapModes];
|
||||||
};
|
};
|
||||||
|
|
||||||
class FExposureExtractShader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Bind(IRenderQueue *q);
|
|
||||||
|
|
||||||
struct UniformBlock
|
|
||||||
{
|
|
||||||
FVector2 Scale;
|
|
||||||
FVector2 Offset;
|
|
||||||
|
|
||||||
static std::vector<UniformFieldDesc> Desc()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
|
||||||
{ "Scale", UniformType::Vec2, offsetof(UniformBlock, Scale) },
|
|
||||||
{ "Offset", UniformType::Vec2, offsetof(UniformBlock, Offset) }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ShaderUniforms<UniformBlock, POSTPROCESS_BINDINGPOINT> Uniforms;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<IShaderProgram> mShader;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FExposureAverageShader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Bind(IRenderQueue *q);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<IShaderProgram> mShader;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FExposureCombineShader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Bind(IRenderQueue *q);
|
|
||||||
|
|
||||||
struct UniformBlock
|
|
||||||
{
|
|
||||||
float ExposureBase;
|
|
||||||
float ExposureMin;
|
|
||||||
float ExposureScale;
|
|
||||||
float ExposureSpeed;
|
|
||||||
|
|
||||||
static std::vector<UniformFieldDesc> Desc()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
|
||||||
{ "ExposureBase", UniformType::Float, offsetof(UniformBlock, ExposureBase) },
|
|
||||||
{ "ExposureMin", UniformType::Float, offsetof(UniformBlock, ExposureMin) },
|
|
||||||
{ "ExposureScale", UniformType::Float, offsetof(UniformBlock, ExposureScale) },
|
|
||||||
{ "ExposureSpeed", UniformType::Float, offsetof(UniformBlock, ExposureSpeed) }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ShaderUniforms<UniformBlock, POSTPROCESS_BINDINGPOINT> Uniforms;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<IShaderProgram> mShader;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in a new issue