You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
689 lines
29 KiB
C++
689 lines
29 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
|
|
// Description : Post processing common utilities
|
|
|
|
|
|
#include "RenderDll_precompiled.h"
|
|
#include "PostProcessUtils.h"
|
|
#include "../RendElements/FlareSoftOcclusionQuery.h"
|
|
|
|
RECT SPostEffectsUtils::m_pScreenRect;
|
|
ITimer* SPostEffectsUtils::m_pTimer;
|
|
int SPostEffectsUtils::m_iFrameCounter = 0;
|
|
SDepthTexture* SPostEffectsUtils::m_pCurDepthSurface;
|
|
CShader* SPostEffectsUtils::m_pCurrShader;
|
|
int SPostEffectsUtils::m_nColorMatrixFrameID;
|
|
float SPostEffectsUtils::m_fWaterLevel;
|
|
float SPostEffectsUtils::m_fOverscanBorderAspectRatio = 1.0f;
|
|
Matrix44 SPostEffectsUtils::m_pScaleBias = Matrix44(
|
|
0.5f, 0, 0, 0,
|
|
0, -0.5f, 0, 0,
|
|
0, 0, 1.0f, 0,
|
|
0.5f, 0.5f, 0, 1.0f);
|
|
|
|
Vec3 SPostEffectsUtils::m_vRT = Vec3(0, 0, 0);
|
|
Vec3 SPostEffectsUtils::m_vLT = Vec3(0, 0, 0);
|
|
Vec3 SPostEffectsUtils::m_vLB = Vec3(0, 0, 0);
|
|
Vec3 SPostEffectsUtils::m_vRB = Vec3(0, 0, 0);
|
|
int SPostEffectsUtils::m_nFrustrumFrameID = 0;
|
|
|
|
CTexture* SPostEffectsUtils::m_UpscaleTarget = nullptr;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool SPostEffectsUtils::Create()
|
|
{
|
|
assert(gRenDev);
|
|
|
|
const SViewport& MainVp = gRenDev->m_MainViewport;
|
|
const bool bCreatePostAA = CRenderer::CV_r_AntialiasingMode && !CTexture::IsTextureExist(CTexture::s_ptexPrevBackBuffer[0][0]);
|
|
//@NOTE: CV_r_watercaustics will be removed when the infinite ocean component feature toggle is removed.
|
|
const bool bCreateCaustics = (CRenderer::CV_r_watervolumecaustics && CRenderer::CV_r_watercaustics) && !CTexture::IsTextureExist(CTexture::s_ptexWaterCaustics[0]);
|
|
|
|
static ICVar* DolbyCvar = gEnv->pConsole->GetCVar("r_HDRDolby");
|
|
|
|
ETEX_Format nHDRReducedFormat = gRenDev->UseHalfFloatRenderTargets() ? eTF_R11G11B10F : eTF_R10G10B10A2;
|
|
|
|
ETEX_Format taaFormat = eTF_R8G8B8A8;
|
|
if (CRenderer::CV_r_AntialiasingMode == eAT_TAA)
|
|
{
|
|
taaFormat = eTF_R16G16B16A16F;
|
|
}
|
|
|
|
bool taaFormatMismatch = (CRenderer::CV_r_AntialiasingMode && CTexture::s_ptexPrevBackBuffer[0][0] && CTexture::s_ptexPrevBackBuffer[0][0]->GetDstFormat() != taaFormat);
|
|
|
|
if (!CTexture::s_ptexBackBufferScaled[0] || taaFormatMismatch || m_pScreenRect.right != MainVp.nWidth || m_pScreenRect.bottom != MainVp.nHeight || bCreatePostAA || bCreateCaustics)
|
|
{
|
|
assert(gRenDev);
|
|
|
|
const int nWidth = gRenDev->GetWidth();
|
|
const int nHeight = gRenDev->GetHeight();
|
|
|
|
// Update viewport info
|
|
m_pScreenRect.left = 0;
|
|
m_pScreenRect.top = 0;
|
|
|
|
m_pScreenRect.right = nWidth;
|
|
m_pScreenRect.bottom = nHeight;
|
|
|
|
if (CRenderer::CV_r_AntialiasingMode)
|
|
{
|
|
CreateRenderTarget("$PrevBackBuffer0", CTexture::s_ptexPrevBackBuffer[0][0], nWidth, nHeight, Clr_Unknown, 1, 0, taaFormat, TO_PREVBACKBUFFERMAP0, FT_DONT_RELEASE | FT_USAGE_ALLOWREADSRGB);
|
|
CreateRenderTarget("$PrevBackBuffer1", CTexture::s_ptexPrevBackBuffer[1][0], nWidth, nHeight, Clr_Unknown, 1, 0, taaFormat, TO_PREVBACKBUFFERMAP1, FT_DONT_RELEASE | FT_USAGE_ALLOWREADSRGB);
|
|
if (gRenDev->m_bDualStereoSupport)
|
|
{
|
|
CreateRenderTarget("$PrevBackBuffer0_R", CTexture::s_ptexPrevBackBuffer[0][1], nWidth, nHeight, Clr_Unknown, 1, 0, taaFormat, -1, FT_DONT_RELEASE | FT_USAGE_ALLOWREADSRGB);
|
|
CreateRenderTarget("$PrevBackBuffer1_R", CTexture::s_ptexPrevBackBuffer[1][1], nWidth, nHeight, Clr_Unknown, 1, 0, taaFormat, -1, FT_DONT_RELEASE | FT_USAGE_ALLOWREADSRGB);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SAFE_RELEASE(CTexture::s_ptexPrevBackBuffer[0][0]);
|
|
SAFE_RELEASE(CTexture::s_ptexPrevBackBuffer[1][0]);
|
|
SAFE_RELEASE(CTexture::s_ptexPrevBackBuffer[0][1]);
|
|
SAFE_RELEASE(CTexture::s_ptexPrevBackBuffer[1][1]);
|
|
}
|
|
|
|
CreateRenderTarget("$Cached3DHud", CTexture::s_ptexCached3DHud, nWidth, nHeight, Clr_Unknown, 1, 0, eTF_R8G8B8A8, -1, FT_DONT_RELEASE);
|
|
CreateRenderTarget("$Cached3DHudDownsampled", CTexture::s_ptexCached3DHudScaled, nWidth >> 2, nHeight >> 2, Clr_Unknown, 1, 0, eTF_R8G8B8A8, -1, FT_DONT_RELEASE);
|
|
|
|
// Scaled versions of the scene target
|
|
CreateRenderTarget("$BackBufferScaled_d2", CTexture::s_ptexBackBufferScaled[0], nWidth >> 1, nHeight >> 1, Clr_Unknown, 1, 0, eTF_R8G8B8A8, TO_BACKBUFFERSCALED_D2, FT_DONT_RELEASE);
|
|
|
|
// Ghosting requires data overframes, need to handle for each GPU in MGPU mode
|
|
CreateRenderTarget("$PrevFrameScaled", CTexture::s_ptexPrevFrameScaled, nWidth >> 1, nHeight >> 1, Clr_Unknown, 1, 0, eTF_R8G8B8A8, -1, FT_DONT_RELEASE);
|
|
|
|
CreateRenderTarget("$BackBufferScaledTemp_d2", CTexture::s_ptexBackBufferScaledTemp[0], nWidth >> 1, nHeight >> 1, Clr_Unknown, 1, 0, eTF_R8G8B8A8, -1, FT_DONT_RELEASE);
|
|
|
|
CreateRenderTarget("$WaterVolumeRefl", CTexture::s_ptexWaterVolumeRefl[0], nWidth >> 1, nHeight >> 1, Clr_Unknown, 1, true, nHDRReducedFormat, TO_WATERVOLUMEREFLMAP, FT_DONT_RELEASE);
|
|
CreateRenderTarget("$WaterVolumeReflPrev", CTexture::s_ptexWaterVolumeRefl[1], nWidth >> 1, nHeight >> 1, Clr_Unknown, 1, true, nHDRReducedFormat, TO_WATERVOLUMEREFLMAPPREV, FT_DONT_RELEASE);
|
|
|
|
CreateRenderTarget("$BackBufferScaled_d4", CTexture::s_ptexBackBufferScaled[1], nWidth >> 2, nHeight >> 2, Clr_Unknown, 1, 0, eTF_R8G8B8A8, TO_BACKBUFFERSCALED_D4, FT_DONT_RELEASE);
|
|
CreateRenderTarget("$BackBufferScaledTemp_d4", CTexture::s_ptexBackBufferScaledTemp[1], nWidth >> 2, nHeight >> 2, Clr_Unknown, 1, 0, eTF_R8G8B8A8, -1, FT_DONT_RELEASE);
|
|
|
|
CreateRenderTarget("$BackBufferScaled_d8", CTexture::s_ptexBackBufferScaled[2], nWidth >> 3, nHeight >> 3, Clr_Unknown, 1, 0, eTF_R8G8B8A8, TO_BACKBUFFERSCALED_D8, FT_DONT_RELEASE);
|
|
|
|
CreateRenderTarget("$RainDropsAccumRT_0", CTexture::s_ptexRainDropsRT[0], nWidth >> 2, nHeight >> 2, Clr_Unknown, 1, false, eTF_R8G8B8A8, -1, FT_DONT_RELEASE);
|
|
CreateRenderTarget("$RainDropsAccumRT_1", CTexture::s_ptexRainDropsRT[1], nWidth >> 2, nHeight >> 2, Clr_Unknown, 1, false, eTF_R8G8B8A8, -1, FT_DONT_RELEASE);
|
|
|
|
CreateRenderTarget("$RainSSOcclusion0", CTexture::s_ptexRainSSOcclusion[0], nWidth >> 3, nHeight >> 3, Clr_Unknown, 1, false, eTF_R8G8B8A8);
|
|
CreateRenderTarget("$RainSSOcclusion1", CTexture::s_ptexRainSSOcclusion[1], nWidth >> 3, nHeight >> 3, Clr_Unknown, 1, false, eTF_R8G8B8A8);
|
|
|
|
CreateRenderTarget("$RainOcclusion", CTexture::s_ptexRainOcclusion, RAIN_OCC_MAP_SIZE, RAIN_OCC_MAP_SIZE, Clr_Unknown, false, false, eTF_R8G8B8A8, -1, FT_DONT_RELEASE);
|
|
|
|
// Water phys simulation requires data overframes, need to handle for each GPU in MGPU mode
|
|
CreateRenderTarget("$WaterRipplesDDN_0", CTexture::s_ptexWaterRipplesDDN, 256, 256, Clr_Unknown, 1, true, eTF_R8G8B8A8, TO_WATERRIPPLESMAP);
|
|
if (gRenDev->UseHalfFloatRenderTargets())
|
|
{
|
|
CreateRenderTarget("$WaterVolumeDDN", CTexture::s_ptexWaterVolumeDDN, 64, 64, Clr_Unknown, 1, true, eTF_R16G16B16A16F, TO_WATERVOLUMEMAP);
|
|
}
|
|
else
|
|
{
|
|
CreateRenderTarget("$WaterVolumeDDN", CTexture::s_ptexWaterVolumeDDN, 64, 64, Clr_Unknown, 1, true, eTF_R8G8B8A8, TO_WATERVOLUMEMAP);
|
|
}
|
|
|
|
if (CRenderer::CV_r_watervolumecaustics && CRenderer::CV_r_watercaustics) //@NOTE: CV_r_watercaustics will be removed when the infinite ocean component feature toggle is removed.
|
|
{
|
|
const int nCausticRes = clamp_tpl(CRenderer::CV_r_watervolumecausticsresolution, 256, 4096);
|
|
CreateRenderTarget("$WaterVolumeCaustics", CTexture::s_ptexWaterCaustics[0], nCausticRes, nCausticRes, Clr_Unknown, 1, false, eTF_R8G8B8A8, TO_WATERVOLUMECAUSTICSMAP);
|
|
CreateRenderTarget("$WaterVolumeCausticsTemp", CTexture::s_ptexWaterCaustics[1], nCausticRes, nCausticRes, Clr_Unknown, 1, false, eTF_R8G8B8A8, TO_WATERVOLUMECAUSTICSMAPTEMP);
|
|
}
|
|
else
|
|
{
|
|
SAFE_RELEASE(CTexture::s_ptexWaterCaustics[0]);
|
|
SAFE_RELEASE(CTexture::s_ptexWaterCaustics[1]);
|
|
}
|
|
|
|
#if defined(VOLUMETRIC_FOG_SHADOWS)
|
|
int fogShadowBufDiv = (CRenderer::CV_r_FogShadows == 2) ? 4 : 2;
|
|
CreateRenderTarget("$VolFogShadowBuf0", CTexture::s_ptexVolFogShadowBuf[0], nWidth / fogShadowBufDiv, nHeight / fogShadowBufDiv, Clr_Unknown, 1, 0, eTF_R8G8B8A8, TO_VOLFOGSHADOW_BUF);
|
|
CreateRenderTarget("$VolFogShadowBuf1", CTexture::s_ptexVolFogShadowBuf[1], nWidth / fogShadowBufDiv, nHeight / fogShadowBufDiv, Clr_Unknown, 1, 0, eTF_R8G8B8A8);
|
|
#endif
|
|
|
|
char str[256];
|
|
|
|
// TODO: Only create necessary RTs for minimal ring?
|
|
for (int i = 0; i < MAX_OCCLUSION_READBACK_TEXTURES; i++)
|
|
{
|
|
azsprintf(str, "$FlaresOcclusion_%d", i);
|
|
|
|
CreateRenderTarget(str, CTexture::s_ptexFlaresOcclusionRing[i], CFlareSoftOcclusionQuery::s_nIDColMax, CFlareSoftOcclusionQuery::s_nIDRowMax, Clr_Unknown, 1, 0, eTF_R8G8B8A8, -1, FT_DONT_RELEASE | FT_STAGE_READBACK);
|
|
}
|
|
|
|
CreateRenderTarget("$FlaresGather", CTexture::s_ptexFlaresGather, CFlareSoftOcclusionQuery::s_nGatherTextureWidth, CFlareSoftOcclusionQuery::s_nGatherTextureHeight, Clr_Unknown, 1, 0, eTF_R8G8B8A8, -1, FT_DONT_RELEASE);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::Release()
|
|
{
|
|
SAFE_RELEASE(CTexture::s_ptexPrevBackBuffer[0][0]);
|
|
SAFE_RELEASE(CTexture::s_ptexPrevBackBuffer[1][0]);
|
|
SAFE_RELEASE(CTexture::s_ptexPrevBackBuffer[0][1]);
|
|
SAFE_RELEASE(CTexture::s_ptexPrevBackBuffer[1][1]);
|
|
|
|
SAFE_RELEASE(CTexture::s_ptexBackBufferScaled[0]);
|
|
SAFE_RELEASE(CTexture::s_ptexBackBufferScaled[1]);
|
|
SAFE_RELEASE(CTexture::s_ptexBackBufferScaled[2]);
|
|
|
|
SAFE_RELEASE(CTexture::s_ptexBackBufferScaledTemp[0]);
|
|
SAFE_RELEASE(CTexture::s_ptexBackBufferScaledTemp[1]);
|
|
|
|
SAFE_RELEASE(CTexture::s_ptexWaterVolumeDDN);
|
|
SAFE_RELEASE(CTexture::s_ptexWaterVolumeRefl[0]);
|
|
SAFE_RELEASE(CTexture::s_ptexWaterVolumeRefl[1]);
|
|
SAFE_RELEASE(CTexture::s_ptexWaterCaustics[0]);
|
|
SAFE_RELEASE(CTexture::s_ptexWaterCaustics[1]);
|
|
|
|
SAFE_RELEASE(CTexture::s_ptexCached3DHud);
|
|
SAFE_RELEASE(CTexture::s_ptexCached3DHudScaled);
|
|
|
|
SAFE_RELEASE(CTexture::s_ptexPrevFrameScaled);
|
|
SAFE_RELEASE(CTexture::s_ptexWaterRipplesDDN);
|
|
|
|
SAFE_RELEASE(CTexture::s_ptexRainDropsRT[0]);
|
|
SAFE_RELEASE(CTexture::s_ptexRainDropsRT[1]);
|
|
|
|
SAFE_RELEASE(CTexture::s_ptexRainSSOcclusion[0]);
|
|
SAFE_RELEASE(CTexture::s_ptexRainSSOcclusion[1]);
|
|
SAFE_RELEASE(CTexture::s_ptexRainOcclusion);
|
|
|
|
#if defined(VOLUMETRIC_FOG_SHADOWS)
|
|
SAFE_RELEASE(CTexture::s_ptexVolFogShadowBuf[0]);
|
|
SAFE_RELEASE(CTexture::s_ptexVolFogShadowBuf[1]);
|
|
#endif
|
|
|
|
for (int i = 0; i < MAX_OCCLUSION_READBACK_TEXTURES; i++)
|
|
{
|
|
SAFE_RELEASE(CTexture::s_ptexFlaresOcclusionRing[i]);
|
|
}
|
|
SAFE_RELEASE(CTexture::s_ptexFlaresGather);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::GetFullScreenTri(SVF_P3F_C4B_T2F pResult[3], int nTexWidth, int nTexHeight, float z, const RECT * pSrcRegion)
|
|
{
|
|
if (gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_PersFlags & RBPF_REVERSE_DEPTH)
|
|
z = 1.0f - z;
|
|
|
|
pResult[0].xyz = Vec3(-0.0f, -0.0f, z);
|
|
pResult[0].color.dcolor = ~0U;
|
|
pResult[0].st = Vec2(0, 0);
|
|
pResult[1].xyz = Vec3(-0.0f, 2.0f, z);
|
|
pResult[1].color.dcolor = ~0U;
|
|
pResult[1].st = Vec2(0, 2);
|
|
pResult[2].xyz = Vec3(2.0f, -0.0f, z);
|
|
pResult[2].color.dcolor = ~0U;
|
|
pResult[2].st = Vec2(2, 0);
|
|
|
|
if (pSrcRegion)
|
|
{
|
|
const Vec4 vTexCoordsRegion(2.0f*float(pSrcRegion->left) / nTexWidth,
|
|
2.0f*float(pSrcRegion->right) / nTexWidth,
|
|
2.0f*float(pSrcRegion->top) / nTexHeight,
|
|
2.0f*float(pSrcRegion->bottom) / nTexHeight);
|
|
pResult[0].st = Vec2(vTexCoordsRegion.x, vTexCoordsRegion.z);
|
|
pResult[1].st = Vec2(vTexCoordsRegion.x, vTexCoordsRegion.w);
|
|
pResult[2].st = Vec2(vTexCoordsRegion.y, vTexCoordsRegion.z);
|
|
}
|
|
}
|
|
|
|
void SPostEffectsUtils::DrawFullScreenTri(int nTexWidth, int nTexHeight, float z, const RECT * pSrcRegion)
|
|
{
|
|
SVF_P3F_C4B_T2F screenTri[3];
|
|
GetFullScreenTri(screenTri, nTexWidth, nTexHeight, z, pSrcRegion);
|
|
|
|
CVertexBuffer strip(screenTri, eVF_P3F_C4B_T2F);
|
|
gRenDev->DrawPrimitivesInternal(&strip, 3, eptTriangleList);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::DrawScreenQuad([[maybe_unused]] int nTexWidth, [[maybe_unused]] int nTexHeight, float x0, float y0, float x1, float y1)
|
|
{
|
|
const float z = (gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_PersFlags & RBPF_REVERSE_DEPTH) ? 1.0f : 0.0f;
|
|
|
|
Vec3 vv[4];
|
|
vv[0] = Vec3(x0, y0, z);
|
|
vv[1] = Vec3(x0, y1, z);
|
|
vv[2] = Vec3(x1, y0, z);
|
|
vv[3] = Vec3(x1, y1, z);
|
|
SVF_P3F_C4B_T2F pScreenQuad[] =
|
|
{
|
|
{ Vec3(0, 0, 0), {
|
|
{0}
|
|
}, Vec2(0, 0) },
|
|
{ Vec3(0, 0, 0), {
|
|
{0}
|
|
}, Vec2(0, 1) },
|
|
{ Vec3(0, 0, 0), {
|
|
{0}
|
|
}, Vec2(1, 0) },
|
|
{ Vec3(0, 0, 0), {
|
|
{0}
|
|
}, Vec2(1, 1) },
|
|
};
|
|
|
|
pScreenQuad[0].xyz = vv[0];
|
|
pScreenQuad[1].xyz = vv[1];
|
|
pScreenQuad[2].xyz = vv[2];
|
|
pScreenQuad[3].xyz = vv[3];
|
|
|
|
gRenDev->m_RP.m_PersFlags2 &= ~(RBPF2_COMMIT_PF);
|
|
|
|
CVertexBuffer strip(pScreenQuad, eVF_P3F_C4B_T2F);
|
|
gRenDev->DrawPrimitivesInternal(&strip, 4, eptTriangleStrip);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::DrawQuad([[maybe_unused]] int nTexWidth, [[maybe_unused]] int nTexHeight,
|
|
const Vec2& vxA, const Vec2& vxB, const Vec2& vxC, const Vec2& vxD,
|
|
const Vec2& uvA, const Vec2& uvB, const Vec2& uvC, const Vec2& uvD)
|
|
{
|
|
const float z = (gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_PersFlags & RBPF_REVERSE_DEPTH) ? 1.0f : 0.0f;
|
|
|
|
SVF_P3F_C4B_T2F pScreenQuad[4] =
|
|
{
|
|
{ Vec3(vxA.x, vxA.y, z), {
|
|
{0}
|
|
}, uvA },
|
|
{ Vec3(vxB.x, vxB.y, z), {
|
|
{0}
|
|
}, uvB },
|
|
{ Vec3(vxD.x, vxD.y, z), {
|
|
{0}
|
|
}, uvD },
|
|
{ Vec3(vxC.x, vxC.y, z), {
|
|
{0}
|
|
}, uvC }
|
|
};
|
|
gRenDev->m_RP.m_PersFlags2 &= ~(RBPF2_COMMIT_PF);
|
|
|
|
CVertexBuffer strip(pScreenQuad, eVF_P3F_C4B_T2F);
|
|
gRenDev->DrawPrimitivesInternal(&strip, 4, eptTriangleStrip);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::GetFullScreenTriWPOS(SVF_P3F_T2F_T3F pResult[3], int nTexWidth, int nTexHeight, float z, const RECT *pSrcRegion)
|
|
{
|
|
UpdateFrustumCorners();
|
|
|
|
if (gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_PersFlags & RBPF_REVERSE_DEPTH)
|
|
z = 1.0f - z;
|
|
|
|
pResult[0].p = Vec3(-0.0f, -0.0f, z);
|
|
pResult[0].st0 = Vec2(0, 0);
|
|
pResult[0].st1 = m_vLT;
|
|
pResult[1].p = Vec3(-0.0f, 2.0f, z);
|
|
pResult[1].st0 = Vec2(0, 2);
|
|
pResult[1].st1 = m_vLB*2.0f - m_vLT;
|
|
pResult[2].p = Vec3(2.0f, -0.0f, z);
|
|
pResult[2].st0 = Vec2(2, 0);
|
|
pResult[2].st1 = m_vRT*2.0f - m_vLT;
|
|
|
|
if (pSrcRegion)
|
|
{
|
|
const Vec4 vTexCoordsRegion(2.0f*float(pSrcRegion->left) / nTexWidth,
|
|
2.0f*float(pSrcRegion->right) / nTexWidth,
|
|
2.0f*float(pSrcRegion->top) / nTexHeight,
|
|
2.0f*float(pSrcRegion->bottom) / nTexHeight);
|
|
pResult[0].st0 = Vec2(vTexCoordsRegion.x, vTexCoordsRegion.z);
|
|
pResult[1].st0 = Vec2(vTexCoordsRegion.x, vTexCoordsRegion.w);
|
|
pResult[2].st0 = Vec2(vTexCoordsRegion.y, vTexCoordsRegion.z);
|
|
}
|
|
}
|
|
|
|
void SPostEffectsUtils::DrawFullScreenTriWPOS(int nTexWidth, int nTexHeight, float z, const RECT *pSrcRegion)
|
|
{
|
|
SVF_P3F_T2F_T3F screenTri[3];
|
|
GetFullScreenTriWPOS(screenTri, nTexWidth, nTexHeight, z, pSrcRegion);
|
|
|
|
CVertexBuffer strip(&screenTri[0], eVF_P3F_T2F_T3F);
|
|
gRenDev->DrawPrimitivesInternal(&strip, 3, eptTriangleList);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::SetTexture(CTexture* pTex, int nStage, int nFilter, int nClamp, bool bSRGBLookup, DWORD dwBorderColor)
|
|
{
|
|
if (pTex)
|
|
{
|
|
STexState TS;
|
|
TS.SetFilterMode(nFilter);
|
|
TS.SetClampMode(nClamp, nClamp, nClamp);
|
|
if (nClamp == TADDR_BORDER)
|
|
{
|
|
TS.SetBorderColor(dwBorderColor);
|
|
}
|
|
TS.m_bSRGBLookup = bSRGBLookup;
|
|
int nTexState = CTexture::GetTexState(TS);
|
|
pTex->Apply(nStage, nTexState);
|
|
}
|
|
else
|
|
{
|
|
CTexture::ApplyForID(nStage, 0, -1, -1);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool SPostEffectsUtils::CreateRenderTarget(const char* szTexName, CTexture*& pTex, int nWidth, int nHeight, const ColorF& cClear, [[maybe_unused]] bool bUseAlpha, bool bMipMaps, ETEX_Format eTF, int nCustomID, int nFlags)
|
|
{
|
|
// check if parameters are valid
|
|
if (!nWidth || !nHeight)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
uint32 flags = nFlags;
|
|
flags |= FT_DONT_STREAM | FT_USAGE_RENDERTARGET | (bMipMaps ? FT_FORCE_MIPS : FT_NOMIPS);
|
|
|
|
// if texture doesn't exist yet, create it
|
|
if (!CTexture::IsTextureExist(pTex))
|
|
{
|
|
pTex = CTexture::CreateRenderTarget(szTexName, nWidth, nHeight, cClear, eTT_2D, flags, eTF, nCustomID);
|
|
}
|
|
else
|
|
{
|
|
pTex->SetFlags(flags);
|
|
pTex->SetWidth(nWidth);
|
|
pTex->SetHeight(nHeight);
|
|
pTex->CreateRenderTarget(eTF, cClear);
|
|
}
|
|
|
|
// Following will mess up don't care resolve/restore actions since Fill() sets textures to be cleared on next draw
|
|
#if !defined(CRY_USE_METAL) && !defined(OPENGL_ES)
|
|
if (pTex)
|
|
{
|
|
pTex->Clear();
|
|
}
|
|
#endif
|
|
|
|
return CTexture::IsTextureExist(pTex) ? 1 : 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool SPostEffectsUtils::ShBeginPass(CShader* pShader, const CCryNameTSCRC& TechName, uint32 nFlags)
|
|
{
|
|
assert(pShader);
|
|
|
|
m_pCurrShader = pShader;
|
|
|
|
uint32 nPasses;
|
|
m_pCurrShader->FXSetTechnique(TechName);
|
|
m_pCurrShader->FXBegin(&nPasses, nFlags);
|
|
return m_pCurrShader->FXBeginPass(0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::ShEndPass()
|
|
{
|
|
assert(m_pCurrShader);
|
|
|
|
m_pCurrShader->FXEndPass();
|
|
m_pCurrShader->FXEnd();
|
|
|
|
m_pCurrShader = 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::ShSetParamVS(const CCryNameR& pParamName, const Vec4& pParam)
|
|
{
|
|
assert(m_pCurrShader);
|
|
m_pCurrShader->FXSetVSFloat(pParamName, &pParam, 1);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::ShSetParamPS(const CCryNameR& pParamName, const Vec4& pParam)
|
|
{
|
|
assert(m_pCurrShader);
|
|
m_pCurrShader->FXSetPSFloat(pParamName, &pParam, 1);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::ClearScreen(float r, float g, float b, float a)
|
|
{
|
|
static CCryNameTSCRC pTechName("ClearScreen");
|
|
ShBeginPass(CShaderMan::s_shPostEffects, pTechName, FEF_DONTSETTEXTURES | FEF_DONTSETSTATES);
|
|
|
|
int iTempX, iTempY, iWidth, iHeight;
|
|
gRenDev->GetViewport(&iTempX, &iTempY, &iWidth, &iHeight);
|
|
|
|
Vec4 pClrScrParms = Vec4(r, g, b, a);
|
|
static CCryNameR pParamName("clrScrParams");
|
|
CShaderMan::s_shPostEffects->FXSetPSFloat(pParamName, &pClrScrParms, 1);
|
|
|
|
DrawFullScreenTri(iWidth, iHeight);
|
|
|
|
ShEndPass();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::PrepareGmemDeferredDecals()
|
|
{
|
|
static CCryNameTSCRC pTechName("PrepareGmemDeferredDecals");
|
|
ShBeginPass(CShaderMan::s_shPostEffects, pTechName, FEF_DONTSETTEXTURES | FEF_DONTSETSTATES);
|
|
|
|
int iTempX, iTempY, iWidth, iHeight;
|
|
gRenDev->GetViewport(&iTempX, &iTempY, &iWidth, &iHeight);
|
|
|
|
DrawFullScreenTri(iWidth, iHeight);
|
|
|
|
ShEndPass();
|
|
}
|
|
void SPostEffectsUtils::ClearGmemGBuffer()
|
|
{
|
|
static CCryNameTSCRC pTechName("ClearGmemGBuffer");
|
|
ShBeginPass(CShaderMan::s_shPostEffects, pTechName, FEF_DONTSETTEXTURES | FEF_DONTSETSTATES);
|
|
|
|
int iTempX, iTempY, iWidth, iHeight;
|
|
gRenDev->GetViewport(&iTempX, &iTempY, &iWidth, &iHeight);
|
|
|
|
DrawFullScreenTri(iWidth, iHeight);
|
|
|
|
ShEndPass();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SPostEffectsUtils::UpdateFrustumCorners()
|
|
{
|
|
auto& renderPipeline = gRenDev->m_RP;
|
|
auto& threadInfo = renderPipeline.m_TI[renderPipeline.m_nProcessThreadID];
|
|
|
|
int nFrameID = threadInfo.m_nFrameID;
|
|
if (m_nFrustrumFrameID != nFrameID || CRenderer::CV_r_StereoMode == 1)
|
|
{
|
|
Vec3 frustumCoords[8];
|
|
gRenDev->GetViewParameters().CalcVerts(frustumCoords);
|
|
|
|
m_vRT = frustumCoords[4] - frustumCoords[0];
|
|
m_vLT = frustumCoords[5] - frustumCoords[1];
|
|
m_vLB = frustumCoords[6] - frustumCoords[2];
|
|
m_vRB = frustumCoords[7] - frustumCoords[3];
|
|
|
|
// Swap order when mirrored culling enabled
|
|
if ((gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_PersFlags & RBPF_MIRRORCULL))
|
|
{
|
|
m_vLT = frustumCoords[4] - frustumCoords[0];
|
|
m_vRT = frustumCoords[5] - frustumCoords[1];
|
|
m_vRB = frustumCoords[6] - frustumCoords[2];
|
|
m_vLB = frustumCoords[7] - frustumCoords[3];
|
|
}
|
|
|
|
m_nFrustrumFrameID = nFrameID;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void SPostEffectsUtils::UpdateOverscanBorderAspectRatio()
|
|
{
|
|
if (gRenDev)
|
|
{
|
|
const float screenWidth = (float)gRenDev->GetWidth();
|
|
const float screenHeight = (float)gRenDev->GetHeight();
|
|
Vec2 overscanBorders = Vec2(0.0f, 0.0f);
|
|
gRenDev->EF_Query(EFQ_OverscanBorders, overscanBorders);
|
|
|
|
const float aspectX = (screenWidth * (1.0f - (overscanBorders.y * 2.0f)));
|
|
const float aspectY = (screenHeight * (1.0f - (overscanBorders.x * 2.0f)));
|
|
m_fOverscanBorderAspectRatio = aspectX / max(aspectY, 0.001f);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Matrix44& SPostEffectsUtils::GetColorMatrix()
|
|
{
|
|
CPostEffectsMgr* pPostMgr = PostEffectMgr();
|
|
int nFrameID = gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nProcessThreadID].m_nFrameID;
|
|
if (m_nColorMatrixFrameID != nFrameID)
|
|
{
|
|
// Create color transformation matrices
|
|
float fBrightness = pPostMgr->GetByNameF("Global_Brightness");
|
|
float fContrast = pPostMgr->GetByNameF("Global_Contrast");
|
|
float fSaturation = pPostMgr->GetByNameF("Global_Saturation");
|
|
float fColorC = pPostMgr->GetByNameF("Global_ColorC");
|
|
float fColorM = pPostMgr->GetByNameF("Global_ColorM");
|
|
float fColorY = pPostMgr->GetByNameF("Global_ColorY");
|
|
float fColorK = pPostMgr->GetByNameF("Global_ColorK");
|
|
float fColorHue = pPostMgr->GetByNameF("Global_ColorHue");
|
|
|
|
float fUserCyan = pPostMgr->GetByNameF("Global_User_ColorC");
|
|
fColorC = fUserCyan;
|
|
|
|
float fUserMagenta = pPostMgr->GetByNameF("Global_User_ColorM");
|
|
fColorM = fUserMagenta;
|
|
|
|
float fUserYellow = pPostMgr->GetByNameF("Global_User_ColorY");
|
|
fColorY = fUserYellow;
|
|
|
|
float fUserLuminance = pPostMgr->GetByNameF("Global_User_ColorK");
|
|
fColorK = fUserLuminance;
|
|
|
|
float fUserHue = pPostMgr->GetByNameF("Global_User_ColorHue");
|
|
fColorHue = fUserHue;
|
|
|
|
float fUserBrightness = pPostMgr->GetByNameF("Global_User_Brightness");
|
|
fBrightness = fUserBrightness;
|
|
|
|
float fUserContrast = pPostMgr->GetByNameF("Global_User_Contrast");
|
|
fContrast = fUserContrast;
|
|
|
|
float fUserSaturation = pPostMgr->GetByNameF("Global_User_Saturation"); // translate to 0
|
|
fSaturation = fUserSaturation;
|
|
|
|
// Saturation matrix
|
|
Matrix44 pSaturationMat;
|
|
|
|
{
|
|
float y = 0.3086f, u = 0.6094f, v = 0.0820f, s = clamp_tpl<float>(fSaturation, -1.0f, 100.0f);
|
|
|
|
float a = (1.0f - s) * y + s;
|
|
float b = (1.0f - s) * y;
|
|
float c = (1.0f - s) * y;
|
|
float d = (1.0f - s) * u;
|
|
float e = (1.0f - s) * u + s;
|
|
float f = (1.0f - s) * u;
|
|
float g = (1.0f - s) * v;
|
|
float h = (1.0f - s) * v;
|
|
float i = (1.0f - s) * v + s;
|
|
|
|
pSaturationMat.SetIdentity();
|
|
pSaturationMat.SetRow(0, Vec3(a, d, g));
|
|
pSaturationMat.SetRow(1, Vec3(b, e, h));
|
|
pSaturationMat.SetRow(2, Vec3(c, f, i));
|
|
}
|
|
|
|
// Create Brightness matrix
|
|
Matrix44 pBrightMat;
|
|
fBrightness = clamp_tpl<float>(fBrightness, 0.0f, 100.0f);
|
|
|
|
pBrightMat.SetIdentity();
|
|
pBrightMat.SetRow(0, Vec3(fBrightness, 0, 0));
|
|
pBrightMat.SetRow(1, Vec3(0, fBrightness, 0));
|
|
pBrightMat.SetRow(2, Vec3(0, 0, fBrightness));
|
|
|
|
// Create Contrast matrix
|
|
Matrix44 pContrastMat;
|
|
{
|
|
float c = clamp_tpl<float>(fContrast, -1.0f, 100.0f);
|
|
|
|
pContrastMat.SetIdentity();
|
|
pContrastMat.SetRow(0, Vec3(c, 0, 0));
|
|
pContrastMat.SetRow(1, Vec3(0, c, 0));
|
|
pContrastMat.SetRow(2, Vec3(0, 0, c));
|
|
pContrastMat.SetColumn(3, 0.5f * Vec3(1.0f - c, 1.0f - c, 1.0f - c));
|
|
}
|
|
|
|
// Create CMKY matrix
|
|
Matrix44 pCMKYMat;
|
|
{
|
|
Vec4 pCMYKParams = Vec4(fColorC + fColorK, fColorM + fColorK, fColorY + fColorK, 1.0f);
|
|
|
|
pCMKYMat.SetIdentity();
|
|
pCMKYMat.SetColumn(3, -Vec3(pCMYKParams.x, pCMYKParams.y, pCMYKParams.z));
|
|
}
|
|
|
|
// Create Hue rotation matrix
|
|
Matrix44 pHueMat;
|
|
{
|
|
pHueMat.SetIdentity();
|
|
|
|
const Vec3 pHueVec = Vec3(0.57735026f, 0.57735026f, 0.57735026f); // (normalized(1,1,1)
|
|
pHueMat = Matrix34::CreateRotationAA(fColorHue * PI, pHueVec);
|
|
pHueMat.SetColumn(3, Vec3(0, 0, 0));
|
|
}
|
|
|
|
// Compose final color matrix and set fragment program constants
|
|
m_pColorMat = pSaturationMat * (pBrightMat * pContrastMat * pCMKYMat * pHueMat);
|
|
|
|
m_nColorMatrixFrameID = nFrameID;
|
|
}
|
|
|
|
|
|
return m_pColorMat;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|