improved culling

This commit is contained in:
turanszkij
2016-10-03 00:06:45 +02:00
parent 170853ab8f
commit 46ec5a30f1
5 changed files with 189 additions and 111 deletions
+73 -30
View File
@@ -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<Point> 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(dis<LOD[i]){
culledPatches.erase(iter++);
culled=NULL;
renderPoints.insert(renderPoints.end(),patch->p.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<Point>& 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 (dis<LOD[i]) {
culledPatches.erase(iter++);
culled = NULL;
renderPoints.insert(renderPoints.end(), patch->p.begin(), patch->p.end());
}
else
++iter;
}
}
}
}
wiHairParticle::Patch::Patch(){
p.resize(0);
+8 -1
View File
@@ -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<Point> renderPoints[3]; // per lod
};
unordered_map<Camera*, FrameCulling> 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();
+98 -79
View File
@@ -79,6 +79,8 @@ vector<Cube> wiRenderer::cubes;
vector<wiTranslator*> wiRenderer::renderableTranslators;
vector<pair<XMFLOAT4X4, XMFLOAT4>> wiRenderer::renderableBoxes;
unordered_map<Camera*, wiRenderer::FrameCulling> 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;
+9
View File
@@ -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<Camera*, FrameCulling> frameCullings;
public:
+1 -1
View File
@@ -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()