//////////////////////////////////////////////////////////////////////////// // // Crytek Engine Source File. // Copyright (C), Crytek Studios, 2002. // ------------------------------------------------------------------------- // File name: 3denginerender.cpp // Version: v1.00 // Created: 28/5/2001 by Vladimir Kajalin // Compilers: Visual Studio.NET // Description: rendering // ------------------------------------------------------------------------- // History: // //////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "3dEngine.h" #include "objman.h" #include "visareas.h" #include "terrain_water.h" #include "partman.h" #include "DecalManager.h" #include "bflyes.h" #include "rain.h" #include "../RenderDll/Common/RendElements/CREScreenCommon.h" #include "cbuffer.h" #include "watervolumes.h" //////////////////////////////////////////////////////////////////////////////////////// // RenderScene //////////////////////////////////////////////////////////////////////////////////////// void C3DEngine::Draw() { m_bProfilerEnabled = GetISystem()->GetIProfileSystem()->IsProfiling(); FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE ); if (!m_bEnabled) { return; } #if !defined(LINUX) if(GetCVars()->e_sleep) Sleep(GetCVars()->e_sleep); #endif GetTimer()->MeasureTime("EnterDraw"); m_nRenderFrameID = GetRenderer()->GetFrameID(); if(IsCameraAnd3DEngineInvalid(GetViewCamera(), "C3DEngine::Draw")) return; UpdateScene(); Get3DEngine()->CheckPhysicalized(GetViewCamera().GetPos()-Vec3d(2,2,2),GetViewCamera().GetPos()+Vec3d(2,2,2)); if(GetCVars()->e_hires_screenshoot) { if(GetRenderer()->GetType()==R_GL_RENDERER) MakeHiResScreenShot(); else { GetLog()->Log("\003e_hires_screenshoot is suported only in OpenGL"); GetCVars()->e_hires_screenshoot=0; } } m_pObjManager->m_fMaxViewDistanceScale = 1.f; if (GetSystem()->IsDedicated()) RenderScene(0); else { // bad solution - only to get CryVision working properly if(*((bool*)m_pREScreenProcess->mfGetParameter(SCREENPROCESS_NIGHTVISION, SCREENPROCESS_ACTIVE))) { static ICVar *pCVVolFog=GetConsole()->GetCVar("r_VolumetricFog"); int e_shadow_maps=GetCVars()->e_shadow_maps; GetCVars()->e_shadow_maps=0; int e_stencil_shadows=GetCVars()->e_stencil_shadows; GetCVars()->e_stencil_shadows=0; int r_VolumetricFog=pCVVolFog->GetIVal(); pCVVolFog->Set(0); RenderScene(-1); GetCVars()->e_shadow_maps=e_shadow_maps; GetCVars()->e_stencil_shadows=e_stencil_shadows; pCVVolFog->Set(r_VolumetricFog); } else { RenderScene(-1); } } CaptureFrameBufferToFile(); GetRenderer()->EF_ClearLightsList(); // fog addons //GetRenderer()->ResetToDefault(); /* m_pTerrain->m_pWater->DrawUnderWaterFog( m_arrUnderWaterPlaneColor[0], m_arrUnderWaterPlaneColor[1], m_arrUnderWaterPlaneColor[2], m_arrUnderWaterPlaneColor[3]);*/ // streaming state if(GetCVars()->e_terrain_debug) if (CStatObj::m_fStreamingTimePerFrame>0 || (IsOutdoorVisible() && m_pTerrain && m_pTerrain->IsStreamingNow() && GetCVars()->e_terrain && !GetCVars()->e_hires_screenshoot)) { //GetRenderer()->ResetToDefault(); GetRenderer()->Draw2dImage(800-8,0,8,8,m_nStreamingIconTexID); } // black quad for simple shadow volumes // if(GetCVars()->e_stencil_shadows) //{ // GetRenderer()->ResetToDefault(); // GetRenderer()->DrawTransparentQuad2D(0.5); // } // c-buffer debug info if(m_pObjManager && m_pObjManager->m_pCoverageBuffer && GetCVars()->e_cbuffer>=2) { m_pObjManager->m_pCoverageBuffer->DrawDebug(GetCVars()->e_cbuffer-1); GetTimer()->MeasureTime("3CBDebug"); } GetTimer()->MeasureTime("3DrawEnd"); /* #ifdef _DEBUG #ifdef WIN32 if(GetCVars()->e_portals>1) { Sleep(20); GetTimer()->MeasureTime("3Sleep(20)"); } #endif #endif */ // Unload old stuff if(GetCVars()->e_stream_areas) { if(m_pTerrain) m_pTerrain->CheckUnload(); if(m_pVisAreaManager) m_pVisAreaManager->CheckUnload(); } if(m_pObjManager && GetCVars()->e_stream_cgf) m_pObjManager->CheckUnload(); /* CSectorInfo * pSectorInfo = m_pTerrain ? m_pTerrain->GetSecInfo(GetViewCamera().GetPos()) : 0; uchar * pImage = new uchar[256*256*4]; if(pSectorInfo) MakeSectorLightMap(pSectorInfo->m_nOriginX, pSectorInfo->m_nOriginY, pImage, 256); delete [] pImage;*/ } void C3DEngine::RenderScene(unsigned int dwDrawFlags) { FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE ); if (!m_pTerrain) return; #ifdef WIN64 #pragma warning( push ) //AMD Port #pragma warning( disable : 4311 ) #endif // it's correct only before StartEf() int nRecursionLevel = (int)GetRenderer()->EF_Query(EFQ_RecurseLevel); assert(nRecursionLevel>=0); m_pObjManager->m_nRenderStackLevel = m_pTerrain->m_nRenderStackLevel = nRecursionLevel; if(m_pObjManager->m_nRenderStackLevel<0 || m_pObjManager->m_nRenderStackLevel>1) return; #ifdef WIN64 #pragma warning( pop ) //AMD Port #endif GetRenderer()->EF_StartEf(); GetTimer()->MeasureTime("3StartEf"); //////////////////////////////////////////////////////////////////////////////////////// // Add lsources to the renderer and register into sectors //////////////////////////////////////////////////////////////////////////////////////// //if(dwDrawFlags & DLD_ADD_LIGHTSOURCES) { // Add lsources to the renderer and register into sectors GetRenderer()->EF_ClearLightsList(); UpdateLightSources(); PrepareLightSourcesForRendering(); GetTimer()->MeasureTime("3LSources"); } // prepare coverage buffer m_pObjManager->m_pCoverageBuffer->BeginFrame(GetViewCamera()); //////////////////////////////////////////////////////////////////////////////////////// // Add render elements for indoor //////////////////////////////////////////////////////////////////////////////////////// CCamera InitialCam = GetViewCamera(); // m_lstPortalCamera.Clear(); // m_bCameraInsideBuilding = false; m_pDecalManager->SubmitLightHolesToRenderer(); //////////////////////////////////////////////////////////////////////////////////////// // Add render elements for outdoor //////////////////////////////////////////////////////////////////////////////////////// { for(int i=0; im_lstLightEntities[i].Clear(); } // for(int i=0; im_lstShadowEntities[i].Clear(); CStatObj::m_fStreamingTimePerFrame-=CGF_STREAMING_MAX_TIME_PER_FRAME; if(CStatObj::m_fStreamingTimePerFrame<0) CStatObj::m_fStreamingTimePerFrame=0; if(CStatObj::m_fStreamingTimePerFrame>0.25f) CStatObj::m_fStreamingTimePerFrame=0.25f; assert(Cry3DEngineBase::m_nRenderStackLevel>=0 && Cry3DEngineBase::m_nRenderStackLevel<=1); m_pObjManager->m_dwRecursionDrawFlags[Cry3DEngineBase::m_nRenderStackLevel] = dwDrawFlags; m_pVisAreaManager->DrawOcclusionAreasIntoCBuffer(m_pObjManager->m_pCoverageBuffer); GetTimer()->MeasureTime("3OcclAreas"); // draw entities inside vis areas m_pVisAreaManager->Render(m_pObjManager); GetTimer()->MeasureTime("3VisAreas"); if(m_pObjManager) m_pObjManager->PreloadNearObjects(); if(GetCVars()->e_stream_preload_textures && Cry3DEngineBase::m_nRenderStackLevel==0) { m_fPreloadStartTime = GetCurTimeSec(); bool bPreloadOutdoor = m_pVisAreaManager->PreloadResources(); GetTimer()->MeasureTime("3TexPrelInd"); // for(int p=0; p<16; p++) if(bPreloadOutdoor && m_pTerrain->PreloadResources() && m_pSHSky) { FRAME_PROFILER( "Renderer::EF_PrecacheResource", GetSystem(), PROFILE_RENDERER ); GetRenderer()->EF_PrecacheResource(m_pSHSky, 0, 1.f, 0); } GetTimer()->MeasureTime("3TexPrelOut"); } /* // precache tarrain data if camera was teleported more than 32 meters if(m_pTerrain->m_nRenderStackLevel==0) { if(GetDistance(m_pTerrain->m_vPrevCameraPos, GetViewCamera().GetPos()) > 32) m_pTerrain->PreCacheArea(GetViewCamera().GetPos(), GetViewCamera().GetZMax()*1.5f); m_pTerrain->m_vPrevCameraPos = GetViewCamera().GetPos(); } */ // clear sprites list if(m_nRenderStackLevel>=0 && m_nRenderStackLevel<=1) { list2 * pList = &m_pObjManager->m_lstFarObjects[m_nRenderStackLevel]; pList->Clear(); } else assert(0); CCamera prevCam = GetViewCamera(); if (IsOutdoorVisible()) { if (m_pVisAreaManager->m_lstOutdoorPortalCameras.Count() && (m_pVisAreaManager->m_pCurArea || m_pVisAreaManager->m_pCurPortal)) GetViewCamera() = m_pVisAreaManager->m_lstOutdoorPortalCameras[0]; if(m_pVisAreaManager->IsOutdoorAreasVisible()) { if(GetCVars()->e_out_space) RenderOutSpace(); else RenderSkyBox(m_pSHSky); } // terrain and tree sprites m_pTerrain->m_bCameraInsideBuilding = (m_pVisAreaManager->m_pCurArea || m_pVisAreaManager->m_pCurPortal); if(m_pVisAreaManager->IsOutdoorAreasVisible()) m_pTerrain->RenderTerrain(m_pObjManager, dwDrawFlags); GetTimer()->MeasureTime("3Terrain"); // m_pObjManager->m_lstStatShadowsBuffer.Clear(); m_pObjManager->m_fWindForce = m_vWindForce.Length()/53.33f; // if(m_pVisAreaManager->IsOutdoorAreasVisible()) // m_pTerrain->RenderStaticObjects(m_pObjManager); //GetTimer()->MeasureTime("3statobj"); // draw terrain water and beach if( m_pVisAreaManager->IsOutdoorAreasVisible() && ( dwDrawFlags & DLD_TERRAIN_WATER) && m_pTerrain->m_fDistanceToSectorWithWater>=0 && m_pTerrain->GetWaterLevel() && m_pTerrain->m_bOceanIsVisibe && m_bOcean) { Vec3d vBoxMin(-2048.f,-2048.f,-2048.f); Vec3d vBoxMax(GetTerrainSize()+2048.f,GetTerrainSize()+2048.f,m_pTerrain->GetWaterLevel()); if(GetViewCamera().IsAABBVisible_exact(AABB(vBoxMin,vBoxMax))) m_pTerrain->RenderTerrainWater(m_bShore); } if(m_pTerrain && m_pTerrain->m_pWater) m_pTerrain->m_pWater->SetLastFov(GetViewCamera().GetFov()); GetTimer()->MeasureTime("3Wtr&Bch"); // if(m_pObjManager->m_pCWaterVolumes && m_pVisAreaManager->IsOutdoorAreasVisible()) // m_pObjManager->m_pCWaterVolumes->RenderWaterVolumes(); // GetTimer()->MeasureTime("3WaterVol"); // draw sprites at far distance if(dwDrawFlags & DLD_FAR_SPRITES) m_pObjManager->RenderFarObjects(); GetTimer()->MeasureTime("3Far"); // render entities not registered in sectors m_pTerrain->RenderEntitiesOutOfTheMap(m_pObjManager); GetTimer()->MeasureTime("3EntOut"); // render terrain ground if(dwDrawFlags & DLD_TERRAIN_FULLRES)// && !m_pTerrain->m_nRenderStackLevel) m_pTerrain->DrawVisibleSectors(); else m_pTerrain->RenderReflectedTerrain(); GetTimer()->MeasureTime("3TerVisSec"); // unload far and old sectors if(!m_pTerrain->m_nRenderStackLevel) m_pTerrain->UnloadOldSectors(m_fMaxViewDist); GetTimer()->MeasureTime("3UnlOldSecs"); if((dwDrawFlags & DLD_TERRAIN_LIGHT) && m_pTerrain && m_pVisAreaManager->IsOutdoorAreasVisible()) { // render terrain light passes FRAME_PROFILER( "TerrainLightPasses", GetSystem(), PROFILE_RENDERER ); for (int nLightId=0; nLightId=0 && !(m_lstDynLights[nLightId].m_Flags & DLF_DIRECTIONAL)) { if(m_lstDynLights[nLightId].m_Flags & DLF_CASTSHADOW_VOLUME) m_pObjManager->m_lstLightEntities[nLightId].Add((IEntityRender*)-1); else if(m_pVisAreaManager->IsOutdoorAreasVisible()) { if( (!(m_lstDynLights[nLightId].m_Flags & DLF_DIRECTIONAL)) && IsSphereVisibleOnTheScreen(m_lstDynLights[nLightId].m_Origin, m_lstDynLights[nLightId].m_fRadius, 0)) m_pTerrain->RenderDLightOnHeightMap(&m_lstDynLights[nLightId]); } } } GetTimer()->MeasureTime("3TerLSrc"); } } else if(m_pVisAreaManager->IsSkyVisible()) RenderSkyBox(m_pSHSky); GetViewCamera() = prevCam; // water volumes if(m_pObjManager->m_pCWaterVolumes && !m_pObjManager->m_nRenderStackLevel) m_pObjManager->m_pCWaterVolumes->RenderWaterVolumes(m_pVisAreaManager->IsOutdoorAreasVisible()); GetTimer()->MeasureTime("3WaterVol"); // render/generate shadow maps from entities m_pObjManager->RenderEntitiesShadowMapsOnTerrain(false, m_pREShadowMapGenerator); GetTimer()->MeasureTime("3EntSMaps"); if(GetCVars()->e_stencil_shadows) { m_pObjManager->DrawEntitiesLightPass(); GetTimer()->MeasureTime("3EntLPass"); } // render terrain detail textures if(m_pVisAreaManager->IsOutdoorAreasVisible()) if(dwDrawFlags & DLD_DETAIL_TEXTURES) m_pTerrain->RenderDetailTextures(m_fFogNearDist,m_fFogFarDist); GetTimer()->MeasureTime("3TerDetTex"); GetViewCamera() = InitialCam; m_pDecalManager->Render(); GetTimer()->MeasureTime("3Decals"); if(dwDrawFlags & DLD_PARTICLES) { RenderTerrainParticles(); m_pPartManager->Render(m_pObjManager, m_pTerrain); GetTimer()->MeasureTime("3Part3d"); } if (m_pRenderCallbackFunc && GetCVars()->e_entities && !m_pObjManager->m_nRenderStackLevel) if(m_pObjManager && m_pVisAreaManager->IsOutdoorAreasVisible()) { FRAME_PROFILER( "RenderScene::m_pRenderCallbackFunc", GetSystem(), PROFILE_EDITOR ); m_pRenderCallbackFunc(m_pRenderCallbackParams); GetTimer()->MeasureTime("3RendCB"); } RenderVolumeFogTopPlane(); GetTimer()->MeasureTime("3UW&FP"); if(m_pSHFullScreenQuad && !m_pObjManager->m_nRenderStackLevel) { DrawFullScreenQuad(m_pSHFullScreenQuad, false, eS_HeatVision); GetTimer()->MeasureTime("32dquad"); } if(GetCVars()->e_rain_amount>1) GetCVars()->e_rain_amount=1; else if(GetCVars()->e_rain_amount<0) GetCVars()->e_rain_amount=0; if(GetCVars()->e_rain_amount && (m_pVisAreaManager->IsOutdoorAreasVisible())) { bool bCameraInOutdoors = !m_pVisAreaManager->m_pCurArea && !(m_pVisAreaManager->m_pCurPortal && m_pVisAreaManager->m_pCurPortal->m_lstConnections.Count()>1); if(bCameraInOutdoors) DrawFullScreenQuad(m_pSHRainMap, false); } //----------------------------------------------------------------------- ProcessScreenEffects(); SetupDistanceFog(); if(!m_pTerrain->m_nRenderStackLevel) SetupClearColor(); IRenderer * ppp = GetRenderer(); { FRAME_PROFILER( "Renderer::EF_EndEf3D", GetSystem(), PROFILE_RENDERER ); if(!m_nRenderStackLevel) { if(GetCVars()->e_widescreen) { // set view port to 16/9 mode int nVPSizeX = GetRenderer()->GetWidth(); int nVPSizeY = GetRenderer()->GetWidth()*9/16; int nOffsetY = (GetRenderer()->GetHeight()-nVPSizeY)/2; int nOffsetX = 0; if(nOffsetY<0) { nOffsetY = 0; nVPSizeX = GetRenderer()->GetHeight()*16/9; nVPSizeY = GetRenderer()->GetHeight(); nOffsetX = (GetRenderer()->GetWidth()-nVPSizeX)/2; } // draw2 black textures GetRenderer()->SetViewport(0,0,GetRenderer()->GetWidth(),GetRenderer()->GetHeight()); GetRenderer()->SetState(GS_NODEPTHTEST); float fRatioX = 800.f/GetRenderer()->GetWidth(); float fRatioY = 600.f/GetRenderer()->GetHeight(); if(nOffsetY>0) { GetRenderer()->Draw2dImage(0,0,nVPSizeX*fRatioX,(600-(nVPSizeY*fRatioY))/2,m_nBlackTexID); GetRenderer()->Draw2dImage(0,(nOffsetY+nVPSizeY)*fRatioY,nVPSizeX*fRatioX,(600-(nVPSizeY*fRatioY))/2,m_nBlackTexID); } else if(nOffsetX>0) { GetRenderer()->Draw2dImage(0,0,(800-(nVPSizeX*fRatioX))/2,nVPSizeY*fRatioY,m_nBlackTexID); GetRenderer()->Draw2dImage((nOffsetX+nVPSizeX)*fRatioX,0,(800-(nVPSizeX*fRatioX))/2,nVPSizeY*fRatioY,m_nBlackTexID); } // set viewport GetRenderer()->SetViewport(nOffsetX,nOffsetY,nVPSizeX,nVPSizeY); } else GetRenderer()->SetViewport(0,0,GetRenderer()->GetWidth(),GetRenderer()->GetHeight()); } GetRenderer()->EF_EndEf3D(SHDF_ALLOWHDR | SHDF_SORT); } GetRenderer()->EnableFog(false); //GetRenderer()->EF_ClearLightsList(); if(!m_pObjManager->m_nRenderStackLevel) GetTimer()->MeasureTime("3EndEf"); /* // example for wemade // setup vertices SColorVert arrVerts[4]; Vec3d vPos(142,46,20); Vec3d right(1,0,0); Vec3d up(0,1,0); UCol ucResCol; ucResCol.dcolor= (DWORD)-1; arrVerts[0].vert = (-right-up) + vPos; arrVerts[0].dTC[0] = 1; arrVerts[0].dTC[1] = 0; arrVerts[0].color = ucResCol; arrVerts[1].vert = ( right-up) + vPos; arrVerts[1].dTC[0] = 1; arrVerts[1].dTC[1] = 1; arrVerts[1].color = ucResCol; arrVerts[2].vert = ( right+up) + vPos; arrVerts[2].dTC[0] = 0; arrVerts[2].dTC[1] = 1; arrVerts[2].color = ucResCol; arrVerts[3].vert = (-right+up) + vPos; arrVerts[3].dTC[0] = 0; arrVerts[3].dTC[1] = 0; arrVerts[3].color = ucResCol; // make indices byte arrIndices[6] = {0,1,2,0,2,3}; // get shader IShader * pShader = GetRenderer()->EF_LoadShader("ParticleLight", eSH_World); int nTexId = GetRenderer()->LoadTexture("detail"); // now render // make object CCObject * pOb = GetRenderer()->EF_GetObject(true); pOb->m_Trans(0,0,0); pOb->m_Angs(0,0,0); pOb->m_AmbColor = Col_White; pOb->m_RenderState = GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA; pOb->m_NumCM = nTexId; GetRenderer()->EF_StartEf(); GetRenderer()->EF_AddSpriteToScene(pShader->GetID(), 4, arrVerts, pOb, arrIndices, 6); GetRenderer()->EF_EndEf3D(true); */ /* { // i use static in this example only allow to have initialization and rendering in one place static CLeafBuffer * pLeafBuffer = 0; if(!pLeafBuffer) { const int nChunksNum = 16; struct_VERTEX_FORMAT_P3F tmp; list2 lstVertices; list2 lstIndices; list2 lstChunkFirstIdxId; // contruct some geometry for(float r1=0, r2=1.f; r2<=nChunksNum; r1+=1.f, r2+=1.f) { lstChunkFirstIdxId.Add(lstIndices.Count()); for(int i=0; i<=360; i+=30) { float rad = (i) * (gf_PI/180); tmp.x = Fsin(rad)*(r2); tmp.y = Fcos(rad)*(r2); tmp.z = 0; lstIndices.Add(lstVertices.Count()); lstVertices.Add(tmp); tmp.x = Fsin(rad)*(r1); tmp.y = Fcos(rad)*(r1); tmp.z = 0; lstIndices.Add(lstVertices.Count()); lstVertices.Add(tmp); } } lstChunkFirstIdxId.Add(lstIndices.Count()); // make leaf buffer pLeafBuffer = GetRenderer()->CreateLeafBufferInitialized( lstVertices.GetElements(), lstVertices.Count(), VERTEX_FORMAT_P3F, lstIndices.GetElements(), lstIndices.Count(), R_PRIMV_MULTI_STRIPS, "VolFogTopCircle", eBT_Dynamic,nChunksNum, 0x1000); // make shader IShader * pShader = GetRenderer()->EF_LoadShader("WaterVolume",eSH_World); // define chunks for(int i=0; iSetChunk(pShader, lstIndices[lstChunkFirstIdxId[i]],lstVertices.Count()/(lstChunkFirstIdxId.Count()-1), lstChunkFirstIdxId[i],lstChunkFirstIdxId[i+1]-lstChunkFirstIdxId[i], i); } } // render CCObject * pObject = GetRenderer()->EF_GetObject(true); Vec3d vPos(142,46,20); pObject->m_Trans = vPos; pObject->m_Scale = Vec3d(0.1f,0.1f,0.1f); GetRenderer()->EF_StartEf(); pLeafBuffer->AddRenderElements(pObject); GetRenderer()->EF_EndEf3D(true); } */ /* list2 lstVert; list2 lstIdx; static CLeafBuffer * pLeafBuffer = NULL; static IShader* pTempShader = NULL; int offset = 2; struct_VERTEX_FORMAT_P3F_COL4UB center; center.x = 142; center.y = 46; center.z = 20; center.r = 255; center.g = 255; center.b = 255; center.a = 255; struct_VERTEX_FORMAT_P3F_COL4UB temp[3]; temp[0] = center; temp[0].x -= offset; temp[0].z -= offset; temp[1] = center; temp[1].z += offset; temp[2] = center; temp[2].x += offset; temp[2].z -= offset; lstVert.Add( temp[0]); lstVert.Add( temp[1]); lstVert.Add( temp[2]); lstIdx.Add(0); lstIdx.Add(1); lstIdx.Add(2); static int minit=1; if(minit) { minit=0; pTempShader= GetSystem()->GetIRenderer()->EF_LoadShader("WaterVolume", eSH_World, 0); pLeafBuffer = GetSystem()->GetIRenderer()->CreateLeafBufferInitialized( &temp[0], lstVert.Count(), VERTEX_FORMAT_P3F_COL4UB, lstIdx.GetElements(), lstIdx.Count(), R_PRIMV_TRIANGLES,"TerrainSector"); pLeafBuffer->SetChunk(pTempShader,0,3,0,3); pLeafBuffer->SetShader(pTempShader); } //In Rendering part { //In this position, want to change some vertex pos. //and want to render. Below is Possible? CCObject * pObject = GetRenderer()->EF_GetObject(true); // Vec3d vPos(142,46,20); //pObject->m_Trans = vPos; //pObject->m_Scale = Vec3d(0.1f,0.1f,0.1f); // pObject->m_NumCM = 4096; // pLeafBuffer->UpdateVertices() GetSystem()->GetIRenderer()->EF_StartEf(); pLeafBuffer->AddRenderElements(); GetSystem()->GetIRenderer()->EF_EndEf3D(true); } */ m_pObjManager->m_nRenderStackLevel = m_pTerrain->m_nRenderStackLevel = 0; // Light info is not valid after C3Dengine::Render() // m_lstDynLights.Clear(); } void C3DEngine::RenderSkyBox(IShader *pSH) { // skybox if (pSH && m_pRESky && GetCVars()->e_sky_box) { CCObject * pObj = GetRenderer()->EF_GetObject(true, -1); pObj->m_Matrix.SetTranslationMat(GetViewCamera().GetPos()); pObj->m_Matrix = Matrix33::CreateRotationZ(gf_DEGTORAD*m_fSkyBoxAngle)*pObj->m_Matrix; pObj->m_ObjFlags |= FOB_TRANS_TRANSLATE | FOB_TRANS_ROTATE; if(!m_pObjManager->m_nRenderStackLevel) { pObj->m_nScissorX1 = GetViewCamera().m_ScissorInfo.x1; pObj->m_nScissorY1 = GetViewCamera().m_ScissorInfo.y1; pObj->m_nScissorX2 = GetViewCamera().m_ScissorInfo.x2; pObj->m_nScissorY2 = GetViewCamera().m_ScissorInfo.y2; if(m_pVisAreaManager->m_lstIndoorActiveOcclVolumes.Count()) { Matrix44 matInv = pObj->m_Matrix; matInv.Invert44(); Vec3d vPos; for(int i=0; im_lstIndoorActiveOcclVolumes.Count()) { vPos = matInv.TransformPointOLD(m_pVisAreaManager->m_lstIndoorActiveOcclVolumes[i]->m_arrvActiveVerts[0]); m_pRESky->m_arrvPortalVerts[i][0].xyz = vPos; m_pRESky->m_arrvPortalVerts[i][0].color.bcolor[3] = 255; vPos = matInv.TransformPointOLD(m_pVisAreaManager->m_lstIndoorActiveOcclVolumes[i]->m_arrvActiveVerts[1]); m_pRESky->m_arrvPortalVerts[i][1].xyz = vPos; m_pRESky->m_arrvPortalVerts[i][1].color.bcolor[3] = 255; vPos = matInv.TransformPointOLD(m_pVisAreaManager->m_lstIndoorActiveOcclVolumes[i]->m_arrvActiveVerts[3]); m_pRESky->m_arrvPortalVerts[i][2].xyz = vPos; m_pRESky->m_arrvPortalVerts[i][2].color.bcolor[3] = 255; vPos = matInv.TransformPointOLD(m_pVisAreaManager->m_lstIndoorActiveOcclVolumes[i]->m_arrvActiveVerts[2]); m_pRESky->m_arrvPortalVerts[i][3].xyz = vPos; m_pRESky->m_arrvPortalVerts[i][3].color.bcolor[3] = 255; } else memset(m_pRESky->m_arrvPortalVerts[i],0,sizeof(m_pRESky->m_arrvPortalVerts[i])); } } else memset(m_pRESky->m_arrvPortalVerts,0,sizeof(m_pRESky->m_arrvPortalVerts)); } else memset(m_pRESky->m_arrvPortalVerts,0,sizeof(m_pRESky->m_arrvPortalVerts)); m_pRESky->m_fTerrainWaterLevel = max(0,m_pTerrain->GetWaterLevel()); m_pRESky->m_fSkyBoxStretching = m_fSkyBoxStretching; GetRenderer()->EF_AddEf(0, m_pRESky, pSH, NULL, pObj, 0, NULL,EFSLIST_PREPROCESS); } // sun lensflares if(m_pSHLensFlares && GetCVars()->e_sun==1 )//&& // GetViewCamera().GetPos().z > GetWaterLevel(&GetViewCamera().GetPos())) { // no sun flare under water because of conflict with vol fog if (m_pSHLensFlares->GetREs()->Num()) { //get the object if (!m_SunObject[m_pTerrain->m_nRenderStackLevel]) m_SunObject[m_pTerrain->m_nRenderStackLevel] = GetRenderer()->EF_GetObject(false, -1); else GetRenderer()->EF_GetObject(false, m_SunObject[m_pTerrain->m_nRenderStackLevel]->m_Id); Vec3d vTrans = GetSunPosition(false); vTrans.z *= m_fSunHeightScale; Vec3d vCamDir = -GetViewCamera().GetVCMatrixD3D9().GetOrtZ(); if(vTrans.Dot(vCamDir)<0) return; // sun is behind the camera float fDist = vTrans.GetDistance(GetViewCamera().GetPos()); if(fDist > GetViewCamera().GetZMax()) // sun is behind far cliping plane - move it closer { float t = GetViewCamera().GetZMax() / fDist; vTrans = GetViewCamera().GetPos() + 0.9f*t*(vTrans-GetViewCamera().GetPos()); } m_SunObject[m_pTerrain->m_nRenderStackLevel]->m_Matrix = GetTranslationMat(vTrans); m_SunObject[m_pTerrain->m_nRenderStackLevel]->m_ObjFlags |= FOB_DRSUN | FOB_TRANS_TRANSLATE; m_SunObject[m_pTerrain->m_nRenderStackLevel]->m_TempVars[2] = 1.0f; float fWaterLevel = GetWaterLevel(); float fCamZ = GetViewCamera().GetPos().z; if((fCamZ-fWaterLevel)*(vTrans.z-fWaterLevel)>0) m_SunObject[m_pTerrain->m_nRenderStackLevel]->m_SortId = -1000000; else m_SunObject[m_pTerrain->m_nRenderStackLevel]->m_SortId = 1000000; GetRenderer()->EF_AddEf(0, m_pSHLensFlares->GetREs()->Get(0), m_pSHLensFlares, NULL, m_SunObject[m_pTerrain->m_nRenderStackLevel], -1, NULL, EFSLIST_DISTSORT); } } } void C3DEngine::DrawText(float x, float y, const char * format, ...) { char buffer[512]; va_list args; va_start(args, format); vsprintf(buffer, format, args); va_end(args); ICryFont *pCryFont = GetSystem()->GetICryFont(); if (!pCryFont) return; IFFont *pFont = pCryFont->GetFont("console"); if (!pFont) return; pFont->UseRealPixels(false); pFont->SetSameSize(true); pFont->SetCharWidthScale(1); pFont->SetSize(vector2f(16, 16)); pFont->SetColor(color4f(1,1,1,1)); pFont->SetCharWidthScale(.65f); pFont->DrawString( x-pFont->GetCharWidth() * strlen(buffer) * pFont->GetCharWidthScale(), y, buffer ); } void C3DEngine::DisplayInfo(float & fTextPosX, float & fTextPosY, float & fTextStepY) { //GetRenderer()->ResetToDefault(); //GetRenderer()->EnableDepthTest(false); GetRenderer()->SetState(GS_NODEPTHTEST); static float fCurrentFPS = 0; static float fFrameRateSecMin=GetTimer()->GetFrameRate(); static float fFrameRateSecMax=GetTimer()->GetFrameRate(); float fFrameRate = 0; float fFrameTimeInSec=GetTimer()->GetFrameTime(); if(fFrameTimeInSec>0.0f) // to prevent divide by zero fFrameRate = 1.0f / fFrameTimeInSec; if(fFrameRate>999.0f) // to ensure number is <=999 (for nice printout) fFrameRate=999.0f; { // current fps static float START_TIME = GetCurAsyncTimeSec()*1000; static int iFrameRateCount=0; static float fFrameRateSum=0; static float fFrameRateMin=0; static float fFrameRateMax=0; float time = GetCurAsyncTimeSec()*1000; iFrameRateCount++; fFrameRateSum += fFrameRate; if (fFrameRateMin > fFrameRate) fFrameRateMin = fFrameRate; if (fFrameRateMax < fFrameRate) fFrameRateMax = fFrameRate; float diff = (time-START_TIME); if(diff>500) // every second { if(iFrameRateCount) fCurrentFPS = (float)(fFrameRateSum/(float)iFrameRateCount); else fCurrentFPS=0.0f; fFrameRateSecMin = fFrameRateMin; fFrameRateSecMax = fFrameRateMax; fFrameRateMin = fFrameRate; fFrameRateMax = fFrameRate; fFrameRateSum = 0; iFrameRateCount = 0; START_TIME = time; } else if(diff<0) // timer was reseted { START_TIME = GetCurAsyncTimeSec()*1000; iFrameRateCount=0; fFrameRateSum=0; fFrameRateMin=0; fFrameRateMax=0; } } int nPolygons,nShadowVolPolys; GetRenderer()->GetPolyCount(nPolygons,nShadowVolPolys); // Cam pos Vec3d vPos = GetViewCamera().GetPos(); // make level name char szLevelName[16]; *szLevelName=0; { int i; for(i=strlen(m_szLevelFolder)-2; i>0; i--) if(m_szLevelFolder[i] == '\\' || m_szLevelFolder[i] == '/') break; if(i>=0) { strncpy(szLevelName,&m_szLevelFolder[i+1],sizeof(szLevelName)); szLevelName[sizeof(szLevelName)-1] = 0; for(int i=strlen(szLevelName)-1; i>0; i--) if(szLevelName[i] == '\\' || szLevelName[i] == '/') szLevelName[i]=0; } } fTextPosX = 800-5; fTextPosY = -10; fTextStepY = 16; DrawText( fTextPosX, fTextPosY+=fTextStepY, "CamPos=%3d %3d %3d Angl=%3d %2d %3d", (int)vPos.x,(int)vPos.y,(int)vPos.z, (int)GetViewCamera().GetAngles().x, (int)GetViewCamera().GetAngles().y, (int)GetViewCamera().GetAngles().z); // get verson const SFileVersion & ver = GetSystem()->GetFileVersion(); char sVersion[128]; ver.ToString(sVersion); DrawText( fTextPosX, fTextPosY+=fTextStepY, "Ver=%s Lev=%s", sVersion,szLevelName); // Polys in scene if (nShadowVolPolys>0) DrawText(fTextPosX, fTextPosY+=fTextStepY,"Polygons %d(SV=%d)", nPolygons,nShadowVolPolys); else DrawText(fTextPosX, fTextPosY+=fTextStepY,"Polygons %2d,%003d", nPolygons/1000, nPolygons-nPolygons/1000*1000); { // Polys per sec int per_sec = (int)(nPolygons*fCurrentFPS); int m = per_sec /1000000; int t = (per_sec - m*1000000)/1000; int n = per_sec - m*1000000 - t*1000; DrawText(fTextPosX, fTextPosY+=fTextStepY,"P/Sec %003d,%003d,%003d", m,t,n); } if(GetCVars()->e_stream_cgf && m_pObjManager) { int nReady=0, nTotalInStreaming=0, nTotal=0; m_pObjManager->GetObjectsStreamingStatus(nReady,nTotalInStreaming,nTotal); DrawText(fTextPosX, fTextPosY+=fTextStepY,"Objects streaming: %d/%d/%d", nReady, nTotalInStreaming, nTotal); } if(GetCVars()->e_stream_areas && m_pTerrain) { int nReady=0, nTotal=0; m_pTerrain->GetStreamingStatus(nReady,nTotal); DrawText(fTextPosX, fTextPosY+=fTextStepY,"Terrain streaming: %d/%d", nReady, nTotal); m_pVisAreaManager->GetStreamingStatus(nReady,nTotal); DrawText(fTextPosX, fTextPosY+=fTextStepY,"Indoor streaming: %d/%d", nReady, nTotal); } // fps const int nStartFrame = -50; static int nFrames = nStartFrame; static float fStartTime = GetTimer()->gfGetTime(); float fCurrentTime = GetTimer()->gfGetTime(); if(fCurrentTimee_timedemo_frames && nFrames>=0) { // print current and average fps if(fStartTime != GetTimer()->gfGetTime()) DrawText( fTextPosX, fTextPosY+=fTextStepY, "FPS %3d (%3d..%3d) / %3.2f / %3.2f", (int)fCurrentFPS, (int)fFrameRateSecMin, (int)fFrameRateSecMax, fFrameRate, float(nFrames)/(GetTimer()->gfGetTime()-fStartTime) ); } else { // print current fps DrawText( fTextPosX, fTextPosY+=fTextStepY, "FPS %3d (%3d..%3d) / %5.1f", (int)fCurrentFPS, (int)fFrameRateSecMin, (int)fFrameRateSecMax, fFrameRate ); } // exit when x frames rendered if(nFrames > GetCVars()->e_timedemo_frames && GetCVars()->e_timedemo_frames) { char buffer[256]; snprintf(buffer, sizeof(buffer), "Average FPS = %3.2f", float(nFrames)/(GetTimer()->gfGetTime()-fStartTime)); #ifdef GAMECUBE OSReport("- Timedemo result -\n"); #elif (defined (PS2) || defined (_XBOX) || defined(LINUX)) snprintf(buffer, sizeof(buffer),"- Timedemo result -"); OutputDebugString(buffer); #else if(GetCVars()->e_timedemo_frames>10) MessageBox(0, buffer, "- Timedemo result -", MB_OK); #endif GetLog()->Log ("\001Timedemo quit"); GetConsole()->Exit("Timedemo quit 1"); } // Exit unconditionally when x seconds of game passed // THis is used for automatic multipass profiling with VTune 6.x if (GetCVars()->e_timedemo_milliseconds) { if (int((GetTimer()->gfGetTime() - fStartTime)*1000) > GetCVars()->e_timedemo_milliseconds) { GetLog()->Log ("\001Timedemo quit in %dms (started at %g sec, stopped at %g sec) Average %3.2f FPS", GetCVars()->e_timedemo_milliseconds, fStartTime, GetTimer()->gfGetTime(), float(nFrames - nStartFrame)/(GetTimer()->gfGetTime()-fStartTime)); GetSystem()->Quit(); } } nFrames++; /* if(GetCVars()->e_video_buffer_stats) { char * szRendererStatus = GetRenderer()->GetStatusText(eRS_VidBuffer); GetRenderer()->TextToScreen( fTextPosX-44, fTextPosY+=fTextStepY, szRendererStatus ); }*/ if(GetCVars()->e_particles_debug) { int nSprites = 0, nFree = 0, nEmitters = 0; int nParts = m_pPartManager->Count(&nSprites, &nFree, &nEmitters); DrawText( fTextPosX, fTextPosY+=fTextStepY, "Parts=%4d/%4d Emit=%d Sprites=%4d", nParts, nFree, nEmitters, nSprites ); } DrawText( fTextPosX, fTextPosY+=fTextStepY, "ViewDist=%d/%.1f", (int)m_fMaxViewDist, m_pObjManager ? m_pObjManager->m_fMaxViewDistanceScale : 0); { int nActive=0; char sLightsList[512]=""; for(int i=0; i=0 && m_lstDynLights[i].m_fRadius >= 0.5f ) if(!(m_lstDynLights[i].m_Flags & DLF_FAKE)) { nActive++; if(i<4) { strcat(sLightsList, m_lstDynLights[i].m_sDebugName); if(ie_terrain_debug>1) DrawText( fTextPosX, fTextPosY+=fTextStepY, m_pTerrain->m_pTexturePool->GetStatusText(m_pTerrain)); // Render path info char * pRenderPath; static ICVar *p_r_SM30PATH = GetConsole()->GetCVar("r_SM30PATH"); static ICVar *p_r_SM2XPATH = GetConsole()->GetCVar("r_SM2XPATH"); static ICVar *p_r_Quality_BumpMapping = GetConsole()->GetCVar("r_Quality_BumpMapping"); if(p_r_SM30PATH->GetIVal()) pRenderPath = "SM3.0 Path"; else if(p_r_SM2XPATH->GetIVal()) pRenderPath = "SM2.X path"; else if(p_r_Quality_BumpMapping->GetIVal() == 3) pRenderPath = "SM2.0 Path"; else if(p_r_Quality_BumpMapping->GetIVal() > 0) pRenderPath = "SM1.1 Path"; else pRenderPath = "FP Path"; DrawText( fTextPosX, fTextPosY+=fTextStepY, "Render path = %s", pRenderPath ); } #define DLD_SET_CVAR(VarName,FlagName)\ int VarName = GetCVars()->VarName;\ if(!(DrawFlags & FlagName))\ GetCVars()->VarName = 0;\ #define DLD_RESTORE_CVAR(VarName) \ GetCVars()->VarName = VarName; \ void C3DEngine::DrawLowDetail(const int & DrawFlags) { if(m_pObjManager) m_pObjManager->m_fMaxViewDistanceScale = 1.f; m_nRenderFrameID = GetRenderer()->GetFrameID(); DLD_SET_CVAR(e_shadow_maps,DLD_SHADOW_MAPS); DLD_SET_CVAR(e_stencil_shadows,DLD_STENCIL_SHADOWS); DLD_SET_CVAR(e_brushes,DLD_STATIC_OBJECTS); DLD_SET_CVAR(e_vegetation,DLD_STATIC_OBJECTS); DLD_SET_CVAR(e_entities,DLD_ENTITIES); DLD_SET_CVAR(e_terrain,DLD_TERRAIN); DLD_SET_CVAR(e_player,DLD_FIRST_PERSON_CAMERA_OWNER); RenderScene(DrawFlags); DLD_RESTORE_CVAR(e_shadow_maps); DLD_RESTORE_CVAR(e_stencil_shadows); DLD_RESTORE_CVAR(e_brushes); DLD_RESTORE_CVAR(e_vegetation); DLD_RESTORE_CVAR(e_entities); DLD_RESTORE_CVAR(e_terrain); DLD_RESTORE_CVAR(e_player); } void C3DEngine::DrawTerrainDetailTextureLayers() { GetRenderer()->EnableFog(false); // float fRainFactor = 1.f;// - 0.75f*GetCVars()->e_rain_amount; //float fFogDistance = (m_fFogNearDist*fRainFactor + m_fFogFarDist *fRainFactor)*0.5f; // m_pTerrain->DrawDetailTextures(m_fFogNearDist,m_fFogFarDist,true); SetupDistanceFog(); // m_pObjManager->DrawShadows(0); // draw tree shadows m_pObjManager->DrawEntitiesShadowSpotsOnTerrain(); } void C3DEngine::DrawFarTrees() { m_pObjManager->DrawFarObjects(m_fMaxViewDist); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // Particles, decals above the water ///////////////////////////////////////////////////////////////////////////////////////////////////////// void C3DEngine::DrawTerrainParticles(IShader * pShader) { if(pShader == m_pSHTerrainParticles) { m_pDecalManager->DrawBigDecalsOnTerrain(); /* if(!(m_pVisAreaManager->m_pCurArea || m_pVisAreaManager->m_pCurPortal) && IsOutdoorVisible() && m_pVisAreaManager->IsOutdoorAreasVisible()) m_pBFManager->Render(m_pTerrain);*/ } // else // assert(0); } void C3DEngine::RenderTerrainParticles() { if (m_pRETerrainParticles && GetCVars()->e_decals) { CCObject * pObj = GetRenderer()->EF_GetObject(true, -1); pObj->m_Matrix.SetIdentity(); GetRenderer()->EF_AddEf(0, m_pRETerrainParticles, m_pSHTerrainParticles, NULL, pObj, 0, NULL, EFSLIST_STENCIL | eS_TerrainDetailTextures); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////// void C3DEngine::SetupDistanceFog() { if(!m_pTerrain) return; VolumeInfo * pFogVolume = NULL; if(GetCVars()->e_use_global_fog_in_fog_volumes && !m_nRenderStackLevel) { // find camera fog volume CVisArea * pCurVisArea = m_pVisAreaManager->m_pCurArea ? m_pVisAreaManager->m_pCurArea : m_pVisAreaManager->m_pCurPortal; if(pCurVisArea) { // find indoor fog volume with this id /*for(int f=0; fm_lstFogVolumes.Count(); f++) if(m_pTerrain->m_lstFogVolumes[f].bOcean) if(m_pTerrain->m_lstFogVolumes[f].nRendererVolumeID == pCurVisArea->m_nFogVolumeId) break; if(fm_lstFogVolumes.Count() && m_pTerrain->m_lstFogVolumes[f].vBoxMax.z>GetViewCamera().GetPos().z) pFogVolume = &m_pTerrain->m_lstFogVolumes[f];*/ } else { // find outdoor fog volume int f; for(f=0; fm_lstFogVolumes.Count(); f++) if(m_pTerrain->m_lstFogVolumes[f].bOcean) if(m_pTerrain->m_lstFogVolumes[f].InsideBBox(GetViewCamera().GetPos())) break; if(fm_lstFogVolumes.Count()) pFogVolume = &m_pTerrain->m_lstFogVolumes[f]; } } GetRenderer()->SetFog(0, pFogVolume ? pFogVolume->fMaxViewDist*0.01f : m_fFogNearDist, pFogVolume ? pFogVolume->fMaxViewDist : m_fFogFarDist , GetRenderer()->EF_GetHeatVision() ? Vec3d(0,0,0) : pFogVolume ? pFogVolume->vColor : m_vFogColor, R_FOGMODE_LINEAR); GetRenderer()->EnableFog(GetCVars()->e_fog>0); } void C3DEngine::RenderOutSpace() { /* if (m_pREOutSpace && GetCVars()->e_out_space) { CCObject * pObj = GetRenderer()->EF_GetObject(true, -1); pObj->m_Matrix.SetTranslationMat(GetViewCamera().GetPos()); GetRenderer()->EF_AddEf(0, m_pREOutSpace, m_pSHOutSpace, NULL, pObj, 0, NULL); }*/ } void C3DEngine::DrawFullScreenQuad(IShader *pShader, bool bRectangle, EF_Sort eSort) { if(m_pRE2DQuad) { CCObject * pObj = GetRenderer()->EF_GetObject(true, -1); pObj->m_Matrix.SetIdentity(); pObj->m_Color = m_vFogColor; pObj->m_Color.a = 1.f; pObj->m_nTemplId = bRectangle; GetRenderer()->EF_AddEf(0, m_pRE2DQuad, pShader, NULL, pObj, 0, NULL, eSort); } } /* void C3DEngine::RenderTerrainShadowMaps() { if(!GetCVars()->e_shadow_maps) return; CCObject * pRendObject = GetRenderer()->EF_GetObject(true, -1); pRendObject->m_Trans.Clear(); pRendObject->m_Angs.Clear(); /// m_pRETerrainShadowMap->m_pShadowFrustum = 0; // m_pRETerrainShadowMap->m_fAlpha = -1; // GetRenderer()->EF_AddEf(0, m_pRETerrainShadowMap, "TerrainShadowMaps", pRendObject, 0, NULL, eS_TerrainDetailTextures); } */ // render fog plane circle if camera is inside volume void C3DEngine::RenderVolumeFogTopPlane() { FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE ); if(m_pObjManager->m_nRenderStackLevel) return; Vec3d vCamPos = GetViewCamera().GetPos(); CSectorInfo * pSectorInfo = m_pTerrain ? m_pTerrain->GetSectorFromPoint((int)vCamPos.x,(int)vCamPos.y) : 0; VolumeInfo * pFogVolume = 0; if(!pSectorInfo || !pSectorInfo->m_pFogVolume || vCamPos.z>pSectorInfo->m_pFogVolume->vBoxMax.z) { } else pFogVolume = pSectorInfo->m_pFogVolume; CVisArea * pCurVisArea = m_pVisAreaManager->m_pCurArea ? m_pVisAreaManager->m_pCurArea : m_pVisAreaManager->m_pCurPortal; if(pCurVisArea && pCurVisArea->m_nFogVolumeId) { int f; for(f=0; fm_lstFogVolumes.Count(); f++) if(m_pTerrain->m_lstFogVolumes[f].nRendererVolumeID == pCurVisArea->m_nFogVolumeId) break; if(fm_lstFogVolumes.Count()) pFogVolume = &m_pTerrain->m_lstFogVolumes[f]; } if(!pFogVolume) return; if( vCamPos.zbOcean ) return; // do not render fog top plane if it is higher than current visarea if( pCurVisArea && pFogVolume->vBoxMax.z>pCurVisArea->m_vBoxMax.z ) return; const int nChunksNum = 16; if(!m_pFogTopPlane) { struct_VERTEX_FORMAT_P3F tmp; list2 lstVertices; list2 lstIndices; list2 lstFirstIdxId; for(float r1=0, r2=1.f; r2<=nChunksNum; r1+=1.f, r2+=1.f) { lstFirstIdxId.Add(lstIndices.Count()); for(int i=0; i<=360; i+=30) { float rad = (i) * (gf_PI/180); tmp.xyz.x = cry_sinf(rad)*(r2); tmp.xyz.y = cry_cosf(rad)*(r2); tmp.xyz.z = 0; lstIndices.Add(lstVertices.Count()); lstVertices.Add(tmp); tmp.xyz.x = cry_sinf(rad)*(r1); tmp.xyz.y = cry_cosf(rad)*(r1); tmp.xyz.z = 0; lstIndices.Add(lstVertices.Count()); lstVertices.Add(tmp); } } lstFirstIdxId.Add(lstIndices.Count()); m_pFogTopPlane = GetRenderer()->CreateLeafBufferInitialized( lstVertices.GetElements(), lstVertices.Count(), VERTEX_FORMAT_P3F, lstIndices.GetElements(), lstIndices.Count(), R_PRIMV_MULTI_STRIPS, "VolFogTopCircle", eBT_Dynamic,nChunksNum, 0x1000); for(int i=0; iSetChunk(pFogVolume->pShader, lstIndices[lstFirstIdxId[i]],lstVertices.Count()/(lstFirstIdxId.Count()-1), lstFirstIdxId[i],lstFirstIdxId[i+1]-lstFirstIdxId[i], i); } } CCObject * pObj = GetRenderer()->EF_GetObject(true); pObj->m_Matrix.SetTranslationMat(Vec3d(vCamPos.x, vCamPos.y, pFogVolume->vBoxMax.z+0.0125f)); float fSize = (pFogVolume->vBoxMax-pFogVolume->vBoxMin).Length(); float s= (1.f/nChunksNum*fSize)*2; pObj->m_Matrix = Matrix33::CreateScale(Vec3d(s,s,s))*pObj->m_Matrix; pObj->m_ObjFlags |= FOB_TRANS_TRANSLATE | FOB_TRANS_SCALE; if(pFogVolume->nRendererVolumeID) m_pFogTopPlane->AddRenderElements(pObj, 0, -1, pFogVolume->nRendererVolumeID); } void C3DEngine::MakeHiResScreenShot() { #if !defined(LINUX) static int nFileId = 0; static int nHiResShootCounter = -1; static list2 lstSubImages; if(nHiResShootCounter<0) { // start loop lstSubImages.Clear(); nHiResShootCounter = GetCVars()->e_hires_screenshoot*GetCVars()->e_hires_screenshoot; GetConsole()->SetScrollMax(0); GetTimer()->Enable(false); // find free group id while(1) { char sFileName[256]; snprintf(sFileName, sizeof(sFileName), "HiResScreenShoots\\%dx%d_%d.tga", nFileId, GetRenderer()->GetWidth()*GetCVars()->e_hires_screenshoot, GetRenderer()->GetHeight()*GetCVars()->e_hires_screenshoot); FILE * fp = GetSystem()->GetIPak()->FOpen(sFileName,"rb"); if (!fp) break; // file doesn't exist GetSystem()->GetIPak()->FClose(fp); nFileId++; } } else { //IVO: I have a special solution for HiResScreenShoots on GameCube! #ifndef GAMECUBE CreateDirectory("HiResScreenShoots",0); lstSubImages.Add(0); lstSubImages.Last() = new unsigned char [GetRenderer()->GetWidth()*GetRenderer()->GetHeight()*4]; GetRenderer()->ReadFrameBuffer(lstSubImages.Last(), GetRenderer()->GetWidth(), GetRenderer()->GetHeight(), false, true); #endif } nHiResShootCounter--; if(nHiResShootCounter<0) { // end loop // restore initial state GetRenderer()->SetViewport(0,0,GetRenderer()->GetWidth(),GetRenderer()->GetHeight()); GetConsole()->SetScrollMax(300); GetTimer()->Enable(true); char sFileName[256]; snprintf(sFileName, sizeof(sFileName), "HiResScreenShoots\\%dx%d_%d.tga", nFileId, GetRenderer()->GetWidth()*GetCVars()->e_hires_screenshoot, GetRenderer()->GetHeight()*GetCVars()->e_hires_screenshoot); GetLog()->UpdateLoadingScreen("Writing %s ...", sFileName); int nFinSize = lstSubImages.Count()* GetRenderer()->GetWidth()*GetRenderer()->GetHeight()*4; unsigned char * pFinalImage = NULL; #ifdef WIN32 pFinalImage = (unsigned char * )VirtualAlloc(NULL,nFinSize,MEM_COMMIT,PAGE_READWRITE); #endif // WIN32 if(pFinalImage) { // Save final image for(int nImageId=0; nImageIde_hires_screenshoot*GetRenderer()->GetWidth(); int pos_Y = (lstSubImages.Count()-nImageId-1)/GetCVars()->e_hires_screenshoot*GetRenderer()->GetHeight(); for(int x=0; xGetWidth(); x++) for(int y=0; yGetHeight(); y++) { int nFin = ((pos_X+x) + (pos_Y+y)*GetRenderer()->GetWidth()*GetCVars()->e_hires_screenshoot); int nSub = (( x) + ( y)*GetRenderer()->GetWidth()); for(int c=0; c<4; c++) pFinalImage[nFin*4+c] = lstSubImages[nImageId][nSub*4+c]; } delete [] lstSubImages[nImageId]; lstSubImages[nImageId]=0; } GetRenderer()->WriteTGA(pFinalImage, GetRenderer()->GetWidth()*GetCVars()->e_hires_screenshoot, GetRenderer()->GetHeight()*GetCVars()->e_hires_screenshoot, sFileName, 32); #ifdef WIN32 VirtualFree( pFinalImage,0,MEM_RELEASE ); #endif // WIN32 GetLog()->LogPlus(" done"); } else GetLog()->Log("Error making screenshot: memory allocation error (%d MB)", nFinSize/1024/1024); GetCVars()->e_hires_screenshoot = 0; } else { GetRenderer()->SetViewport( -nHiResShootCounter%GetCVars()->e_hires_screenshoot*GetRenderer()->GetWidth(), -nHiResShootCounter/GetCVars()->e_hires_screenshoot*GetRenderer()->GetHeight(), GetRenderer()->GetWidth()*GetCVars()->e_hires_screenshoot, GetRenderer()->GetHeight()*GetCVars()->e_hires_screenshoot); } #endif } void C3DEngine::CaptureFrameBufferToFile() { #if !defined(LINUX) if(GetCVars()->e_capture_frames>0) { char * pFolderName = GetCVars()->e_capture_folder->GetString(); CreateDirectory(pFolderName,0); char * pFileFormat = GetCVars()->e_capture_file_format->GetString(); strlwr(pFileFormat); // get image unsigned char * pImage = new unsigned char [GetRenderer()->GetWidth()*GetRenderer()->GetHeight()*4]; GetRenderer()->ReadFrameBuffer(pImage, GetRenderer()->GetWidth(), GetRenderer()->GetHeight(), true, true); { // flip up side down unsigned char * pImageFlip = new unsigned char [GetRenderer()->GetWidth()*GetRenderer()->GetHeight()*4]; int nSizeY = GetRenderer()->GetHeight(); int nSizeX = GetRenderer()->GetWidth(); for (int i=0; ie_capture_frames-1); GetLog()->UpdateLoadingScreen("Writing %s ...", sFileName); GetRenderer()->WriteJPG(pImage,GetRenderer()->GetWidth(), GetRenderer()->GetHeight(), sFileName); } else if(!strcmp(pFileFormat,"tga")) { snprintf(sFileName, sizeof(sFileName), "%s\\Frame%06d.tga", pFolderName, GetCVars()->e_capture_frames-1); GetLog()->UpdateLoadingScreen("Writing %s ...", sFileName); GetRenderer()->WriteTGA(pImage,GetRenderer()->GetWidth(), GetRenderer()->GetHeight(), sFileName, 32); } else Warning(0,0,"C3DEngine::CaptureFrameBuffer: Unsupported image file format specified: %s", pFileFormat); delete [] pImage; GetCVars()->e_capture_frames++; } #endif } void C3DEngine::DrawShadowSpotOnTerrain(Vec3d vPos, float fRadius) { // calc area int x1=int(vPos.x-fRadius*0.75)/CTerrain::GetHeightMapUnitSize()*CTerrain::GetHeightMapUnitSize(); int y1=int(vPos.y-fRadius*0.75)/CTerrain::GetHeightMapUnitSize()*CTerrain::GetHeightMapUnitSize(); int x2=int(vPos.x+CTerrain::GetHeightMapUnitSize()+fRadius*0.75)/CTerrain::GetHeightMapUnitSize()*CTerrain::GetHeightMapUnitSize(); int y2=int(vPos.y+CTerrain::GetHeightMapUnitSize()+fRadius*0.75)/CTerrain::GetHeightMapUnitSize()*CTerrain::GetHeightMapUnitSize(); // limits if(x1<0) x1=0; if(y1<0) y1=0; if(x2>=CTerrain::GetTerrainSize()) x2=CTerrain::GetTerrainSize(); if(y2>=CTerrain::GetTerrainSize()) y2=CTerrain::GetTerrainSize(); // fill buffer and draw list2 verts; struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F tmp; tmp.color.dcolor = -1; float fAlpha = (1.f-( m_pObjManager->m_vOutdoorAmbientColor.x+ m_pObjManager->m_vOutdoorAmbientColor.y+ m_pObjManager->m_vOutdoorAmbientColor.z)*0.3333f*0.5f); float fHeight = vPos.z - GetTerrainElevation(vPos.x,vPos.y) - fRadius; if(fHeight>=fRadius) return; if(fHeight<0) fHeight=0; fHeight = 1.f-fHeight/(fRadius); tmp.color.bcolor[3] = uchar(min(255.f,fAlpha*fHeight*255.f)); GetRenderer()->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA); GetRenderer()->SetColorOp(eCO_MODULATE, eCO_MODULATE, eCA_Texture|(eCA_Constant<<3), eCA_Texture|(eCA_Constant<<3)); GetRenderer()->SetCullMode(R_CULL_DISABLE); GetRenderer()->SetTexture(m_nShadowSpotTexId); ITexPic * pTexPic = GetRenderer()->EF_GetTextureByID(m_nShadowSpotTexId); if(pTexPic) pTexPic->SetFilter(FILTER_LINEAR); GetRenderer()->SetTexClampMode(true); for(int x=x1; xGetTerrainZ(x,y)+0.07f; tmp.st[0] = (((float)x)-vPos.x)/fRadius+0.5f; tmp.st[1] = 1.f-((((float)y)-vPos.y)/fRadius+0.5f); verts.Add(tmp); tmp.xyz.x = (float)(x+CTerrain::GetHeightMapUnitSize()); tmp.xyz.y = (float)y; tmp.xyz.z = Get3DEngine()->GetTerrainZ((x+CTerrain::GetHeightMapUnitSize()),y)+0.07f; tmp.st[0] = (((float)(x+CTerrain::GetHeightMapUnitSize()))-vPos.x)/fRadius+0.5f; tmp.st[1] = 1.f-((((float)y)-vPos.y)/fRadius+0.5f); verts.Add(tmp); } if(verts.Count()) GetRenderer()->DrawTriStrip(&(CVertexBuffer (&verts[0].xyz.x,VERTEX_FORMAT_P3F_COL4UB_TEX2F)),verts.Count()); } } void C3DEngine::SetupClearColor() { bool bCameraInOutdoors = !m_pVisAreaManager->m_pCurArea && !(m_pVisAreaManager->m_pCurPortal && m_pVisAreaManager->m_pCurPortal->m_lstConnections.Count()>1); GetRenderer()->SetClearColor(bCameraInOutdoors ? m_vFogColor : Vec3d(0,0,0)); if(bCameraInOutdoors) if(GetViewCamera().GetPos().zGetSectorFromPoint((int)GetViewCamera().GetPos().x,(int)GetViewCamera().GetPos().y) : 0; if(!pSectorInfo || !pSectorInfo->m_pFogVolume || GetViewCamera().GetPos().z>pSectorInfo->m_pFogVolume->vBoxMax.z) { if(GetViewCamera().GetPos().zm_lstFogVolumes.Count() && m_pTerrain->m_lstFogVolumes[0].bOcean) GetRenderer()->SetClearColor( m_pTerrain->m_lstFogVolumes[0].vColor ); } //else if( pSectorInfo->m_pFogVolume->bOcean ) // makes problems if there is no skybox //GetRenderer()->SetClearColor( pSectorInfo->m_pFogVolume->vColor ); } }