*
This commit is contained in:
@@ -0,0 +1,420 @@
|
||||
#ifndef PostHDR_h__
|
||||
#define PostHDR_h__
|
||||
#include "render/PostEffect.h"
|
||||
#include "Globals.h"
|
||||
#include "render/ITextureSampler.h"
|
||||
#include "math/LifeMath.h"
|
||||
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
|
||||
#include "LifeDebug.h"
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
class PostHDR : public PostEffect
|
||||
{
|
||||
public:
|
||||
ITexture2D* g_brightPassTexture;
|
||||
ITexture2D* g_downSampleTexture;
|
||||
ITexture2D* g_horizontalBlur;
|
||||
ITexture2D* g_verticalBlur;
|
||||
ITexture2D* g_finalImage;
|
||||
ITexture2D* g_lumLast;
|
||||
ITexture2D* g_lumCur;
|
||||
static const int NumLuminanceTextures = 4;
|
||||
ITexture2D* luminanceTextures[NumLuminanceTextures];
|
||||
ITexture2D* luminanceTexturesZ[NumLuminanceTextures];
|
||||
ITexture2D* src;
|
||||
ITexture2D* srcZ;
|
||||
|
||||
ITexture2D* downSampleZ;
|
||||
ITexture2D* brightPassZ;
|
||||
|
||||
ITextureSampler* samplerPointClamp;
|
||||
|
||||
float exposure;
|
||||
float brightTheresold;
|
||||
|
||||
PostHDR()
|
||||
{
|
||||
}
|
||||
~PostHDR()
|
||||
{
|
||||
SAFE_DELETE(g_brightPassTexture);
|
||||
SAFE_DELETE(g_downSampleTexture);
|
||||
SAFE_DELETE(g_horizontalBlur);
|
||||
SAFE_DELETE(g_verticalBlur);
|
||||
SAFE_DELETE(g_finalImage);
|
||||
SAFE_DELETE(g_lumLast);
|
||||
SAFE_DELETE(g_lumCur);
|
||||
SAFE_DELETE(downSampleZ);
|
||||
SAFE_DELETE(brightPassZ);
|
||||
|
||||
SAFE_DELETE(g_downSamplePS);
|
||||
SAFE_DELETE(g_brightPassPS);
|
||||
SAFE_DELETE(g_horizontalBlurPS);
|
||||
SAFE_DELETE(g_verticalBlurPS);
|
||||
SAFE_DELETE(g_downSample2x2PS);
|
||||
SAFE_DELETE(g_downSample3x3PS);
|
||||
SAFE_DELETE(g_resampleAvgLumExp);
|
||||
SAFE_DELETE(g_lumAdaptation);
|
||||
SAFE_DELETE(g_composePS);
|
||||
SAFE_DELETE(g_constBuffer);
|
||||
SAFE_DELETE(g_pointSampler);
|
||||
SAFE_DELETE(g_linearSampler);
|
||||
SAFE_DELETE(g_cbLumAdaptation);
|
||||
|
||||
for(int i = 0; i<NumLuminanceTextures; i++)
|
||||
{
|
||||
SAFE_DELETE(luminanceTextures[i]);
|
||||
SAFE_DELETE(luminanceTexturesZ[i]);
|
||||
}
|
||||
}
|
||||
ITexture2D* Execute(PostEffectParams& params)
|
||||
{
|
||||
g_renderer->SetPSTextureSampler(g_pointSampler, 0);
|
||||
g_renderer->SetPSTextureSampler(g_linearSampler, 1);
|
||||
|
||||
g_renderer->SetTargets(g_downSampleTexture, downSampleZ);
|
||||
g_renderer->SetViewport(LifeMath::Rect2i(0, 0, g_downSampleTexture->Width(), g_downSampleTexture->Height()));
|
||||
|
||||
//1'st pass - do down sampling
|
||||
g_renderer->SetPixelShader(g_downSamplePS);
|
||||
g_renderer->SetPSTexture(params.renderTarget, 0);
|
||||
src = params.renderTarget;
|
||||
srcZ = params.depthTarget;
|
||||
|
||||
Get4x4Offsets(params.renderTarget->Width(), params.renderTarget->Height(), offsets2);
|
||||
g_constBuffer->Update(offsets2, sizeof(LifeMath::float4)*16);
|
||||
g_renderer->SetPSConstantBuffer(g_constBuffer, 0);
|
||||
// g_downSamplePS.SetFloat4A("downSampleOffsets", offsets2);
|
||||
g_renderer->RenderToTextureNoPs();
|
||||
|
||||
// g_downSampleTexture.ToFile("C:\\rt_1_downSample.jpg");
|
||||
|
||||
//2'nd measure scene luminance
|
||||
MeasureLuminance(g_downSampleTexture, params.depthTex);
|
||||
//3'rd calculate scene luminance adaptation
|
||||
//
|
||||
CalculateLuminanceAdaptation(params.timeElapsed);
|
||||
|
||||
//4'th step - bright pass
|
||||
g_renderer->UnbindResourcesPS();
|
||||
g_renderer->SetTargets(g_brightPassTexture, brightPassZ);
|
||||
g_renderer->SetPixelShader(g_brightPassPS);
|
||||
g_renderer->SetPSTexture(g_downSampleTexture, 0);
|
||||
g_renderer->SetPSTexture(g_lumCur, 1);
|
||||
g_renderer->SetPSTexture(params.depthTex, 2);
|
||||
//g_renderer.SetTextureSampler(g_pointSampler, 0);
|
||||
/// g_renderer.SetTextureSampler(g_pointSampler, 1);
|
||||
g_renderer->SetViewport(LifeMath::Rect2i(0, 0, g_brightPassTexture->Width(), g_brightPassTexture->Height()));
|
||||
g_renderer->SetScissorRectangle(LifeMath::Rect2i(0, 0, g_brightPassTexture->Width(), g_brightPassTexture->Height()));
|
||||
|
||||
g_renderer->RenderToTextureNoPs();
|
||||
|
||||
// g_brightPassTexture.ToFile("C:\\rt_2_brightPass.jpg");
|
||||
// g_renderer.SetTextureSampler(g_linearSampler, 0);
|
||||
|
||||
g_renderer->UnbindResourcesPS();
|
||||
|
||||
g_renderer->SetPSTextureSampler(samplerPointClamp, 0);
|
||||
g_renderer->SetPSTextureSampler(samplerPointClamp, 1);
|
||||
//5'th pass - do horizontal blur
|
||||
g_renderer->SetTargets(g_horizontalBlur, downSampleZ);
|
||||
g_renderer->SetPixelShader(g_horizontalBlurPS);
|
||||
g_renderer->SetPSTexture(g_brightPassTexture, 0);
|
||||
|
||||
GetBlurWeightedOffsets((float)NumBlurSamples, g_brightPassTexture->Width(), offsets3);
|
||||
g_constBuffer->Update(offsets3, sizeof(LifeMath::float4)*NumBlurSamples);
|
||||
g_renderer->SetPSConstantBuffer(g_constBuffer, 0);
|
||||
// g_horizontalBlurPS.SetFloat4A("hBlurOffsets", offsets3);
|
||||
g_renderer->SetViewport(LifeMath::Rect2i(0, 0, g_horizontalBlur->Width(), g_horizontalBlur->Height()));
|
||||
g_renderer->SetScissorRectangle(LifeMath::Rect2i(0, 0, g_horizontalBlur->Width(), g_horizontalBlur->Height()));
|
||||
|
||||
g_renderer->RenderToTextureNoPs();
|
||||
|
||||
// g_horizontalBlur.ToFile("C:\\rt_3_horBlur.jpg");
|
||||
//6'th pass - do vertical blur
|
||||
|
||||
g_renderer->UnbindResourcesPS();
|
||||
g_renderer->SetTargets(g_verticalBlur, downSampleZ);
|
||||
g_renderer->SetPixelShader(g_verticalBlurPS);
|
||||
g_renderer->SetPSTexture(g_horizontalBlur, 0);
|
||||
|
||||
GetBlurWeightedOffsets((float)NumBlurSamples, g_brightPassTexture->Height(), offsets3);
|
||||
//g_verticalBlurPS.SetFloat4A("vBlurOffsets", offsets4);
|
||||
|
||||
g_constBuffer->Update(offsets3, sizeof(LifeMath::float4)*NumBlurSamples);
|
||||
g_renderer->SetPSConstantBuffer(g_constBuffer, 0);
|
||||
|
||||
g_renderer->RenderToTextureNoPs();
|
||||
|
||||
//7'th compose final image
|
||||
ComposeFinalImage(params.renderTarget, g_lumCur, g_verticalBlur);
|
||||
// g_finalImage.ToFile("C:\\rt_5_final.jpg");
|
||||
return g_finalImage;
|
||||
}
|
||||
void Init(SceneDescriptor& desc)
|
||||
{
|
||||
g_renderer = CG::me()->GetRenderer();
|
||||
|
||||
g_lumAdaptation = ResourceManager::me()->CompileUserShaderPS(String(_text("HDRLumAdaptation.psh")));
|
||||
|
||||
/* char laPs[] =
|
||||
"Texture2D tex0 : register(t7);"\
|
||||
"Texture2D tex1 : register(t8);"\
|
||||
"SamplerState linearSampler : register(s0);"\
|
||||
"cbuffer timeData : register(b11){float4 g_fElapsedTime : packoffset(c0);};"\
|
||||
"float4 main_PS(in float4 Position : SV_Position, in float2 texcoord : TEXCOORD0) : SV_Target{"\
|
||||
"float4 fAdaptedLum =tex0.Sample(linearSampler, float2(0.25f, 0.25f));"\
|
||||
"float4 fCurrentLum = tex1.Sample(linearSampler, float2(0.5f, 0.5f));"\
|
||||
"float fNewAdaptation = fAdaptedLum + (fCurrentLum - fAdaptedLum) * g_fElapsedTime.x;"\
|
||||
"return fAdaptedLum;}";
|
||||
|
||||
g_lumAdaptation = g_renderer->CompileUserShaderPS(laPs);*/
|
||||
|
||||
ISamplerDescription pscDesc(Clamp, Clamp, Clamp, MinMagMipPoint);
|
||||
samplerPointClamp = g_renderer->CreateTextureSampler(&pscDesc);
|
||||
|
||||
exposure = 0.72f;
|
||||
brightTheresold = 0.7f;
|
||||
|
||||
g_finalImage = g_renderer->CreateRenderTarget(desc.width, desc.height, FORMAT_R16G16B16A16_FLOAT);
|
||||
|
||||
//Bright pass texture
|
||||
int brightPassTextureWidth = desc.width / 4;
|
||||
int brightPassTextureHeight = desc.height / 4;
|
||||
g_brightPassTexture = g_renderer->CreateRenderTarget(brightPassTextureWidth,
|
||||
brightPassTextureHeight, FORMAT_R16G16B16A16_FLOAT);
|
||||
|
||||
brightPassZ = g_renderer->CreateDepthTarget(brightPassTextureWidth,
|
||||
brightPassTextureHeight, FORMAT_D16_UNORM);
|
||||
|
||||
//Down sample texture
|
||||
int downSampledTextureWidth = brightPassTextureWidth / 1;
|
||||
int downSampledTextureHeight = brightPassTextureHeight / 1;
|
||||
g_downSampleTexture = g_renderer->CreateRenderTarget(downSampledTextureWidth,
|
||||
downSampledTextureHeight, FORMAT_R16G16B16A16_FLOAT);
|
||||
|
||||
downSampleZ = g_renderer->CreateDepthTarget(downSampledTextureWidth,
|
||||
downSampledTextureHeight, FORMAT_D16_UNORM);
|
||||
|
||||
//Horizontal blur texture
|
||||
int horizontalBlurTextureWidth = downSampledTextureWidth;
|
||||
int horizontalBlurTextureHeight = downSampledTextureHeight;
|
||||
g_horizontalBlur = g_renderer->CreateRenderTarget(horizontalBlurTextureWidth,
|
||||
horizontalBlurTextureHeight, FORMAT_R16G16B16A16_FLOAT);
|
||||
|
||||
//Vertical blur texture
|
||||
int verticalBlurTextureWidth = horizontalBlurTextureWidth;
|
||||
int verticalBlurTextureHeight = horizontalBlurTextureHeight;
|
||||
g_verticalBlur = g_renderer->CreateRenderTarget(verticalBlurTextureWidth,
|
||||
verticalBlurTextureHeight, FORMAT_R16G16B16A16_FLOAT);
|
||||
|
||||
g_downSamplePS = ResourceManager::me()->CompileUserShaderPS(String(_text("DownSample.psh")));
|
||||
g_brightPassPS = ResourceManager::me()->CompileUserShaderPS(String(_text("BrightPass.psh")));
|
||||
g_horizontalBlurPS = ResourceManager::me()->CompileUserShaderPS(String(_text("HorizontalBlur.psh")));
|
||||
|
||||
g_verticalBlurPS = ResourceManager::me()->CompileUserShaderPS(String(_text("VerticalBlur.psh")));
|
||||
|
||||
g_resampleAvgLumExp = ResourceManager::me()->CompileUserShaderPS(String(_text("ResampleAvgLumExp.psh")));
|
||||
|
||||
//LC
|
||||
g_downSample2x2PS = ResourceManager::me()->CompileUserShaderPS(String(_text("SampleLumInitial.psh")));
|
||||
g_downSample3x3PS = ResourceManager::me()->CompileUserShaderPS(String(_text("DownSampleLum3.psh")));
|
||||
g_composePS = ResourceManager::me()->CompileUserShaderPS(String(_text("ComposeHDR.psh")));
|
||||
|
||||
g_constBuffer = g_renderer->CreateConstantBuffer(16 * 16*256);
|
||||
|
||||
g_cbLumAdaptation = g_renderer->CreateConstantBuffer(sizeof(LifeMath::float4));
|
||||
|
||||
CreateLuminanceTextures();
|
||||
|
||||
ISamplerDescription psDesc(Wrap, Wrap, Wrap, MinMagMipPoint);
|
||||
ISamplerDescription lsDesc(Wrap, Wrap, Wrap, Anisotropic);
|
||||
|
||||
g_pointSampler = g_renderer->CreateTextureSampler(&psDesc);
|
||||
g_linearSampler = g_renderer->CreateTextureSampler(&lsDesc);
|
||||
}
|
||||
private:
|
||||
static const int MAX_SAMPLES = 6;
|
||||
|
||||
//post effects
|
||||
IShader* g_downSamplePS;
|
||||
IShader* g_brightPassPS;
|
||||
IShader* g_horizontalBlurPS;
|
||||
IShader* g_verticalBlurPS;
|
||||
|
||||
//luminance calculation
|
||||
IShader* g_downSample2x2PS;
|
||||
IShader* g_downSample3x3PS;
|
||||
IShader* g_resampleAvgLumExp;
|
||||
IShader* g_lumAdaptation;
|
||||
|
||||
//final composing shader
|
||||
IShader* g_composePS;
|
||||
|
||||
static const int NumBlurSamples = 9;
|
||||
|
||||
//luminance calculator
|
||||
|
||||
IRenderer* g_renderer;
|
||||
|
||||
IConstantBuffer* g_constBuffer;
|
||||
ITextureSampler* g_pointSampler;
|
||||
ITextureSampler* g_linearSampler;
|
||||
|
||||
IConstantBuffer* g_cbLumAdaptation;
|
||||
|
||||
LifeMath::float4 offsets2[16];
|
||||
LifeMath::float4 offsets3[NumBlurSamples];
|
||||
LifeMath::float4 offsets[9];
|
||||
|
||||
void CreateLuminanceTextures()
|
||||
{
|
||||
for (int i = 0; i < NumLuminanceTextures; i++)
|
||||
{
|
||||
int iSampleLen = 1 << (2 * i);
|
||||
luminanceTextures[i] = g_renderer->CreateRenderTarget(iSampleLen, iSampleLen, FORMAT_R16G16B16A16_FLOAT);
|
||||
luminanceTexturesZ[i] = g_renderer->CreateDepthTarget(iSampleLen, iSampleLen, FORMAT_D16_UNORM);
|
||||
}
|
||||
|
||||
g_lumCur = g_renderer->CreateRenderTarget(1, 1, FORMAT_R16G16B16A16_FLOAT);
|
||||
g_lumLast = g_renderer->CreateRenderTarget(1, 1, FORMAT_R16G16B16A16_FLOAT);
|
||||
|
||||
|
||||
LifeMath::float4 clear_color(1,1,1,1);
|
||||
g_renderer->ClearRenderTarget(g_lumCur, &clear_color);
|
||||
g_renderer->ClearRenderTarget(g_lumLast, &clear_color);
|
||||
}
|
||||
|
||||
void Render2x2Pass(ITexture2D* srcTexture, ITexture2D* destTexture, ITexture2D* sceneDepth)
|
||||
{
|
||||
float tU, tV;
|
||||
tU = 1.0f / (3.0f * destTexture->Width());
|
||||
tV = 1.0f / (3.0f * destTexture->Height());
|
||||
|
||||
int index = 0;
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
offsets[index].X = (float)x * tU;
|
||||
offsets[index].Y = (float)y * tV;
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
g_renderer->SetTargets(destTexture,luminanceTexturesZ[NumLuminanceTextures - 1]);
|
||||
g_renderer->SetPSTexture(srcTexture, 0);
|
||||
g_renderer->SetPSTexture(sceneDepth, 1);
|
||||
g_renderer->SetPixelShader(g_downSample2x2PS);
|
||||
|
||||
g_constBuffer->Update(&offsets, sizeof(LifeMath::float4)* 9);
|
||||
g_renderer->SetPSConstantBuffer(g_constBuffer, 0);
|
||||
|
||||
// With everything configured we can now render the first pass to the luminance textures.
|
||||
g_renderer->SetViewport(LifeMath::Rect2i(0, 0, destTexture->Width(), destTexture->Height()));
|
||||
|
||||
g_renderer->RenderToTextureNoPs();
|
||||
}
|
||||
void MeasureLuminance(ITexture2D* hdrTexture, ITexture2D* depth)
|
||||
{
|
||||
int curTex = NumLuminanceTextures - 1;
|
||||
Render2x2Pass(hdrTexture, luminanceTextures[curTex],depth);
|
||||
|
||||
curTex--;
|
||||
while (curTex > 0)
|
||||
{
|
||||
g_renderer->SetTargets(luminanceTextures[curTex], luminanceTexturesZ[curTex]);
|
||||
Get4x4Offsets(luminanceTextures[curTex + 1]->Width(), luminanceTextures[curTex + 1]->Height(), offsets2);
|
||||
|
||||
g_renderer->SetPixelShader(g_downSample3x3PS);
|
||||
g_renderer->SetPSTexture(luminanceTextures[curTex + 1], 0);
|
||||
|
||||
g_constBuffer->Update(offsets2, sizeof(LifeMath::float4)*16);
|
||||
g_renderer->SetPSConstantBuffer(g_constBuffer, 0);
|
||||
|
||||
g_renderer->SetViewport(LifeMath::Rect2i(0, 0, luminanceTextures[curTex]->Width(), luminanceTextures[curTex]->Height()));
|
||||
g_renderer->SetScissorRectangle(LifeMath::Rect2i(0, 0, luminanceTextures[curTex]->Width(), luminanceTextures[curTex]->Height()));
|
||||
g_renderer->RenderToTextureNoPs();
|
||||
curTex--;
|
||||
}
|
||||
|
||||
g_renderer->SetTargets(luminanceTextures[0],luminanceTexturesZ[0]);
|
||||
g_renderer->SetPixelShader(g_resampleAvgLumExp);
|
||||
Get4x4Offsets(luminanceTextures[1]->Width(), luminanceTextures[1]->Height(), offsets2);
|
||||
g_constBuffer->Update(offsets2, sizeof(LifeMath::float4)*16);
|
||||
g_renderer->SetPSConstantBuffer(g_constBuffer, 0);
|
||||
|
||||
g_renderer->SetPSTexture(luminanceTextures[1], 0);
|
||||
g_renderer->SetViewport(LifeMath::Rect2i(0, 0, luminanceTextures[0]->Width(), luminanceTextures[0]->Height()));
|
||||
g_renderer->SetScissorRectangle(LifeMath::Rect2i(0, 0, luminanceTextures[0]->Width(), luminanceTextures[0]->Height()));
|
||||
|
||||
g_renderer->RenderToTextureNoPs();
|
||||
}
|
||||
void CalculateLuminanceAdaptation(float timeElapsed)
|
||||
{
|
||||
g_renderer->SetViewport(LifeMath::Rect2i(0, 0, 1, 1));
|
||||
g_renderer->SetScissorRectangle(LifeMath::Rect2i(0, 0, 1, 1));
|
||||
|
||||
g_renderer->UnbindResourcesPS();
|
||||
|
||||
ITexture2D* texSwap = g_lumLast;
|
||||
g_lumLast = g_lumCur;
|
||||
g_lumCur = texSwap;
|
||||
|
||||
g_renderer->SetTargets(g_lumCur, luminanceTexturesZ[0]);
|
||||
LifeMath::float4 clear_color(0,0,0,0);
|
||||
g_renderer->ClearRenderTarget(g_lumCur, &clear_color);
|
||||
g_renderer->SetPixelShader(g_lumAdaptation);
|
||||
|
||||
g_renderer->SetPSTexture(g_lumLast, luminanceTextures[0], 7,2);
|
||||
// g_renderer->SetPSTexture(rgba.ptr(), luminanceTextures[0], 7,2);
|
||||
|
||||
if(timeElapsed <0.0000001f)
|
||||
timeElapsed = 0.0000001f;
|
||||
|
||||
if(timeElapsed > 1.0f)
|
||||
timeElapsed = 1.0f;
|
||||
|
||||
float val = (1.0f - (pow(0.98f, 30.0f * timeElapsed)));
|
||||
LifeMath::float4 time(val, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
g_cbLumAdaptation->Update(&time, sizeof(LifeMath::float4));
|
||||
g_renderer->SetPSConstantBuffer(g_cbLumAdaptation, 11);
|
||||
|
||||
g_renderer->RenderToTextureNoPs();
|
||||
}
|
||||
void ComposeFinalImage(ITexture2D* hdrTexture, ITexture2D* luminanceTexture, ITexture2D* bloomTexture)
|
||||
{
|
||||
g_renderer->SetPSTextureSampler(g_linearSampler, 1);
|
||||
g_renderer->SetTargets(g_finalImage, srcZ);
|
||||
|
||||
g_renderer->SetPixelShader(g_composePS);
|
||||
g_renderer->SetPSTexture(hdrTexture, 0);
|
||||
g_renderer->SetPSTexture(bloomTexture, 1);
|
||||
g_renderer->SetPSTextureNULL(2);
|
||||
g_renderer->SetPSTexture(luminanceTexture, 3);
|
||||
|
||||
float g_fKeyValue = 0.05f;
|
||||
LifeMath::float4 key(g_fKeyValue, 0, 0, 0);
|
||||
g_constBuffer->Update(key, sizeof(LifeMath::float4));
|
||||
g_renderer->SetPSConstantBuffer(g_constBuffer, 0);
|
||||
// g_composePS.SetFloat("g_fMiddleGray", g_fKeyValue);
|
||||
|
||||
g_renderer->SetViewport(LifeMath::Rect2i(0, 0, g_finalImage->Width(), g_finalImage->Height()));
|
||||
|
||||
g_renderer->SetScissorRectangle(LifeMath::Rect2i(0, 0, g_finalImage->Width(), g_finalImage->Height()));
|
||||
|
||||
g_renderer->RenderToTextureNoPs();
|
||||
|
||||
g_renderer->UnbindResourcesPS();
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // PostHDR_h__
|
||||
Reference in New Issue
Block a user