diff --git a/WickedEngine/wiHairParticle.cpp b/WickedEngine/wiHairParticle.cpp index cc994a526..2605af658 100644 --- a/WickedEngine/wiHairParticle.cpp +++ b/WickedEngine/wiHairParticle.cpp @@ -423,14 +423,8 @@ void wiHairParticle::Draw(Camera* camera, SHADERTYPE shaderType, GRAPHICSTHREAD XMStoreFloat3(&eye, Eye); } - frustum.ConstructFrustum((float)LOD[2], camera->Projection, cull_View); + const FrameCulling& culling = frameCullings[camera]; - - CulledList culledPatches; - if(spTree) - wiSPTree::getVisible(spTree->root,frustum,culledPatches); - - if(!culledPatches.empty()) { GraphicsDevice* device = wiRenderer::GetDevice(); device->EventBegin(L"HairParticle", threadID); @@ -462,36 +456,21 @@ void wiHairParticle::Draw(Camera* camera, SHADERTYPE shaderType, GRAPHICSTHREAD // use the depthstencil of the drawworld instead! //device->BindDepthStencilState(dss,STENCILREF_DEFAULT,threadID); - - for(int i=0;i<3;++i){ - vector renderPoints; - renderPoints.reserve(MAX_PARTICLES); - - if(texture){ + for(int i=0;i<3;++i) + { + if(texture) + { device->BindGS(i<2?qgs[0]:qgs[1],threadID); device->BindRasterizerState(i<2?ncrs:rs,threadID); } else - device->BindGS(gs[i],threadID); - CulledList::iterator iter = culledPatches.begin(); - while(iter != culledPatches.end()){ - Cullable* culled = *iter; - Patch* patch = ((PatchHolder*)culled)->patch; - - float dis = wiMath::Distance(eye,((PatchHolder*)culled)->bounds.getCenter()); - - if(disp.begin(),patch->p.end()); - } - else - ++iter; + { + device->BindGS(gs[i], threadID); } - device->UpdateBuffer(vb[i],renderPoints.data(),threadID,(int)(sizeof(Point)*renderPoints.size())); + device->UpdateBuffer(vb[i],culling.renderPoints[i].data(),threadID,(int)(sizeof(Point)*culling.renderPoints[i].size())); device->BindVertexBuffer(vb[i],0,sizeof(Point),threadID); - device->Draw((int)renderPoints.size(),threadID); + device->Draw((int)culling.renderPoints[i].size(),threadID); } device->BindGS(nullptr,threadID); @@ -499,6 +478,70 @@ void wiHairParticle::Draw(Camera* camera, SHADERTYPE shaderType, GRAPHICSTHREAD device->EventEnd(threadID); } } +void wiHairParticle::PerformCulling(Camera* camera) +{ + XMMATRIX inverseMat = XMLoadFloat4x4(&OriginalMatrix_Inverse); + XMMATRIX renderMatrix = inverseMat * object->getMatrix(); + XMMATRIX inverseRenderMat = XMMatrixInverse(nullptr, renderMatrix); + + Frustum frustum; + + // Culling camera needs to be transformed according to hair ps transform (inverse) + XMFLOAT4X4 cull_View; + XMFLOAT3 eye; + { + XMMATRIX View; + XMVECTOR At = XMVectorSet(0, 0, 1, 0), Up = XMVectorSet(0, 1, 0, 0), Eye; + + XMMATRIX camRot = XMMatrixRotationQuaternion(XMLoadFloat4(&camera->rotation)); + At = XMVector3Normalize(XMVector3Transform(XMVector3Transform(At, camRot), inverseRenderMat)); + Up = XMVector3Normalize(XMVector3Transform(XMVector3Transform(Up, camRot), inverseRenderMat)); + Eye = XMVector4Transform(camera->GetEye(), inverseRenderMat); + + View = XMMatrixLookToLH(Eye, At, Up); + + XMStoreFloat4x4(&cull_View, View); + XMStoreFloat3(&eye, Eye); + } + + frustum.ConstructFrustum((float)LOD[2], camera->Projection, cull_View); + + + + FrameCulling& culling = frameCullings[camera]; + CulledList& culledPatches = culling.culledPatches; + + culling.culledPatches.clear(); + + if (spTree != nullptr) + { + wiSPTree::getVisible(spTree->root, frustum, culledPatches); + + for (int i = 0; i<3; ++i) + { + vector& renderPoints = culling.renderPoints[i]; + renderPoints.clear(); + renderPoints.reserve(MAX_PARTICLES); + + CulledList::iterator iter = culledPatches.begin(); + while (iter != culledPatches.end()) { + Cullable* culled = *iter; + Patch* patch = ((PatchHolder*)culled)->patch; + + float dis = wiMath::Distance(eye, ((PatchHolder*)culled)->bounds.getCenter()); + + if (disp.begin(), patch->p.end()); + } + else + ++iter; + } + } + } + +} wiHairParticle::Patch::Patch(){ p.resize(0); diff --git a/WickedEngine/wiHairParticle.h b/WickedEngine/wiHairParticle.h index a667e7514..67cdb18f5 100644 --- a/WickedEngine/wiHairParticle.h +++ b/WickedEngine/wiHairParticle.h @@ -1,8 +1,8 @@ #pragma once #include "wiParticle.h" #include "ConstantBufferMapping.h" +#include "wiSPTree.h" -class wiSPTree; struct Material; struct Camera; @@ -52,6 +52,12 @@ private: public: static void LoadShaders(); private: + struct FrameCulling + { + CulledList culledPatches; + vector renderPoints[3]; // per lod + }; + unordered_map frameCullings; public: wiHairParticle(); @@ -61,6 +67,7 @@ public: void SetUpPatches(); void Draw(Camera* camera, SHADERTYPE shaderType, GRAPHICSTHREAD threadID); + void PerformCulling(Camera* camera); static void CleanUpStatic(); static void SetUpStatic(); diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 2342eaf93..725b76244 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -79,6 +79,8 @@ vector wiRenderer::cubes; vector wiRenderer::renderableTranslators; vector> wiRenderer::renderableBoxes; +unordered_map wiRenderer::frameCullings; + #pragma endregion wiRenderer::wiRenderer() @@ -1416,10 +1418,42 @@ void wiRenderer::UpdatePerFrameData() { if (GetGameSpeed() > 0) { - UpdateSPTree(spTree); UpdateSPTree(spTree_lights); } + // Perform culling: + { + for (auto& x : frameCullings) + { + Camera* cam = x.first; + FrameCulling& culling = x.second; + + culling.culledRenderer.clear(); + culling.culledObjects.clear(); + culling.culledObjects_transparent.clear(); + culling.culledLights.clear(); + + if (spTree != nullptr) + { + wiSPTree::getVisible(spTree->root, cam->frustum, culling.culledObjects, wiSPTree::SortType::SP_TREE_SORT_FRONT_TO_BACK); + wiSPTree::getVisible(spTree->root, cam->frustum, culling.culledObjects_transparent, wiSPTree::SortType::SP_TREE_SORT_PAINTER); + for (Cullable* object : culling.culledObjects) + { + for (wiHairParticle* hair : ((Object*)object)->hParticleSystems) { + hair->PerformCulling(cam); + } + culling.culledRenderer[((Object*)object)->mesh].insert((Object*)object); + } + } + if (spTree_lights != nullptr) + { + Frustum frustum; + frustum.ConstructFrustum(min(cam->zFarP, GetScene().worldInfo.fogSEH.y), cam->Projection, cam->View); + wiSPTree::getVisible(spTree_lights->root, frustum, culling.culledLights); + } + } + } + UpdateBoneLines(); UpdateCubes(); @@ -1434,6 +1468,7 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID) UpdateCameraCB(threadID); + // Skinning: { bool streamOutSetUp = false; @@ -1523,6 +1558,34 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID) } + + // Environment probe setup: + { + Texture2D* envMaps[] = { enviroMap, enviroMap }; + XMFLOAT3 envMapPositions[] = { XMFLOAT3(0,0,0),XMFLOAT3(0,0,0) }; + GetScene().environmentProbes.sort( + [&](EnvironmentProbe* a, EnvironmentProbe* b) { + return wiMath::DistanceSquared(a->translation, getCamera()->translation) < wiMath::DistanceSquared(b->translation, getCamera()->translation); + } + ); + int envProbeInd = 0; + for (auto& x : GetScene().environmentProbes) + { + envMaps[envProbeInd] = x->cubeMap.GetTexture(); + envMapPositions[envProbeInd] = x->translation; + envProbeInd++; + if (envProbeInd >= ARRAYSIZE(envMaps)) + break; + } + + MiscCB envProbeCB; + envProbeCB.mTransform.r[0] = XMLoadFloat3(&envMapPositions[0]); + envProbeCB.mTransform.r[1] = XMLoadFloat3(&envMapPositions[1]); + envProbeCB.mTransform = XMMatrixTranspose(envProbeCB.mTransform); + GetDevice()->UpdateBuffer(constantBuffers[CBTYPE_MISC], &envProbeCB, threadID); + GetDevice()->BindResourcePS(envMaps[0], TEXSLOT_ENV0, threadID); + GetDevice()->BindResourcePS(envMaps[1], TEXSLOT_ENV1, threadID); + } } @@ -2079,12 +2142,8 @@ void wiRenderer::DrawImagesNormals(GRAPHICSTHREAD threadID, Texture2D* refracRes } void wiRenderer::DrawLights(Camera* camera, GRAPHICSTHREAD threadID) { - Frustum frustum; - frustum.ConstructFrustum(min(camera->zFarP, GetScene().worldInfo.fogSEH.y),camera->Projection,camera->View); - - CulledList culledObjects; - if(spTree_lights) - wiSPTree::getVisible(spTree_lights->root,frustum,culledObjects); + const FrameCulling& culling = frameCullings[camera]; + const CulledList& culledLights = culling.culledLights; GetDevice()->EventBegin(L"Light Render", threadID); @@ -2143,7 +2202,7 @@ void wiRenderer::DrawLights(Camera* camera, GRAPHICSTHREAD threadID) } - for(Cullable* c : culledObjects){ + for(Cullable* c : culledLights){ Light* l = (Light*)c; if (l->type != type) continue; @@ -2222,15 +2281,10 @@ void wiRenderer::DrawLights(Camera* camera, GRAPHICSTHREAD threadID) } void wiRenderer::DrawVolumeLights(Camera* camera, GRAPHICSTHREAD threadID) { - Frustum frustum; - frustum.ConstructFrustum(min(camera->zFarP, GetScene().worldInfo.fogSEH.y), camera->Projection, camera->View); + const FrameCulling& culling = frameCullings[camera]; + const CulledList& culledLights = culling.culledLights; - - CulledList culledObjects; - if(spTree_lights) - wiSPTree::getVisible(spTree_lights->root,frustum,culledObjects); - - if(!culledObjects.empty()) + if(!culledLights.empty()) { GetDevice()->EventBegin(L"Light Volume Render", threadID); @@ -2259,7 +2313,7 @@ void wiRenderer::DrawVolumeLights(Camera* camera, GRAPHICSTHREAD threadID) GetDevice()->BindVS(vertexShaders[VSTYPE_VOLUMESPOTLIGHT],threadID); } - for(Cullable* c : culledObjects){ + for(Cullable* c : culledLights){ Light* l = (Light*)c; if(l->type==type && l->noHalo==false){ @@ -2312,14 +2366,12 @@ void wiRenderer::DrawVolumeLights(Camera* camera, GRAPHICSTHREAD threadID) } -void wiRenderer::DrawLensFlares(GRAPHICSTHREAD threadID){ - - - CulledList culledObjects; - if(spTree_lights) - wiSPTree::getVisible(spTree_lights->root,cam->frustum,culledObjects); +void wiRenderer::DrawLensFlares(GRAPHICSTHREAD threadID) +{ + const FrameCulling& culling = frameCullings[getCamera()]; + const CulledList& culledLights = culling.culledLights; - for(Cullable* c:culledObjects) + for(Cullable* c: culledLights) { Light* l = (Light*)c; @@ -2362,12 +2414,12 @@ void wiRenderer::ClearShadowMaps(GRAPHICSTHREAD threadID){ } void wiRenderer::DrawForShadowMap(GRAPHICSTHREAD threadID) { - if (GameSpeed) { + if (GameSpeed) + { GetDevice()->EventBegin(L"ShadowMap Render", threadID); - CulledList culledLights; - if (spTree_lights) - wiSPTree::getVisible(spTree_lights->root, cam->frustum, culledLights); + const FrameCulling& culling = frameCullings[getCamera()]; + const CulledList& culledLights = culling.culledLights; if (culledLights.size() > 0) { @@ -2940,39 +2992,12 @@ void wiRenderer::DrawWorld(Camera* camera, bool tessellation, GRAPHICSTHREAD thr { tessellation = tessellation && GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_TESSELLATION); - CulledCollection culledRenderer; - CulledList culledObjects; - if(spTree) - wiSPTree::getVisible(spTree->root, camera->frustum,culledObjects,wiSPTree::SortType::SP_TREE_SORT_FRONT_TO_BACK); - else return; + const FrameCulling& culling = frameCullings[camera]; + const CulledList& culledObjects = culling.culledObjects; + const CulledCollection& culledRenderer = culling.culledRenderer; if(!culledObjects.empty()) { - - Texture2D* envMaps[] = { enviroMap, enviroMap }; - XMFLOAT3 envMapPositions[] = { XMFLOAT3(0,0,0),XMFLOAT3(0,0,0) }; - GetScene().environmentProbes.sort( - [&](EnvironmentProbe* a, EnvironmentProbe* b) { - return wiMath::DistanceSquared(a->translation, getCamera()->translation) < wiMath::DistanceSquared(b->translation, getCamera()->translation); - } - ); - int envProbeInd = 0; - for (auto& x : GetScene().environmentProbes) - { - envMaps[envProbeInd] = x->cubeMap.GetTexture(); - envMapPositions[envProbeInd] = x->translation; - envProbeInd++; - if (envProbeInd >= ARRAYSIZE(envMaps)) - break; - } - - MiscCB envProbeCB; - envProbeCB.mTransform.r[0] = XMLoadFloat3(&envMapPositions[0]); - envProbeCB.mTransform.r[1] = XMLoadFloat3(&envMapPositions[1]); - envProbeCB.mTransform = XMMatrixTranspose(envProbeCB.mTransform); - GetDevice()->UpdateBuffer(constantBuffers[CBTYPE_MISC], &envProbeCB, threadID); - GetDevice()->BindResourcePS(envMaps[0], TEXSLOT_ENV0, threadID); - GetDevice()->BindResourcePS(envMaps[1], TEXSLOT_ENV1, threadID); if (shaderType == SHADERTYPE_TILEDFORWARD) { @@ -2989,7 +3014,6 @@ void wiRenderer::DrawWorld(Camera* camera, bool tessellation, GRAPHICSTHREAD thr for(Cullable* object : culledObjects){ - culledRenderer[((Object*)object)->mesh].insert((Object*)object); if(grass){ for(wiHairParticle* hair : ((Object*)object)->hParticleSystems){ hair->Draw(camera, shaderType, threadID); @@ -3025,9 +3049,9 @@ void wiRenderer::DrawWorld(Camera* camera, bool tessellation, GRAPHICSTHREAD thr } - for (CulledCollection::iterator iter = culledRenderer.begin(); iter != culledRenderer.end(); ++iter) { + for (CulledCollection::const_iterator iter = culledRenderer.begin(); iter != culledRenderer.end(); ++iter) { Mesh* mesh = iter->first; - CulledObjectList& visibleInstances = iter->second; + const CulledObjectList& visibleInstances = iter->second; float tessF = mesh->getTessellationFactor(); @@ -3231,10 +3255,10 @@ void wiRenderer::DrawWorld(Camera* camera, bool tessellation, GRAPHICSTHREAD thr void wiRenderer::DrawWorldTransparent(Camera* camera, SHADERTYPE shaderType, Texture2D* refracRes, Texture2D* refRes , Texture2D* waterRippleNormals, GRAPHICSTHREAD threadID, bool grass) { - CulledCollection culledRenderer; - CulledList culledObjects; - if (spTree) - wiSPTree::getVisible(spTree->root, camera->frustum,culledObjects, wiSPTree::SortType::SP_TREE_SORT_PAINTER); + + const FrameCulling& culling = frameCullings[camera]; + const CulledList& culledObjects = culling.culledObjects_transparent; + const CulledCollection& culledRenderer = culling.culledRenderer; if(!culledObjects.empty()) { @@ -3254,7 +3278,6 @@ void wiRenderer::DrawWorldTransparent(Camera* camera, SHADERTYPE shaderType, Tex hair->Draw(camera, shaderType, threadID); } } - culledRenderer[((Object*)object)->mesh].insert((Object*)object); } GetDevice()->BindPrimitiveTopology(TRIANGLELIST,threadID); @@ -3281,9 +3304,9 @@ void wiRenderer::DrawWorldTransparent(Camera* camera, SHADERTYPE shaderType, Tex GetDevice()->BindBlendState(blendStates[BSTYPE_OPAQUE],threadID); - for (CulledCollection::iterator iter = culledRenderer.begin(); iter != culledRenderer.end(); ++iter) { + for (CulledCollection::const_iterator iter = culledRenderer.begin(); iter != culledRenderer.end(); ++iter) { Mesh* mesh = iter->first; - CulledObjectList& visibleInstances = iter->second; + const CulledObjectList& visibleInstances = iter->second; bool isValid = false; for (MeshSubset& subset : mesh->subsets) @@ -3548,14 +3571,14 @@ void wiRenderer::ComputeTiledLightCulling(GRAPHICSTHREAD threadID) dispatchParams.numThreadGroups[2] = 1; // Fill Light Array with lights in the frustum - CulledList culledObjects; - if (spTree_lights) - wiSPTree::getVisible(spTree_lights->root, getCamera()->frustum, culledObjects); + const FrameCulling& culling = frameCullings[getCamera()]; + const CulledList& culledLights = culling.culledLights; + static LightArrayType* lightArray = (LightArrayType*)_mm_malloc(sizeof(LightArrayType)*MAX_LIGHTS, 16); ZeroMemory(lightArray, sizeof(lightArray)); UINT lightCounter = 0; - for (Cullable* c : culledObjects) + for (Cullable* c : culledLights) { Light* l = (Light*)c; @@ -3732,14 +3755,10 @@ void wiRenderer::ComputeTiledLightCulling(GRAPHICSTHREAD threadID) } void wiRenderer::EnableForwardShadowmaps(GRAPHICSTHREAD threadID) { - Frustum frustum; - frustum.ConstructFrustum(min(getCamera()->zFarP, GetScene().worldInfo.fogSEH.y), getCamera()->Projection, getCamera()->View); + const FrameCulling& culling = frameCullings[getCamera()]; + const CulledList& culledLights = culling.culledLights; - CulledList culledObjects; - if (spTree_lights) - wiSPTree::getVisible(spTree_lights->root, frustum, culledObjects); - - for (Cullable* c : culledObjects) + for (Cullable* c : culledLights) { Light* l = (Light*)c; diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index e5541c5e1..53716ccb3 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -389,6 +389,15 @@ public: static Vertex TransformVertex(const Mesh* mesh, int vertexI, const XMMATRIX& mat = XMMatrixIdentity()); static Vertex TransformVertex(const Mesh* mesh, const SkinnedVertex& vertex, const XMMATRIX& mat = XMMatrixIdentity()); static XMFLOAT3 VertexVelocity(const Mesh* mesh, const int& vertexI); + + struct FrameCulling + { + CulledCollection culledRenderer; + CulledList culledObjects; + CulledList culledObjects_transparent; + CulledList culledLights; + }; + static unordered_map frameCullings; public: diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 21530f09f..bc7a819b7 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -7,7 +7,7 @@ namespace wiVersion // minor features, major updates const int minor = 9; // minor bug fixes, alterations, refactors, updates - const int revision = 2; + const int revision = 4; long GetVersion()