BVB Source Codes

CRYENGINE Show terrain_water_quad.cpp Source code

Return Download CRYENGINE: download terrain_water_quad.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   terrain_water_quad.cpp
  5. //  Version:     v1.00
  6. //  Created:     28/8/2001 by Vladimir Kajalin
  7. //  Compilers:   Visual Studio.NET
  8. //  Description: Create and draw terrain water geometry (screen space grid, cycle buffers)
  9. // -------------------------------------------------------------------------
  10. //  History:
  11. //
  12. ////////////////////////////////////////////////////////////////////////////
  13.  
  14. #include "StdAfx.h"
  15.  
  16. #include "terrain_water.h"
  17. #include "PolygonClipContext.h"
  18. #include "3dEngine.h"
  19. #include "ObjMan.h"
  20. #include "MatMan.h"
  21. #include "VisAreas.h"
  22.  
  23. namespace
  24. {
  25. static const float OCEAN_FOG_DENSITY_MINIMUM = 0.0001f;
  26. }
  27.  
  28. ITimer* COcean::m_pOceanTimer = 0;
  29. CREWaterOcean* COcean::m_pOceanRE = 0;
  30. uint32 COcean::m_nVisiblePixelsCount = ~0;
  31.  
  32. COcean::COcean(IMaterial* pMat)
  33. {
  34.         m_pBottomCapRenderMesh = 0;
  35.  
  36.         memset(m_fRECustomData, 0, sizeof(m_fRECustomData));
  37.         memset(m_fREOceanBottomCustomData, 0, sizeof(m_fREOceanBottomCustomData));
  38.  
  39.         m_pMaterial = pMat;
  40.         m_fLastFov = 0;
  41.         m_fLastVisibleFrameTime = 0.0f;
  42.  
  43.         m_pShaderOcclusionQuery = GetRenderer() ?
  44.                                   GetRenderer()->EF_LoadShader("OcclusionTest", 0) : nullptr;
  45.         memset(m_pREOcclusionQueries, 0, sizeof(m_pREOcclusionQueries));
  46.  
  47.         m_nLastVisibleFrameId = 0;
  48.  
  49.         m_pBottomCapMaterial = GetMatMan()->LoadMaterial("EngineAssets/Materials/Water/WaterOceanBottom", false);
  50.         m_pFogIntoMat = GetMatMan()->LoadMaterial("EngineAssets/Materials/Fog/OceanInto", false);
  51.         m_pFogOutofMat = GetMatMan()->LoadMaterial("EngineAssets/Materials/Fog/OceanOutof", false);
  52.         m_pFogIntoMatLowSpec = GetMatMan()->LoadMaterial("EngineAssets/Materials/Fog/OceanIntoLowSpec", false);
  53.         m_pFogOutofMatLowSpec = GetMatMan()->LoadMaterial("EngineAssets/Materials/Fog/OceanOutofLowSpec", false);
  54.  
  55.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; i++)
  56.         {
  57.                 if (GetRenderer())
  58.                 {
  59.                         m_pWVRE[i] = static_cast<CREWaterVolume*>(GetRenderer()->EF_CreateRE(eDATA_WaterVolume));
  60.                         if (m_pWVRE[i])
  61.                         {
  62.                                 m_pWVRE[i]->m_drawWaterSurface = false;
  63.                                 m_pWVRE[i]->m_pParams = &m_wvParams[i];
  64.                                 m_pWVRE[i]->m_pOceanParams = &m_wvoParams[i];
  65.                         }
  66.                 }
  67.                 else
  68.                 {
  69.                         m_pWVRE[i] = nullptr;
  70.                 }
  71.         }
  72.  
  73.         m_pOceanRE = GetRenderer() ?
  74.                      static_cast<CREWaterOcean*>(GetRenderer()->EF_CreateRE(eDATA_WaterOcean)) : nullptr;
  75.  
  76.         m_nVertsCount = 0;
  77.         m_nIndicesCount = 0;
  78.  
  79.         m_bOceanFFT = false;
  80. }
  81.  
  82. COcean::~COcean()
  83. {
  84.         for (int32 x = 0; x < CYCLE_BUFFERS_NUM; ++x)
  85.         {
  86.                 if (m_pREOcclusionQueries[x])
  87.                         m_pREOcclusionQueries[x]->Release(true);
  88.         }
  89.  
  90.         m_pBottomCapRenderMesh = NULL;
  91.  
  92.         SAFE_RELEASE(m_pOceanRE);
  93.         for (int i = 0; i < RT_COMMAND_BUF_COUNT; i++)
  94.                 SAFE_RELEASE(m_pWVRE[i]);
  95. }
  96.  
  97. int32 COcean::GetMemoryUsage()
  98. {
  99.         int32 nSize = 0;
  100.  
  101.         nSize += sizeofVector(m_pMeshIndices);
  102.         nSize += sizeofVector(m_pMeshVerts);
  103.         nSize += sizeofVector(m_pBottomCapVerts);
  104.         nSize += sizeofVector(m_pBottomCapIndices);
  105.  
  106.         return nSize;
  107. }
  108.  
  109. void COcean::Update(const SRenderingPassInfo& passInfo)
  110. {
  111.         FUNCTION_PROFILER_3DENGINE;
  112.  
  113.         C3DEngine* p3DEngine = (C3DEngine*)Get3DEngine();
  114.         IRenderer* pRenderer = GetRenderer();
  115.         if (passInfo.IsRecursivePass() || !passInfo.RenderWaterOcean() || !m_pMaterial)
  116.                 return;
  117.  
  118.         const CCamera& rCamera = passInfo.GetCamera();
  119.         int32 nFillThreadID = passInfo.ThreadID();
  120.         uint32 nBufID = passInfo.GetFrameID() % CYCLE_BUFFERS_NUM;
  121.  
  122.         Vec3 vCamPos = rCamera.GetPosition();
  123.         float fWaterLevel = p3DEngine->GetWaterLevel();
  124.  
  125.         // No hardware FFT support
  126.         m_bOceanFFT = false;
  127.         if (GetCVars()->e_WaterOceanFFT && pRenderer->EF_GetShaderQuality(eST_Water) >= eSQ_High)
  128.         {
  129.                 m_bOceanFFT = true;
  130.         }
  131.  
  132.         if (vCamPos.z < fWaterLevel)
  133.         {
  134.                 // if camera is in indoors and lower than ocean level
  135.                 // and exit portals are higher than ocean level - skip ocean rendering
  136.                 CVisArea* pVisArea = (CVisArea*)p3DEngine->GetVisAreaFromPos(vCamPos);
  137.                 if (pVisArea && !pVisArea->IsPortal())
  138.                 {
  139.                         for (int32 i = 0; i < pVisArea->m_lstConnections.Count(); i++)
  140.                         {
  141.                                 if (pVisArea->m_lstConnections[i]->IsConnectedToOutdoor() && pVisArea->m_lstConnections[i]->m_boxArea.min.z < fWaterLevel)
  142.                                         break; // there is portal making ocean visible
  143.  
  144.                                 if (i == pVisArea->m_lstConnections.Count())
  145.                                         return; // ocean surface is not visible
  146.                         }
  147.                 }
  148.         }
  149.  
  150.         bool bWaterVisible = IsVisible(passInfo);
  151.         float _fWaterPlaneSize = rCamera.GetFarPlane();
  152.  
  153.         // Check if water surface occluded
  154.         if (fabs(m_fLastFov - rCamera.GetFov()) < 0.01f && GetCVars()->e_HwOcclusionCullingWater && passInfo.IsGeneralPass())
  155.         {
  156.                 AABB boxOcean(Vec3(vCamPos.x - _fWaterPlaneSize, vCamPos.y - _fWaterPlaneSize, fWaterLevel),
  157.                               Vec3(vCamPos.x + _fWaterPlaneSize, vCamPos.y + _fWaterPlaneSize, fWaterLevel));
  158.  
  159.                 if ((!GetVisAreaManager()->IsOceanVisible() && rCamera.IsAABBVisible_EM(boxOcean)) ||
  160.                     (GetVisAreaManager()->IsOceanVisible() && rCamera.IsAABBVisible_E(boxOcean)))
  161.                 {
  162.                         // make element if not ready
  163.                         if (!m_pREOcclusionQueries[nBufID])
  164.                         {
  165.                                 m_pREOcclusionQueries[nBufID] = (CREOcclusionQuery*)GetRenderer()->EF_CreateRE(eDATA_OcclusionQuery);
  166.                                 m_pREOcclusionQueries[nBufID]->m_pRMBox = (CRenderMesh*)GetObjManager()->GetRenderMeshBox();
  167.                         }
  168.  
  169.                         // get last test result
  170.                         //      if((m_pREOcclusionQueries[nFillThreadID][nBufID]->m_nCheckFrame - passInfo.GetFrameID())<2)
  171.                         {
  172.                                 COcean::m_nVisiblePixelsCount = m_pREOcclusionQueries[nBufID]->m_nVisSamples;
  173.                                 if (COcean::m_nVisiblePixelsCount > 16)
  174.                                 {
  175.                                         m_nLastVisibleFrameId = passInfo.GetFrameID();
  176.                                         bWaterVisible = true;
  177.                                 }
  178.                         }
  179.  
  180.                         // request new test
  181.                         m_pREOcclusionQueries[nBufID]->m_vBoxMin(boxOcean.min.x, boxOcean.min.y, boxOcean.min.z - 1.0f);
  182.                         m_pREOcclusionQueries[nBufID]->m_vBoxMax(boxOcean.max.x, boxOcean.max.y, boxOcean.max.z);
  183.  
  184.                         m_pREOcclusionQueries[nBufID]->mfReadResult_Try(COcean::m_nVisiblePixelsCount);
  185.                         if (!m_pREOcclusionQueries[nBufID]->m_nDrawFrame || m_pREOcclusionQueries[nBufID]->HasSucceeded())
  186.                         {
  187.                                 SShaderItem shItem(m_pShaderOcclusionQuery);
  188.                                 CRenderObject* pObj = GetIdentityCRenderObject(passInfo.ThreadID());
  189.                                 if (!pObj)
  190.                                         return;
  191.                                 GetRenderer()->EF_AddEf(m_pREOcclusionQueries[nBufID], shItem, pObj, passInfo, EFSLIST_WATER_VOLUMES, 0);
  192.                         }
  193.                 }
  194.         }
  195.         else
  196.         {
  197.                 m_nLastVisibleFrameId = passInfo.GetFrameID();
  198.                 bWaterVisible = true;
  199.         }
  200.  
  201.         if (bWaterVisible || vCamPos.z < fWaterLevel)
  202.         {
  203.                 m_p3DEngine->SetOceanRenderFlags(OCR_OCEANVOLUME_VISIBLE);
  204.  
  205.                 // lazy mesh creation
  206.                 if (bWaterVisible)
  207.                 {
  208.                         Create();
  209.                 }
  210.         }
  211. }
  212.  
  213. void COcean::Create()
  214. {
  215.         // Calculate water geometry and update vertex buffers
  216.         int32 nScrGridSizeX = 20 * GetCVars()->e_WaterTessellationAmount;
  217.  
  218.         nScrGridSizeX = (GetCVars()->e_WaterTessellationAmountX && GetCVars()->e_WaterTessellationAmountY) ? GetCVars()->e_WaterTessellationAmountX : nScrGridSizeX;
  219.         int32 nScrGridSizeY = (GetCVars()->e_WaterTessellationAmountX && GetCVars()->e_WaterTessellationAmountY) ? GetCVars()->e_WaterTessellationAmountY : nScrGridSizeX;
  220.  
  221.         // Store permanently the swath width
  222.         static int32 swathWidth = 0;
  223.         static bool bUsingFFT = false;
  224.         static bool bUseTessHW = false;
  225.         bool bUseWaterTessHW;
  226.         GetRenderer()->EF_Query(EFQ_WaterTessellation, bUseWaterTessHW);
  227.  
  228.         if (!bUseWaterTessHW && m_bOceanFFT)
  229.                 nScrGridSizeX = nScrGridSizeY = 20 * 10; // for hi/very specs - use maximum tessellation
  230.  
  231.         // Generate screen space grid
  232.         if ((m_bOceanFFT && bUsingFFT != m_bOceanFFT) || bUseTessHW != bUseWaterTessHW || swathWidth != GetCVars()->e_WaterTessellationSwathWidth || !m_nVertsCount || !m_nIndicesCount || nScrGridSizeX * nScrGridSizeY != m_nPrevGridDim)
  233.         {
  234.                 m_nPrevGridDim = nScrGridSizeX * nScrGridSizeY;
  235.                 m_pMeshVerts.Clear();
  236.                 m_pMeshIndices.Clear();
  237.                 m_nVertsCount = 0;
  238.                 m_nIndicesCount = 0;
  239.  
  240.                 bUsingFFT = m_bOceanFFT;
  241.                 bUseTessHW = bUseWaterTessHW;
  242.                 // Update the swath width
  243.                 swathWidth = GetCVars()->e_WaterTessellationSwathWidth;
  244.  
  245.                 // Render ocean with screen space tessellation
  246.  
  247.                 int32 nScreenY = GetRenderer()->GetHeight();
  248.                 int32 nScreenX = GetRenderer()->GetWidth();
  249.  
  250.                 if (!nScreenY || !nScreenX)
  251.                 {
  252.                         return;
  253.                 }
  254.  
  255.                 float fRcpScrGridSizeX = 1.0f / ((float) nScrGridSizeX - 1);
  256.                 float fRcpScrGridSizeY = 1.0f / ((float) nScrGridSizeY - 1);
  257.  
  258.                 SVF_P3F_C4B_T2F tmp;
  259.                 Vec3 vv;
  260.                 vv.z = 0;
  261.  
  262.                 m_pMeshVerts.reserve(nScrGridSizeX * nScrGridSizeY);
  263.                 m_pMeshIndices.reserve(nScrGridSizeX * nScrGridSizeY);
  264.  
  265.                 // Grid vertex generation
  266.                 for (int32 y(0); y < nScrGridSizeY; ++y)
  267.                 {
  268.                         vv.y = (float) y * fRcpScrGridSizeY;// + fRcpScrGridSize;
  269.  
  270.                         for (int32 x(0); x < nScrGridSizeX; ++x)
  271.                         {
  272.                                 // vert 1
  273.                                 vv.x = (float) x * fRcpScrGridSizeX;// + fRcpScrGridSize;
  274.  
  275.                                 // store in z edges information
  276.                                 float fx = fabs((vv.x) * 2.0f - 1.0f);
  277.                                 float fy = fabs((vv.y) * 2.0f - 1.0f);
  278.                                 //float fEdgeDisplace = sqrt_tpl(fx*fx + fy * fy);//max(fx, fy);
  279.                                 float fEdgeDisplace = max(fx, fy);
  280.                                 //sqrt_tpl(fx*fx + fy * fy);
  281.                                 vv.z = fEdgeDisplace; //!((y==0 ||y == nScrGridSize-1) || (x==0 || x == nScrGridSize-1));
  282.  
  283.                                 int32 n = m_pMeshVerts.Count();
  284.                                 tmp.xyz = vv;
  285.                                 m_pMeshVerts.Add(tmp);
  286.                         }
  287.                 }
  288.  
  289.                 if (bUseTessHW)
  290.                 {
  291.                         // Normal approach
  292.                         int32 nIndex = 0;
  293.                         for (int32 y(0); y < nScrGridSizeY - 1; ++y)
  294.                         {
  295.                                 for (int32 x(0); x < nScrGridSizeX - 1; ++x, ++nIndex)
  296.                                 {
  297.                                         m_pMeshIndices.Add(nScrGridSizeX * y + x);
  298.                                         m_pMeshIndices.Add(nScrGridSizeX * y + x + 1);
  299.                                         m_pMeshIndices.Add(nScrGridSizeX * (y + 1) + x);
  300.  
  301.                                         m_pMeshIndices.Add(nScrGridSizeX * (y + 1) + x);
  302.                                         m_pMeshIndices.Add(nScrGridSizeX * y + x + 1);
  303.                                         m_pMeshIndices.Add(nScrGridSizeX * (y + 1) + x + 1);
  304.  
  305.                                         //m_pMeshIndices.Add( nIndex );
  306.                                         //m_pMeshIndices.Add( nIndex + 1);
  307.                                         //m_pMeshIndices.Add( nIndex + nScrGridSizeX);
  308.  
  309.                                         //m_pMeshIndices.Add( nIndex + nScrGridSizeX);
  310.                                         //m_pMeshIndices.Add( nIndex + 1);
  311.                                         //m_pMeshIndices.Add( nIndex + nScrGridSizeX + 1);
  312.                                 }
  313.                         }
  314.                 }
  315.                 else
  316.                 {
  317.                         // Grid index generation
  318.  
  319.                         if (swathWidth <= 0)
  320.                         {
  321.                                 // Normal approach
  322.                                 int32 nIndex = 0;
  323.                                 for (int32 y(0); y < nScrGridSizeY - 1; ++y)
  324.                                 {
  325.                                         for (int32 x(0); x < nScrGridSizeX; ++x, ++nIndex)
  326.                                         {
  327.                                                 m_pMeshIndices.Add(nIndex);
  328.                                                 m_pMeshIndices.Add(nIndex + nScrGridSizeX);
  329.                                         }
  330.  
  331.                                         if (nScrGridSizeY - 2 > y)
  332.                                         {
  333.                                                 m_pMeshIndices.Add(nIndex + nScrGridSizeY - 1);
  334.                                                 m_pMeshIndices.Add(nIndex);
  335.                                         }
  336.                                 }
  337.                         }
  338.                         else
  339.                         {
  340.                                 // Boustrophedonic walk
  341.                                 //
  342.                                 //  0  1  2  3  4
  343.                                 //  5  6  7  8  9
  344.                                 // 10 11 12 13 14
  345.                                 // 15 16 17 18 19
  346.                                 //
  347.                                 // Should generate the following indices
  348.                                 // 0 5 1 6 2 7 3 8 4 9 9 14 14 9 13 8 12 7 11 6 10 5 5 10 10 15 11 16 12 17 13 18 14 19
  349.                                 //
  350.  
  351.                                 int32 startX = 0, endX = swathWidth - 1;
  352.  
  353.                                 do
  354.                                 {
  355.  
  356.                                         for (int32 y(0); y < nScrGridSizeY - 1; y += 2)
  357.                                         {
  358.                                                 // Forward
  359.                                                 for (int32 x(startX); x <= endX; ++x)
  360.                                                 {
  361.                                                         m_pMeshIndices.Add(y * nScrGridSizeX + x);
  362.                                                         m_pMeshIndices.Add((y + 1) * nScrGridSizeX + x);
  363.                                                 }
  364.  
  365.                                                 // Can we go backwards?
  366.                                                 if (y + 2 < nScrGridSizeY)
  367.                                                 {
  368.                                                         // Restart strip by duplicating last and first of next strip
  369.                                                         m_pMeshIndices.Add((y + 1) * nScrGridSizeX + endX);
  370.                                                         m_pMeshIndices.Add((y + 2) * nScrGridSizeX + endX);
  371.  
  372.                                                         //Backward
  373.                                                         for (int32 x(endX); x >= startX; --x)
  374.                                                         {
  375.                                                                 m_pMeshIndices.Add((y + 2) * nScrGridSizeX + x);
  376.                                                                 m_pMeshIndices.Add((y + 1) * nScrGridSizeX + x);
  377.                                                         }
  378.  
  379.                                                         // Restart strip
  380.                                                         if (y + 2 == nScrGridSizeY - 1 && endX < nScrGridSizeX - 1)
  381.                                                         {
  382.                                                                 if (endX < nScrGridSizeX - 1)
  383.                                                                 {
  384.                                                                         // Need to restart at the top of the next column
  385.                                                                         m_pMeshIndices.Add((nScrGridSizeY - 1) * nScrGridSizeX + startX);
  386.                                                                         m_pMeshIndices.Add(endX);
  387.                                                                 }
  388.                                                         }
  389.                                                         else
  390.                                                         {
  391.                                                                 m_pMeshIndices.Add((y + 1) * nScrGridSizeX + startX);
  392.                                                                 m_pMeshIndices.Add((y + 2) * nScrGridSizeX + startX);
  393.                                                         }
  394.                                                 }
  395.                                                 else
  396.                                                 {
  397.                                                         // We can restart to next column
  398.                                                         if (endX < nScrGridSizeX - 1)
  399.                                                         {
  400.                                                                 // Restart strip for next swath
  401.                                                                 m_pMeshIndices.Add((nScrGridSizeY - 1) * nScrGridSizeX + endX);
  402.                                                                 m_pMeshIndices.Add(endX);
  403.                                                         }
  404.                                                 }
  405.                                         }
  406.  
  407.                                         startX = endX;
  408.                                         endX = startX + swathWidth - 1;
  409.  
  410.                                         if (endX >= nScrGridSizeX) endX = nScrGridSizeX - 1;
  411.  
  412.                                 }
  413.                                 while (startX < nScrGridSizeX - 1);
  414.  
  415.                         }
  416.                 }
  417.  
  418.                 m_nVertsCount = m_pMeshVerts.Count();
  419.                 m_nIndicesCount = m_pMeshIndices.Count();
  420.  
  421.                 m_pOceanRE->Create(m_pMeshVerts.Count(), m_pMeshVerts.GetElements(), m_pMeshIndices.Count(), m_pMeshIndices.GetElements(), sizeof(m_pMeshIndices[0]));
  422.  
  423.                 m_pMeshVerts.Free();
  424.                 m_pMeshIndices.Free();
  425.         }
  426. }
  427.  
  428. void COcean::Render(const SRenderingPassInfo& passInfo)
  429. {
  430.         FUNCTION_PROFILER_3DENGINE;
  431.  
  432.         // if reaches render stage - means ocean is visible
  433.  
  434.         C3DEngine* p3DEngine = (C3DEngine*)Get3DEngine();
  435.         IRenderer* pRenderer(GetRenderer());
  436.  
  437.         int32 nBufID = (passInfo.GetFrameID() & 1);
  438.         Vec3 vCamPos = passInfo.GetCamera().GetPosition();
  439.         float fWaterLevel = p3DEngine->GetWaterLevel();
  440.  
  441.         const int fillThreadID = passInfo.ThreadID();
  442.  
  443.         CRenderObject* pObject = GetRenderer()->EF_GetObject_Temp(fillThreadID);
  444.         if (!pObject)
  445.                 return;
  446.         pObject->m_II.m_Matrix.SetIdentity();
  447.         pObject->m_pRenderNode = this;
  448.  
  449.         m_fLastFov = passInfo.GetCamera().GetFov();
  450.  
  451.         // test for multiple lights and shadows support
  452.  
  453.         SRenderObjData* pOD = pObject->GetObjData();
  454.  
  455.         m_Camera = passInfo.GetCamera();
  456.         pObject->m_fAlpha = 1.f;//m_fWaterTranspRatio;
  457.  
  458.         m_fRECustomData[0] = p3DEngine->m_oceanWindDirection;
  459.         m_fRECustomData[1] = p3DEngine->m_oceanWindSpeed;
  460.         m_fRECustomData[2] = p3DEngine->m_oceanWavesSpeed;
  461.         m_fRECustomData[3] = p3DEngine->m_oceanWavesAmount;
  462.         m_fRECustomData[4] = p3DEngine->m_oceanWavesSize;
  463.  
  464.         sincos_tpl(p3DEngine->m_oceanWindDirection, &m_fRECustomData[6], &m_fRECustomData[5]);
  465.         m_fRECustomData[7] = fWaterLevel;
  466.         m_fRECustomData[8] = m_fRECustomData[9] = m_fRECustomData[10] = m_fRECustomData[11] = 0.0f;
  467.  
  468.         bool isFastpath = GetCVars()->e_WaterOcean == 2;
  469.         bool bUsingMergedFog = false;
  470.  
  471.         {
  472.                 Vec3 camPos(passInfo.GetCamera().GetPosition());
  473.  
  474.                 // Check if we outside water volume - we can enable fast path with merged fog version
  475.                 if (camPos.z - fWaterLevel >= p3DEngine->m_oceanWavesSize)
  476.                 {
  477.                         Vec3 cFinalFogColor = gEnv->p3DEngine->GetSunColor().CompMul(m_p3DEngine->m_oceanFogColor);
  478.                         Vec4 vFogParams = Vec4(cFinalFogColor, max(OCEAN_FOG_DENSITY_MINIMUM, m_p3DEngine->m_oceanFogDensity) * 1.44269502f);// log2(e) = 1.44269502
  479.  
  480.                         m_fRECustomData[8] = vFogParams.x;
  481.                         m_fRECustomData[9] = vFogParams.y;
  482.                         m_fRECustomData[10] = vFogParams.z;
  483.                         m_fRECustomData[11] = vFogParams.w;
  484.                         if (isFastpath)
  485.                                 bUsingMergedFog = true;
  486.                 }
  487.         }
  488.  
  489.         {
  490.                 CMatInfo* pMatInfo = (CMatInfo*)(IMaterial*)m_pMaterial;
  491.                 float fInstanceDistance = GetTerrain()->GetDistanceToSectorWithWater();
  492.                 pMatInfo->PrecacheMaterial(fInstanceDistance, 0, false);
  493.         }
  494.  
  495.         if (!GetCVars()->e_WaterOceanFFT || !m_bOceanFFT)
  496.         {
  497.                 m_pOceanRE->m_oceanParam[fillThreadID].bWaterOceanFFT = false;
  498.         }
  499.         else
  500.         {
  501.                 m_pOceanRE->m_oceanParam[fillThreadID].bWaterOceanFFT = m_bOceanFFT;
  502.         }
  503.  
  504.         pObject->m_pCurrMaterial = m_pMaterial;
  505.         SShaderItem& shaderItem(m_pMaterial->GetShaderItem(0));
  506.         m_pOceanRE->m_CustomData = &m_fRECustomData[0];
  507.         pRenderer->EF_AddEf(m_pOceanRE, shaderItem, pObject, passInfo, EFSLIST_WATER, 0);
  508.  
  509.         if (GetCVars()->e_WaterOceanBottom)
  510.                 RenderBottomCap(passInfo);
  511.  
  512.         if (!bUsingMergedFog)
  513.                 RenderFog(passInfo);
  514. }
  515.  
  516. void COcean::RenderBottomCap(const SRenderingPassInfo& passInfo)
  517. {
  518.         C3DEngine* p3DEngine = (C3DEngine*)Get3DEngine();
  519.  
  520.         Vec3 vCamPos = passInfo.GetCamera().GetPosition();
  521.  
  522.         // Render ocean with screen space tessellation
  523.  
  524.         int32 nScreenY = GetRenderer()->GetHeight();
  525.         int32 nScreenX = GetRenderer()->GetWidth();
  526.  
  527.         if (!nScreenY || !nScreenX)
  528.                 return;
  529.  
  530.         // Calculate water geometry and update vertex buffers
  531.         int32 nScrGridSize = 5;
  532.         float fRcpScrGridSize = 1.0f / (float) nScrGridSize;
  533.  
  534.         if (!m_pBottomCapVerts.Count() || !m_pBottomCapIndices.Count() || nScrGridSize * nScrGridSize != m_pBottomCapVerts.Count())
  535.         {
  536.  
  537.                 m_pBottomCapVerts.Clear();
  538.                 m_pBottomCapIndices.Clear();
  539.  
  540.                 SVF_P3F_C4B_T2F tmp;
  541.                 Vec3 vv;
  542.                 vv.z = 0;
  543.  
  544.                 // Grid vertex generation
  545.                 for (int32 y(0); y < nScrGridSize; ++y)
  546.                 {
  547.                         vv.y = (float) y * fRcpScrGridSize + fRcpScrGridSize;
  548.                         for (int32 x(0); x < nScrGridSize; ++x)
  549.                         {
  550.                                 vv.x = (float) x * fRcpScrGridSize + fRcpScrGridSize;
  551.                                 tmp.xyz = vv;
  552.                                 m_pBottomCapVerts.Add(tmp);
  553.                         }
  554.                 }
  555.  
  556.                 // Normal approach
  557.                 int32 nIndex = 0;
  558.                 for (int32 y(0); y < nScrGridSize - 1; ++y)
  559.                 {
  560.                         for (int32 x(0); x < nScrGridSize; ++x, ++nIndex)
  561.                         {
  562.                                 m_pBottomCapIndices.Add(nIndex);
  563.                                 m_pBottomCapIndices.Add(nIndex + nScrGridSize);
  564.                         }
  565.  
  566.                         if (nScrGridSize - 2 > y)
  567.                         {
  568.                                 m_pBottomCapIndices.Add(nIndex + nScrGridSize - 1);
  569.                                 m_pBottomCapIndices.Add(nIndex);
  570.                         }
  571.                 }
  572.  
  573.                 m_pBottomCapRenderMesh = GetRenderer()->CreateRenderMeshInitialized(
  574.                   m_pBottomCapVerts.GetElements(),
  575.                   m_pBottomCapVerts.Count(),
  576.                   eVF_P3F_C4B_T2F,
  577.                   m_pBottomCapIndices.GetElements(),
  578.                   m_pBottomCapIndices.Count(),
  579.                   prtTriangleStrip,
  580.                   "OceanBottomGrid", "OceanBottomGrid",
  581.                   eRMT_Static);
  582.  
  583.                 m_pBottomCapRenderMesh->SetChunk(m_pBottomCapMaterial, 0, m_pBottomCapVerts.Count(), 0, m_pBottomCapIndices.Count(), 1.0f);
  584.         }
  585.  
  586.         CRenderObject* pObject = GetRenderer()->EF_GetObject_Temp(passInfo.ThreadID());
  587.         if (!pObject)
  588.                 return;
  589.         pObject->m_II.m_Matrix.SetIdentity();
  590.         pObject->m_pRenderNode = this;
  591.  
  592.         // make distance to water level near to zero
  593.         m_pBottomCapRenderMesh->SetBBox(vCamPos, vCamPos);
  594.  
  595.         m_Camera = passInfo.GetCamera();
  596.         pObject->m_fAlpha = 1.f;
  597.  
  598.         m_pBottomCapRenderMesh->AddRenderElements(m_pBottomCapMaterial, pObject, passInfo, EFSLIST_GENERAL, 0);
  599. }
  600.  
  601. void COcean::RenderFog(const SRenderingPassInfo& passInfo)
  602. {
  603.         if (!GetCVars()->e_Fog || !GetCVars()->e_FogVolumes)
  604.                 return;
  605.  
  606.         IRenderer* pRenderer(GetRenderer());
  607.         C3DEngine* p3DEngine(Get3DEngine());
  608.  
  609.         const int fillThreadID = passInfo.ThreadID();
  610.  
  611.         CRenderObject* pROVol(pRenderer->EF_GetObject_Temp(fillThreadID));
  612.         if (!pROVol)
  613.                 return;
  614.  
  615.         bool isFastpath = GetCVars()->e_WaterOcean == 2;
  616.         bool isLowSpec(GetCVars()->e_ObjQuality == CONFIG_LOW_SPEC || isFastpath);
  617.         if (pROVol && m_pWVRE[fillThreadID] && ((!isLowSpec && m_pFogIntoMat && m_pFogOutofMat) ||
  618.                                                 (isLowSpec && m_pFogIntoMatLowSpec && m_pFogOutofMatLowSpec)))
  619.         {
  620.                 Vec3 camPos(passInfo.GetCamera().GetPosition());
  621.                 float waterLevel(p3DEngine->GetWaterLevel());
  622.                 Vec3 planeOrigin(camPos.x, camPos.y, waterLevel);
  623.  
  624.                 // fill water volume param structure
  625.                 m_wvParams[fillThreadID].m_center = planeOrigin;
  626.                 m_wvParams[fillThreadID].m_fogPlane.Set(Vec3(0, 0, 1), -waterLevel);
  627.  
  628.                 float distCamToFogPlane(camPos.z + m_wvParams[fillThreadID].m_fogPlane.d);
  629.                 m_wvParams[fillThreadID].m_viewerCloseToWaterPlane = (distCamToFogPlane) < 0.5f;
  630.                 m_wvParams[fillThreadID].m_viewerInsideVolume = distCamToFogPlane < 0.00f;
  631.                 m_wvParams[fillThreadID].m_viewerCloseToWaterVolume = true;
  632.  
  633.                 if (!isFastpath || (distCamToFogPlane < p3DEngine->m_oceanWavesSize))
  634.                 {
  635.                         if (isLowSpec)
  636.                         {
  637.                                 m_wvParams[fillThreadID].m_fogColor = m_p3DEngine->m_oceanFogColor;
  638.                                 m_wvParams[fillThreadID].m_fogDensity = m_p3DEngine->m_oceanFogDensity;
  639.  
  640.                                 m_wvoParams[fillThreadID].m_fogColor = Vec3(0, 0, 0);        // not needed for low spec
  641.                                 m_wvoParams[fillThreadID].m_fogColorShallow = Vec3(0, 0, 0); // not needed for low spec
  642.                                 m_wvoParams[fillThreadID].m_fogDensity = 0;                  // not needed for low spec
  643.  
  644.                                 m_pWVRE[fillThreadID]->m_pOceanParams = 0;
  645.                         }
  646.                         else
  647.                         {
  648.                                 m_wvParams[fillThreadID].m_fogColor = Vec3(0, 0, 0); // not needed, we set ocean specific params below
  649.                                 m_wvParams[fillThreadID].m_fogDensity = 0;           // not needed, we set ocean specific params below
  650.  
  651.                                 m_wvoParams[fillThreadID].m_fogColor = m_p3DEngine->m_oceanFogColor;
  652.                                 m_wvoParams[fillThreadID].m_fogColorShallow = m_p3DEngine->m_oceanFogColorShallow;
  653.                                 m_wvoParams[fillThreadID].m_fogDensity = max(OCEAN_FOG_DENSITY_MINIMUM, m_p3DEngine->m_oceanFogDensity);
  654.  
  655.                                 m_pWVRE[fillThreadID]->m_pOceanParams = &m_wvoParams[fillThreadID];
  656.                         }
  657.  
  658.                         // tessellate plane
  659.                         float planeSize(2.0f * passInfo.GetCamera().GetFarPlane());
  660.                         size_t subDivSize(min(64, 1 + (int32) (planeSize / 512.0f)));
  661.                         if (isFastpath)
  662.                                 subDivSize = 4;
  663.  
  664.                         size_t numSubDivVerts((subDivSize + 1) * (subDivSize + 1));
  665.  
  666.                         if (m_wvVertices[fillThreadID].size() != numSubDivVerts)
  667.                         {
  668.                                 m_wvVertices[fillThreadID].resize(numSubDivVerts);
  669.                                 m_wvParams[fillThreadID].m_pVertices = &m_wvVertices[fillThreadID][0];
  670.                                 m_wvParams[fillThreadID].m_numVertices = m_wvVertices[fillThreadID].size();
  671.  
  672.                                 m_wvIndices[fillThreadID].resize(subDivSize * subDivSize * 6);
  673.                                 m_wvParams[fillThreadID].m_pIndices = &m_wvIndices[fillThreadID][0];
  674.                                 m_wvParams[fillThreadID].m_numIndices = m_wvIndices[fillThreadID].size();
  675.  
  676.                                 size_t ind(0);
  677.                                 for (uint32 y(0); y < subDivSize; ++y)
  678.                                 {
  679.                                         for (uint32 x(0); x < subDivSize; ++x, ind += 6)
  680.                                         {
  681.                                                 m_wvIndices[fillThreadID][ind + 0] = static_cast<uint16>((y) * (subDivSize + 1) + (x));
  682.                                                 m_wvIndices[fillThreadID][ind + 1] = static_cast<uint16>((y) * (subDivSize + 1) + (x + 1));
  683.                                                 m_wvIndices[fillThreadID][ind + 2] = static_cast<uint16>((y + 1) * (subDivSize + 1) + (x + 1));
  684.  
  685.                                                 m_wvIndices[fillThreadID][ind + 3] = static_cast<uint16>((y) * (subDivSize + 1) + (x));
  686.                                                 m_wvIndices[fillThreadID][ind + 4] = static_cast<uint16>((y + 1) * (subDivSize + 1) + (x + 1));
  687.                                                 m_wvIndices[fillThreadID][ind + 5] = static_cast<uint16>((y + 1) * (subDivSize + 1) + (x));
  688.                                         }
  689.                                 }
  690.                         }
  691.                         {
  692.                                 float xyDelta(2.0f * planeSize / (float) subDivSize);
  693.                                 float zDelta(waterLevel - camPos.z);
  694.  
  695.                                 size_t ind(0);
  696.                                 float yd(-planeSize);
  697.                                 for (uint32 y(0); y <= subDivSize; ++y, yd += xyDelta)
  698.                                 {
  699.                                         float xd(-planeSize);
  700.                                         for (uint32 x(0); x <= subDivSize; ++x, xd += xyDelta, ++ind)
  701.                                         {
  702.                                                 m_wvVertices[fillThreadID][ind].xyz = Vec3(xd, yd, zDelta);
  703.                                                 m_wvVertices[fillThreadID][ind].st = Vec2(0, 0);
  704.                                         }
  705.                                 }
  706.                         }
  707.  
  708.                         // fill in data for render object
  709.                         pROVol->m_II.m_Matrix.SetIdentity();
  710.                         pROVol->m_fSort = 0;
  711.  
  712.                         auto pMaterial =
  713.                                 m_wvParams[fillThreadID].m_viewerInsideVolume
  714.                                 ? (isLowSpec ? m_pFogOutofMatLowSpec.get() : m_pFogOutofMat.get())
  715.                                 : (isLowSpec ? m_pFogIntoMatLowSpec.get() : m_pFogIntoMat.get());
  716.  
  717.                         pROVol->m_pCurrMaterial = pMaterial;
  718.  
  719.                         // get shader item
  720.                         SShaderItem& shaderItem(pMaterial->GetShaderItem(0));
  721.  
  722.                         // add to renderer
  723.                         pRenderer->EF_AddEf(m_pWVRE[fillThreadID], shaderItem, pROVol, passInfo, EFSLIST_WATER_VOLUMES, distCamToFogPlane < -0.1f);
  724.                 }
  725.         }
  726. }
  727.  
  728. bool COcean::IsVisible(const SRenderingPassInfo& passInfo)
  729. {
  730.         if (abs(m_nLastVisibleFrameId - passInfo.GetFrameID()) <= 2)
  731.                 m_fLastVisibleFrameTime = 0.0f;
  732.  
  733.         ITimer* pTimer(gEnv->pTimer);
  734.         m_fLastVisibleFrameTime += gEnv->pTimer->GetFrameTime();
  735.  
  736.         if (m_fLastVisibleFrameTime > 2.0f)                                 // at least 2 seconds
  737.                 return (abs(m_nLastVisibleFrameId - passInfo.GetFrameID()) < 64); // and at least 64 frames
  738.  
  739.         return true; // keep water visible for a couple frames - or at least 1 second - minimizes popping during fast camera movement
  740. }
  741.  
  742. void COcean::SetTimer(ITimer* pTimer)
  743. {
  744.         assert(pTimer);
  745.         m_pOceanTimer = pTimer;
  746. }
  747.  
  748. float COcean::GetWave(const Vec3& pPos, int32 nFrameID)
  749. {
  750.         // todo: optimize...
  751.  
  752.         IRenderer* pRenderer(GetRenderer());
  753.         if (!pRenderer)
  754.                 return 0.0f;
  755.  
  756.         EShaderQuality nShaderQuality = pRenderer->EF_GetShaderQuality(eST_Water);
  757.  
  758.         if (!m_pOceanTimer || nShaderQuality < eSQ_High)
  759.                 return 0.0f;
  760.  
  761.         // Return height - matching computation on GPU
  762.  
  763.         C3DEngine* p3DEngine(Get3DEngine());
  764.  
  765.         bool bOceanFFT = false;
  766.         if (GetCVars()->e_WaterOceanFFT && nShaderQuality >= eSQ_High)
  767.                 bOceanFFT = true;
  768.  
  769.         if (bOceanFFT)
  770.         {
  771.                 Vec4 pDispPos = Vec4(0, 0, 0, 0);
  772.  
  773.                 if (m_pOceanRE)
  774.                 {
  775.                         // Get height from FFT grid
  776.  
  777.                         Vec4* pGridFFT = m_pOceanRE->GetDisplaceGrid();
  778.                         if (!pGridFFT)
  779.                                 return 0.0f;
  780.  
  781.                         // match scales used in shader
  782.                         float fScaleX = pPos.x * 0.0125f * p3DEngine->m_oceanWavesAmount * 1.25f;
  783.                         float fScaleY = pPos.y * 0.0125f * p3DEngine->m_oceanWavesAmount * 1.25f;
  784.  
  785.                         float fu = fScaleX * 64.0f;
  786.                         float fv = fScaleY * 64.0f;
  787.                         int32 u1 = ((int32)fu) & 63;
  788.                         int32 v1 = ((int32)fv) & 63;
  789.                         int32 u2 = (u1 + 1) & 63;
  790.                         int32 v2 = (v1 + 1) & 63;
  791.  
  792.                         // Fractional parts
  793.                         float fracu = fu - floorf(fu);
  794.                         float fracv = fv - floorf(fv);
  795.  
  796.                         // Get weights
  797.                         float w1 = (1 - fracu) * (1 - fracv);
  798.                         float w2 = fracu * (1 - fracv);
  799.                         float w3 = (1 - fracu) * fracv;
  800.                         float w4 = fracu * fracv;
  801.  
  802.                         Vec4 h1 = pGridFFT[u1 + v1 * 64];
  803.                         Vec4 h2 = pGridFFT[u2 + v1 * 64];
  804.                         Vec4 h3 = pGridFFT[u1 + v2 * 64];
  805.                         Vec4 h4 = pGridFFT[u2 + v2 * 64];
  806.  
  807.                         // scale and sum the four heights
  808.                         pDispPos = h1 * w1 + h2 * w2 + h3 * w3 + h4 * w4;
  809.                 }
  810.  
  811.                 // match scales used in shader
  812.                 return pDispPos.z * 0.06f * p3DEngine->m_oceanWavesSize;
  813.         }
  814.  
  815.         // constant to scale down values a bit
  816.         const float fAnimAmplitudeScale = 1.0f / 5.0f;
  817.  
  818.         static int32 s_nFrameID = 0;
  819.         static Vec3 vFlowDir = Vec3(0, 0, 0);
  820.         static Vec4 vFrequencies = Vec4(0, 0, 0, 0);
  821.         static Vec4 vPhases = Vec4(0, 0, 0, 0);
  822.         static Vec4 vAmplitudes = Vec4(0, 0, 0, 0);
  823.  
  824.         // Update per-frame data
  825.         if (s_nFrameID != nFrameID)
  826.         {
  827.                 sincos_tpl(p3DEngine->m_oceanWindDirection, &vFlowDir.y, &vFlowDir.x);
  828.                 vFrequencies = Vec4(0.233f, 0.455f, 0.6135f, -0.1467f) * p3DEngine->m_oceanWavesSpeed * 5.0f;
  829.                 vPhases = Vec4(0.1f, 0.159f, 0.557f, 0.2199f) * p3DEngine->m_oceanWavesAmount;
  830.                 vAmplitudes = Vec4(1.0f, 0.5f, 0.25f, 0.5f) * p3DEngine->m_oceanWavesSize;
  831.  
  832.                 s_nFrameID = nFrameID;
  833.         }
  834.  
  835.         float fPhase = sqrt_tpl(pPos.x * pPos.x + pPos.y * pPos.y);
  836.         Vec4 vCosPhase = vPhases * (fPhase + pPos.x);
  837.  
  838.         Vec4 vWaveFreq = vFrequencies * m_pOceanTimer->GetCurrTime();
  839.  
  840.         Vec4 vCosWave = Vec4(cos_tpl(vWaveFreq.x * vFlowDir.x + vCosPhase.x),
  841.                              cos_tpl(vWaveFreq.y * vFlowDir.x + vCosPhase.y),
  842.                              cos_tpl(vWaveFreq.z * vFlowDir.x + vCosPhase.z),
  843.                              cos_tpl(vWaveFreq.w * vFlowDir.x + vCosPhase.w));
  844.  
  845.         Vec4 vSinPhase = vPhases * (fPhase + pPos.y);
  846.         Vec4 vSinWave = Vec4(sin_tpl(vWaveFreq.x * vFlowDir.y + vSinPhase.x),
  847.                              sin_tpl(vWaveFreq.y * vFlowDir.y + vSinPhase.y),
  848.                              sin_tpl(vWaveFreq.z * vFlowDir.y + vSinPhase.z),
  849.                              sin_tpl(vWaveFreq.w * vFlowDir.y + vSinPhase.w));
  850.  
  851.         return (vCosWave.Dot(vAmplitudes) + vSinWave.Dot(vAmplitudes)) * fAnimAmplitudeScale;
  852. }
  853.  
  854. uint32 COcean::GetVisiblePixelsCount()
  855. {
  856.         return m_nVisiblePixelsCount;
  857. }
  858.  
  859. void COcean::OffsetPosition(const Vec3& delta)
  860. {
  861. #ifdef SEG_WORLD
  862.         if (m_pTempData) m_pTempData->OffsetPosition(delta);
  863. #endif
  864. }
  865.  
  866. void COcean::FillBBox(AABB& aabb)
  867. {
  868.         aabb = COcean::GetBBox();
  869. }
  870.  
  871. EERType COcean::GetRenderNodeType()
  872. {
  873.         return eERType_WaterVolume;
  874. }
  875.  
  876. Vec3 COcean::GetPos(bool) const
  877. {
  878.         return Vec3(0, 0, 0);
  879. }
  880.  
  881. IMaterial* COcean::GetMaterial(Vec3* pHitPos) const
  882. {
  883.         return m_pMaterial;
  884. }
  885.  
downloadterrain_water_quad.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top