updated tiled lighting

This commit is contained in:
turanszkij
2016-10-03 23:42:43 +02:00
parent 5189aca1d7
commit 684bb1ea73
11 changed files with 180 additions and 96 deletions
+1 -1
View File
@@ -180,7 +180,7 @@ void Renderable3DComponent::Compose(){
RenderColorGradedComposition();
//wiImage::Draw(wiRenderer::ComputeTiledLightCulling(GRAPHICSTHREAD_IMMEDIATE), wiImageEffects((float)wiRenderer::GetDevice()->GetScreenWidth(), (float)wiRenderer::GetDevice()->GetScreenHeight()));
//wiImage::Draw((Texture2D*)wiRenderer::textures[TEXTYPE_2D_DEBUGUAV], wiImageEffects((float)wiRenderer::GetDevice()->GetScreenWidth(), (float)wiRenderer::GetDevice()->GetScreenHeight()));
Renderable2DComponent::Compose();
}
+46
View File
@@ -108,4 +108,50 @@ bool PointInsidePlane(float3 p, Plane plane)
return dot(plane.N, p) - plane.d < 0;
}
struct Cone
{
float3 T; // Cone tip.
float h; // Height of the cone.
float3 d; // Direction of the cone.
float r; // bottom radius of the cone.
};
// Check to see if a cone if fully behind (inside the negative halfspace of) a plane.
// Source: Real-time collision detection, Christer Ericson (2005)
bool ConeInsidePlane(Cone cone, Plane plane)
{
// Compute the farthest point on the end of the cone to the positive space of the plane.
float3 m = cross(cross(plane.N, cone.d), cone.d);
float3 Q = cone.T + cone.d * cone.h - m * cone.r;
// The cone is in the negative halfspace of the plane if both
// the tip of the cone and the farthest point on the end of the cone to the
// positive halfspace of the plane are both inside the negative halfspace
// of the plane.
return PointInsidePlane(cone.T, plane) && PointInsidePlane(Q, plane);
}
bool ConeInsideFrustum(Cone cone, Frustum frustum, float zNear, float zFar)
{
bool result = true;
Plane nearPlane = { float3(0, 0, 1), zNear };
Plane farPlane = { float3(0, 0, -1), -zFar };
// First check the near and far clipping planes.
if (ConeInsidePlane(cone, nearPlane) || ConeInsidePlane(cone, farPlane))
{
result = false;
}
// Then check frustum planes
for (int i = 0; i < 4 && result; i++)
{
if (ConeInsidePlane(cone, frustum.planes[i]))
{
result = false;
}
}
return result;
}
#endif // _CULLING_SHADER_HF_
+30 -64
View File
@@ -2,8 +2,10 @@
#include "cullingShaderHF.hlsli"
#include "tiledLightingHF.hlsli"
//RWTEXTURE2D(DebugTexture, float4, UAVSLOT_DEBUGTEXTURE);
//groupshared uint _counter = 0;
#ifdef DEBUG_TILEDLIGHTCULLING
RWTEXTURE2D(DebugTexture, float4, UAVSLOT_DEBUGTEXTURE);
groupshared uint _counter = 0;
#endif
STRUCTUREDBUFFER(in_Frustums, Frustum, SBSLOT_TILEFRUSTUMS);
@@ -87,45 +89,6 @@ void main(ComputeShaderInput IN)
// Get frustum from frustum buffer:
GroupFrustum = in_Frustums[IN.groupID.x + (IN.groupID.y * xDispatchParams_numThreads.x)]; // numthreads is from the frustum computation phase, so not actual number of threads here
//// Calculate frustum in place:
//{
// // View space eye position is always at the origin.
// const float3 eyePos = float3(0, 0, 0);
// // Compute 4 points on the far clipping plane to use as the
// // frustum vertices.
// float4 screenSpace[4];
// // Top left point
// screenSpace[0] = float4(IN.dispatchThreadID.xy, 1.0f, 1.0f);
// // Top right point
// screenSpace[1] = float4(float2(IN.dispatchThreadID.x + BLOCK_SIZE, IN.dispatchThreadID.y), 1.0f, 1.0f);
// // Bottom left point
// screenSpace[2] = float4(float2(IN.dispatchThreadID.x, IN.dispatchThreadID.y + BLOCK_SIZE), 1.0f, 1.0f);
// // Bottom right point
// screenSpace[3] = float4(float2(IN.dispatchThreadID.x + BLOCK_SIZE, IN.dispatchThreadID.y + BLOCK_SIZE), 1.0f, 1.0f);
// float3 viewSpace[4];
// // Now convert the screen space points to view space
// for (int i = 0; i < 4; i++)
// {
// viewSpace[i] = ScreenToView(screenSpace[i]).xyz;
// }
// // Now build the frustum planes from the view space points
// Frustum frustum;
// // Left plane
// frustum.planes[0] = ComputePlane(eyePos, viewSpace[2], viewSpace[0]);
// // Right plane
// frustum.planes[1] = ComputePlane(eyePos, viewSpace[1], viewSpace[3]);
// // Top plane
// frustum.planes[2] = ComputePlane(eyePos, viewSpace[0], viewSpace[1]);
// // Bottom plane
// frustum.planes[3] = ComputePlane(eyePos, viewSpace[3], viewSpace[2]);
// GroupFrustum = frustum;
//}
}
GroupMemoryBarrierWithGroupSync();
@@ -138,9 +101,6 @@ void main(ComputeShaderInput IN)
float fMinDepth = asfloat(uMinDepth);
float fMaxDepth = asfloat(uMaxDepth);
//fMinDepth = g_xCamera_ZFarP;
//fMaxDepth = g_xCamera_ZNearP;
// Convert depth values to view space.
float minDepthVS = ScreenToView(float4(0, 0, fMinDepth, 1)).z;
float maxDepthVS = ScreenToView(float4(0, 0, fMaxDepth, 1)).z;
@@ -162,7 +122,7 @@ void main(ComputeShaderInput IN)
{
case 1/*POINT_LIGHT*/:
{
Sphere sphere = { light.PositionVS.xyz, light.range };
Sphere sphere = { light.positionVS.xyz, light.range };
if (SphereInsideFrustum(sphere, GroupFrustum, nearClipVS, maxDepthVS))
{
//// Add light to light list for transparent geometry.
@@ -175,29 +135,34 @@ void main(ComputeShaderInput IN)
// Add light to light list for opaque geometry.
o_AppendLight(i);
//InterlockedAdd(_counter, 1);
#ifdef DEBUG_TILEDLIGHTCULLING
InterlockedAdd(_counter, 1);
#endif
}
}
}
break;
//case SPOT_LIGHT:
//{
// float coneRadius = tan(radians(light.SpotlightAngle)) * light.distance;
// Cone cone = { light.PositionVS.xyz, light.distance, light.DirectionVS.xyz, coneRadius };
// if (ConeInsideFrustum(cone, GroupFrustum, nearClipVS, maxDepthVS))
// {
// // Add light to light list for transparent geometry.
// t_AppendLight(i);
case 2/*SPOT_LIGHT*/:
{
float coneRadius = tan(/*radians*/(light.coneAngle)) * light.range;
Cone cone = { light.positionVS.xyz, light.range, -light.directionVS.xyz, coneRadius };
if (ConeInsideFrustum(cone, GroupFrustum, nearClipVS, maxDepthVS))
{
// Add light to light list for transparent geometry.
t_AppendLight(i);
#ifdef DEBUG_TILEDLIGHTCULLING
InterlockedAdd(_counter, 1);
#endif
// if (!ConeInsidePlane(cone, minPlane))
// {
// // Add light to light list for opaque geometry.
// o_AppendLight(i);
// }
// }
//}
//break;
if (!ConeInsidePlane(cone, minPlane))
{
// Add light to light list for opaque geometry.
o_AppendLight(i);
}
}
}
break;
case 0/*DIRECTIONAL_LIGHT*/:
{
// Directional lights always get added to our light list.
@@ -240,6 +205,7 @@ void main(ComputeShaderInput IN)
t_LightIndexList[t_LightIndexStartOffset + i] = t_LightList[i];
}
//DebugTexture[texCoord] = float4((float)_counter / (float)lightCount,0,0,1);
#ifdef DEBUG_TILEDLIGHTCULLING
DebugTexture[texCoord] = float4((float)_counter / (float)lightCount,0,0,0.75);
#endif
}
+2
View File
@@ -4,4 +4,6 @@
#define BLOCK_SIZE 16
#define MAX_LIGHTS 1024
//#define DEBUG_TILEDLIGHTCULLING
#endif // _LIGHTCULLING_INTEROP_H_
+39 -10
View File
@@ -178,7 +178,7 @@ inline void TiledLighting(in float2 pixel, in float3 N, in float3 V, in float3 P
uint lightIndex = LightIndexList[startOffset + i];
LightArrayType light = LightArray[lightIndex];
float3 L = light.PositionWS - P;
float3 L = light.positionWS - P;
float lightDistance = length(L);
if (light.type > 0 && lightDistance > light.range)
continue;
@@ -188,20 +188,21 @@ inline void TiledLighting(in float2 pixel, in float3 N, in float3 V, in float3 P
float3 lightColor = light.color.rgb * light.energy;
[branch]
switch (light.type)
{
case 0/*DIRECTIONAL*/:
{
L = light.direction.xyz;
L = light.directionWS.xyz;
BRDF_MAKE(N, L, V);
result.specular = lightColor * BRDF_SPECULAR(roughness, f0);
result.diffuse = lightColor * BRDF_DIFFUSE(roughness);
float sh = max(NdotL, 0);
float4 ShPos[3];
ShPos[0] = mul(float4(P, 1), g_xDirLight_ShM[0]);
ShPos[1] = mul(float4(P, 1), g_xDirLight_ShM[1]);
ShPos[2] = mul(float4(P, 1), g_xDirLight_ShM[2]);
ShPos[0] = mul(float4(P, 1), light.shadowMat[0]);
ShPos[1] = mul(float4(P, 1), light.shadowMat[1]);
ShPos[2] = mul(float4(P, 1), light.shadowMat[2]);
float3 ShTex[3];
ShTex[0] = ShPos[0].xyz*float3(1, -1, 1) / ShPos[0].w / 2.0f + 0.5f;
ShTex[1] = ShPos[1].xyz*float3(1, -1, 1) / ShPos[1].w / 2.0f + 0.5f;
@@ -255,19 +256,47 @@ inline void TiledLighting(in float2 pixel, in float3 N, in float3 V, in float3 P
//}
result.diffuse *= sh;
result.specular *= sh;
result.diffuse = max(result.diffuse, 0);
result.specular = max(result.specular, 0);
}
break;
case 2/*SPOT*/:
{
float SpotFactor = dot(L, light.directionWS);
float spotCutOff = light.coneAngleCos;
[branch]if (SpotFactor > spotCutOff)
{
BRDF_MAKE(N, L, V);
result.specular = lightColor * BRDF_SPECULAR(roughness, f0);
result.diffuse = lightColor * BRDF_DIFFUSE(roughness);
float att = (light.energy * (light.range / (light.range + 1 + lightDistance)));
float attenuation = /*saturate*/(att * (light.range - lightDistance) / light.range);
attenuation *= saturate((1.0 - (1.0 - SpotFactor) * 1.0 / (1.0 - spotCutOff)));
result.diffuse *= attenuation;
result.specular *= attenuation;
float sh = max(NdotL, 0);
//float4 ShPos = mul(float4(P, 1), xShMat);
//float2 ShTex = ShPos.xy / ShPos.w * float2(0.5f, -0.5f) + float2(0.5f, 0.5f);
//[branch]if ((saturate(ShTex.x) == ShTex.x) && (saturate(ShTex.y) == ShTex.y))
//{
// //light.r+=1.0f;
// sh *= shadowCascade(ShPos, ShTex, texture_shadow0);
//}
result.diffuse *= sh;
result.specular *= sh;
result.diffuse = max(result.diffuse, 0);
result.specular = max(result.specular, 0);
}
}
break;
}
diffuse += result.diffuse;
specular += result.specular;
diffuse += max(0.0f, result.diffuse);
specular += max(0.0f, result.specular);
}
}
+16 -7
View File
@@ -3,17 +3,26 @@
struct LightArrayType
{
float3 PositionVS; // View Space!
float3 positionVS; // View Space!
float range;
// --
float4 color;
float3 PositionWS;
// --
float3 positionWS;
float energy;
float3 direction;
uint type;
float shadowBias;
// --
float3 directionVS;
float _pad0;
float _pad1;
float _pad2;
// --
float3 directionWS;
uint type;
// --
float shadowBias;
uint shadowMap_index;
float coneAngle;
float coneAngleCos;
// --
float4x4 shadowMat[3];
};
#endif // _TILEDLIGHTING_HF_
+7
View File
@@ -4049,6 +4049,13 @@ Light::~Light() {
for (string x : lensFlareNames)
wiResourceManager::GetGlobal()->del(x);
}
XMFLOAT3 Light::GetDirection()
{
XMMATRIX rot = XMMatrixRotationQuaternion(XMLoadFloat4(&rotation));
XMFLOAT3 retVal;
XMStoreFloat3(&retVal, XMVector3Normalize(-XMVector3Transform(XMVectorSet(0, -1, 0, 1), rot)));
return retVal;
}
void Light::UpdateTransform()
{
Transform::UpdateTransform();
+2
View File
@@ -794,6 +794,8 @@ struct Light : public Cullable , public Transform
};
LightType type;
XMFLOAT3 GetDirection();
Light();
virtual ~Light();
virtual void UpdateTransform();
+29 -9
View File
@@ -1425,7 +1425,7 @@ void wiRenderer::UpdatePerFrameData()
{
for (auto& x : frameCullings)
{
Camera* cam = x.first;
Camera* camera = x.first;
FrameCulling& culling = x.second;
culling.culledRenderer.clear();
@@ -1435,12 +1435,12 @@ void wiRenderer::UpdatePerFrameData()
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_BACK_TO_FRONT);
wiSPTree::getVisible(spTree->root, camera->frustum, culling.culledObjects, wiSPTree::SortType::SP_TREE_SORT_FRONT_TO_BACK);
wiSPTree::getVisible(spTree->root, camera->frustum, culling.culledObjects_transparent, wiSPTree::SortType::SP_TREE_SORT_BACK_TO_FRONT);
for (Cullable* object : culling.culledObjects)
{
for (wiHairParticle* hair : ((Object*)object)->hParticleSystems) {
hair->PerformCulling(cam);
hair->PerformCulling(camera);
}
culling.culledRenderer[((Object*)object)->mesh].insert((Object*)object);
}
@@ -1448,7 +1448,7 @@ void wiRenderer::UpdatePerFrameData()
if (spTree_lights != nullptr)
{
Frustum frustum;
frustum.ConstructFrustum(min(cam->zFarP, GetScene().worldInfo.fogSEH.y), cam->Projection, cam->View);
frustum.ConstructFrustum(min(camera->zFarP, GetScene().worldInfo.fogSEH.y), camera->Projection, camera->View);
wiSPTree::getVisible(spTree_lights->root, frustum, culling.culledLights);
}
}
@@ -2246,7 +2246,7 @@ void wiRenderer::DrawLights(Camera* camera, GRAPHICSTHREAD threadID)
else if(type==2) //spot
{
SpotLightCB lcb;
const float coneS=(const float)(l->enerDis.z/0.7853981852531433);
const float coneS = (const float)(l->enerDis.z / XM_PIDIV4);
XMMATRIX world,rot;
world = XMMatrixTranspose(
XMMatrixScaling(coneS*l->enerDis.y,l->enerDis.y,coneS*l->enerDis.y)*
@@ -3578,23 +3578,41 @@ void wiRenderer::ComputeTiledLightCulling(GRAPHICSTHREAD threadID)
static LightArrayType* lightArray = (LightArrayType*)_mm_malloc(sizeof(LightArrayType)*MAX_LIGHTS, 16);
ZeroMemory(lightArray, sizeof(lightArray));
XMMATRIX viewMatrix = cam->GetView();
UINT lightCounter = 0;
for (Cullable* c : culledLights)
{
Light* l = (Light*)c;
lightArray[lightCounter].posWS = l->translation;
XMStoreFloat3(&lightArray[lightCounter].posVS, XMVector3TransformCoord(XMLoadFloat3(&lightArray[lightCounter].posWS), cam->GetView()));
XMStoreFloat3(&lightArray[lightCounter].posVS, XMVector3TransformCoord(XMLoadFloat3(&lightArray[lightCounter].posWS), viewMatrix));
lightArray[lightCounter].distance = l->enerDis.y;
lightArray[lightCounter].col = l->color;
lightArray[lightCounter].energy = l->enerDis.x;
lightArray[lightCounter].type = l->type;
lightArray[lightCounter].shadowBias = l->shadowBias;
lightArray[lightCounter].shadowMap_index = l->shadowMap_index;
switch (l->type)
{
case Light::DIRECTIONAL:
{
XMStoreFloat3(&lightArray[lightCounter].direction, XMVector3Normalize(-XMVector3Transform(XMVectorSet(0, -1, 0, 1), XMMatrixRotationQuaternion(XMLoadFloat4(&l->rotation)))));
lightArray[lightCounter].directionWS = l->GetDirection();
for (unsigned int shmap = 0; shmap < min(l->shadowCam_dirLight.size(),ARRAYSIZE(lightArray[lightCounter].shadowMatrix)); ++shmap) {
lightArray[lightCounter].shadowMatrix[shmap] = l->shadowCam_dirLight[shmap].getVP();
}
}
break;
case Light::SPOT:
{
lightArray[lightCounter].coneAngle = (l->enerDis.z * 0.5f);
lightArray[lightCounter].coneAngleCos = cosf(lightArray[lightCounter].coneAngle);
lightArray[lightCounter].directionWS = l->GetDirection();
XMStoreFloat3(&lightArray[lightCounter].directionVS, XMVector3TransformNormal(XMLoadFloat3(&lightArray[lightCounter].directionWS), viewMatrix));
if (l->shadow && l->shadowMap_index >= 0)
{
lightArray[lightCounter].shadowMatrix[0] = l->shadowCam_spotLight[0].getVP();
}
}
break;
default:
@@ -3739,7 +3757,9 @@ void wiRenderer::ComputeTiledLightCulling(GRAPHICSTHREAD threadID)
device->BindResourceCS(frustumBuffer, SBSLOT_TILEFRUSTUMS, threadID);
device->BindCS(computeShaders[CSTYPE_TILEDLIGHTCULLING], threadID);
//device->BindUnorderedAccessResourceCS(textures[TEXTYPE_2D_DEBUGUAV], UAVSLOT_DEBUGTEXTURE, threadID);
#ifdef DEBUG_TILEDLIGHTCULLING
device->BindUnorderedAccessResourceCS(textures[TEXTYPE_2D_DEBUGUAV], UAVSLOT_DEBUGTEXTURE, threadID);
#endif
device->BindUnorderedAccessResourceCS(lightCounterHelper_Opaque, UAVSLOT_LIGHTINDEXCOUNTERHELPER_OPAQUE, threadID);
device->BindUnorderedAccessResourceCS(lightCounterHelper_Transparent, UAVSLOT_LIGHTINDEXCOUNTERHELPER_TRANSPARENT, threadID);
device->BindUnorderedAccessResourceCS(resourceBuffers[RBTYPE_LIGHTINDEXLIST_OPAQUE], UAVSLOT_LIGHTINDEXLIST_OPAQUE, threadID);
+7 -4
View File
@@ -285,12 +285,15 @@ public:
XMFLOAT4 col;
XMFLOAT3 posWS;
float energy;
XMFLOAT3 direction;
XMFLOAT3 directionVS;
float __pad0;
XMFLOAT3 directionWS;
UINT type;
float shadowBias;
float _pad0;
float _pad1;
float _pad2;
UINT shadowMap_index;
float coneAngle;
float coneAngleCos;
XMMATRIX shadowMatrix[3];
STRUCTUREDBUFFER_SETBINDSLOT(SBSLOT_LIGHTARRAY)
+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 = 5;
const int revision = 6;
long GetVersion()