text: /*
  * 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
  
  
  #ifndef CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_POSTPROCESS_POSTPROCESSUTILS_H
  #define CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_POSTPROCESS_POSTPROCESSUTILS_H
  #pragma once
  
  
  struct SDepthTexture;
  class CShader;
  
  struct SPostEffectsUtils
  {
      enum EDepthDownsample
      {
          eDepthDownsample_None = 0,
  
          eDepthDownsample_Min,
          eDepthDownsample_Max,
      };
  
      // Create all resources
      bool Create();
  
      // Release all used resources
      void Release();
  
      // Create a render target
      static bool CreateRenderTarget(const char* szTexName, CTexture*& pTex, int iWidth, int iHeight, const ColorF& cClear, bool bUseAlpha, bool bMipMaps = 0, ETEX_Format pTexFormat = eTF_R8G8B8A8, int nCustomID = -1, int nFlags = 0);
  
      ////////////////////////////////////////////////////////////////////////////////////////////////////
      // Utilities to void some code duplication
      ////////////////////////////////////////////////////////////////////////////////////////////////////
  
      // Begins render pass utility - for post process stuff only pass 0 assumed to be used
      static bool ShBeginPass(CShader* pShader, const CCryNameTSCRC& TechName, uint32 nFlags = 0);
  
      // Ends render pass utility
      static void ShEndPass();
  
      // Set vertex shader constant utility
      static void ShSetParamVS(const CCryNameR& pParamName, const Vec4& pParam);
  
      // Set pixel shader constant utility
      static void ShSetParamPS(const CCryNameR& pParamName, const Vec4& pParam);
  
      static void GetFullScreenTri(SVF_P3F_C4B_T2F pResult[3], int nTexWidth, int nTexHeight, float z = 0, const RECT * pSrcRegion = NULL);
      static void GetFullScreenTriWPOS(SVF_P3F_T2F_T3F pResult[3], int nTexWidth, int nTexHeight, float z = 0, const RECT * pSrcRegion = NULL);
  
      // Draws fullscreen aligned triangle
      static void DrawFullScreenTri(int nTexWidth, int nTexHeight, float z = 0, const RECT* pSrcRegion = NULL);
      static void DrawFullScreenTriWPOS(int nTexWidth, int nTexHeight, float z = 0, const RECT* pSrcRegion = NULL);
  
      // Draws static quad. Uv/size offsets handled via vertex shader.
      virtual void DrawQuadFS(CShader* pShader, bool bOutputCamVec, int nWidth, int nHeight, float x0 = 0, float y0 = 0, float x1 = 1, float y1 = 1, float z = 0) = 0;
  
      // Deprecated - use DrawQuadFS. Draws screen aligned quad
      static void DrawScreenQuad(int nTexWidth, int nTexHeight, float x0 = 0, float y0 = 0, float x1 = 1, float y1 = 1);
  
      //  Deprecated: Only used in GammaCorrection technique - Draws a generic, non-screen-aligned quad
      static void DrawQuad(int nTexWidth, int nTexHeight,
          const Vec2& vxA, const Vec2& vxB, const Vec2& vxC, const Vec2& vxD,
          const Vec2& uvA = Vec2(0, 0), const Vec2& uvB = Vec2(0, 1), const Vec2& uvC = Vec2(1, 1), const Vec2& uvD = Vec2(1, 0));
  
      // Sets a texture
      static void SetTexture(CTexture* pTex, int nStage, int nFilter = FILTER_LINEAR, int nClamp = 1, bool bSRGBLookup = false, DWORD dwBorderColor = 0);
  
      // Copy a texture into other texture
      virtual void StretchRect(CTexture* pSrc, CTexture*& pDst, bool bClearAlpha = false, bool bDecodeSrcRGBK = false, bool bEncodeDstRGBK = false, bool bBigDownsample = false, EDepthDownsample depthDownsampleMode = eDepthDownsample_None, bool bBindMultisampled = false, const RECT* srcRegion = NULL) = 0;
  
      // Copy screen into texture
      virtual void CopyScreenToTexture(CTexture*& pDst, const RECT* pSrcRect) = 0;
  
      // Apply Gaussian blur a texture
      virtual void TexBlurGaussian(CTexture* pTex, int nAmount = 1, float fScale = 1.0f, float fDistribution = 5.0f, bool bAlphaOnly = false, CTexture* pMask = 0, bool bSRGB = false, CTexture* pBlurTmp = 0) = 0;
  
      // Clear active render target region
      static void ClearScreen(float r, float g, float b, float a);
  
      static void UpdateFrustumCorners();
      static void UpdateOverscanBorderAspectRatio();
  
      // Special full screen pass utility functions used by GMEM path /////
      static void PrepareGmemDeferredDecals();
      static void ClearGmemGBuffer();
      /////////////////////////////////////////////////////////////////////
  
      // Log utility
      static void Log(const char* pszMsg)
      {
          if (gRenDev->m_logFileHandle != AZ::IO::InvalidHandle && pszMsg)
          {
              gRenDev->Logv(SRendItem::m_RecurseLevel[gRenDev->m_pRT->GetThreadList()], pszMsg);
          }
      }
  
      // Get current color matrix set up by global color parameters
      Matrix44& GetColorMatrix();
  
      ////////////////////////////////////////////////////////////////////////////////////////////////////
      // Math utils
      ////////////////////////////////////////////////////////////////////////////////////////////////////
  
      // Linear interpolation
      static float InterpolateLinear(float p1, float p2, float t)
      {
          return p1 + (p2 - p1) * t;
      };
  
      // Cubic interpolation
      static float InterpolateCubic(float p1, float p2, float p3, float p4, float t)
      {
          float t2 = t * t;
          return (((-p1 * 2.0f) + (p2 * 5.0f) - (p3 * 4.0f) + p4) / 6.0f) * t2 * t + (p1 + p3 - (2.0f * p2)) * t2 + (((-4.0f * p1) + p2 + (p3 * 4.0f) - p4) / 6.0f) * t + p2;
      };
  
      // Sine interpolation
      static float InterpolateSine(float p1, float p2, float p3, float p4, float t)
      {
          return p2 + (t * (p3 - p2)) + (sinf(t * PI) * ((p2 + p2) - p1 - p3 + (t * (p1 - (p2 + p2 + p2) + (p3 + p3 + p3) - p4))) / 8.0f);
      };
  
      // Return normalized random number
      static float randf()
      {
          return cry_random(0.0f, 1.0f);
      }
  
      // Return signed normalized random number
      static float srandf()
      {
          return cry_random(-1.0f, 1.0f);
      }
  
      // Returns a quasi-random sequence of values; for 2d data (2, 3) is the recommended base
      static float HaltonSequence(int index, int primeBase)
      {
          float invBase = 1.0f / (float)primeBase;
          float f = invBase;
          float result = 0;
  
          for (int i = index; i > 0; i /= primeBase, f *= invBase)
          {
              result += f * (float)(i % primeBase);
          }
  
          return result;
      }
  
      // Returns closest power of 2 size
      static int GetClosestPow2Size(int size)
      {
          float fPower = floorf(logf((float)size) / logf(2.0f));
          int nResize = int(powf(2.0f, fPower));
  
          // Clamp
          if (nResize >= 512)
          {
              nResize = 512;
          }
  
          return nResize;
      }
  
      static void GetViewMatrix(Matrix44A& viewMatrix, bool bCameraSpace = false)
      {
          viewMatrix = gRenDev->m_ViewMatrix;
          if (bCameraSpace)
          {
              viewMatrix.m30 = 0.0f;
              viewMatrix.m31 = 0.0f;
              viewMatrix.m32 = 0.0f;
          }
      }
  
      static void GetTextureRect(CTexture* pTexture, RECT* pRect)
      {
          pRect->left = 0;
          pRect->top = 0;
          pRect->right = pTexture->GetWidth();
          pRect->bottom = pTexture->GetHeight();
      }
  
      static float GaussianDistribution1D(float x, float rho)
      {
          float g = 1.0f / (rho * sqrtf(2.0f * PI));
          g *= expf(-(x * x) / (2.0f * rho * rho));
          return g;
      }
  
      static float GaussianDistribution2D(float x, float y, float rho)
      {
          float g = 1.0f / (2.0f * PI * rho * rho);
          g *= expf(-(x * x + y * y) / (2 * rho * rho));
          return g;
      }
  
      static CTexture* GetTemporalCurrentTarget()
      {
          return CTexture::s_ptexPrevBackBuffer[SPostEffectsUtils::m_iFrameCounter % 2][gRenDev->m_CurRenderEye];
      }
  
      static CTexture* GetTemporalHistoryTarget()
      {
          return CTexture::s_ptexPrevBackBuffer[(SPostEffectsUtils::m_iFrameCounter + 1) % 2][gRenDev->m_CurRenderEye];
      }
  
      static CTexture* GetCoCCurrentTarget()
      {
          return CTexture::s_ptexSceneCoCHistory[SPostEffectsUtils::m_iFrameCounter % 2];
      }
  
      static CTexture* GetCoCHistoryTarget()
      {
          return CTexture::s_ptexSceneCoCHistory[(SPostEffectsUtils::m_iFrameCounter + 1) % 2];
      }
  
      static CTexture* AcquireFinalCompositeTarget(bool bNeedHDRTarget)
      {
          if (bNeedHDRTarget)
          {
              m_UpscaleTarget = GetTemporalHistoryTarget();
          }
          else
          {
              m_UpscaleTarget = CTexture::s_ptexSceneDiffuse;
          }
          return m_UpscaleTarget;
      }
  
      static CTexture* GetFinalCompositeTarget()
      {
          return m_UpscaleTarget;
      }
  
      static CTexture* GetVelocityObjectRT()
      {
          return CTexture::s_ptexVelocityObjects[gRenDev->m_CurRenderEye];
      }
  
      static float GetOverscanBorderAspectRatio()
      {
          return m_fOverscanBorderAspectRatio;
      }
  
  public:
  
      static SDepthTexture* m_pCurDepthSurface;
      static RECT m_pScreenRect;
      static ITimer* m_pTimer;
      static int m_iFrameCounter;
      static int m_nColorMatrixFrameID;
  
      static CShader* m_pCurrShader;
  
      Matrix44 m_pView;
      Matrix44 m_pProj;
      Matrix44 m_pViewProj;
      Matrix44 m_pColorMat;
      static Matrix44 m_pScaleBias;
      static float m_fWaterLevel;
  
      // frustrum corners
      static Vec3 m_vRT, m_vLT, m_vLB, m_vRB;
      static int m_nFrustrumFrameID;
  
  protected:
  
      SPostEffectsUtils()
      {
          m_pView.SetIdentity();
          m_pProj.SetIdentity();
          m_pViewProj.SetIdentity();
          m_pColorMat.SetIdentity();
  
          m_pCurDepthSurface = NULL;
          m_pScreenRect.left = m_pScreenRect.top = 0;
          m_pScreenRect.bottom = m_pScreenRect.right = 0;
          m_pTimer = NULL;
          m_iFrameCounter = 0;
          m_nColorMatrixFrameID = -1;
  
          m_pCurrShader = NULL;
          m_fWaterLevel = 0.0;
          m_vRT = m_vLT = m_vLB = m_vRB = Vec3(ZERO);
          m_nFrustrumFrameID = -1;
      }
  
      virtual ~SPostEffectsUtils()
      {
      }
  
      static float m_fOverscanBorderAspectRatio;
  
  private:
      static CTexture* m_UpscaleTarget;
  };
  
  #endif // CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_POSTPROCESS_POSTPROCESSUTILS_H