diff --git a/WickedEngine/cullingShaderHF.hlsli b/WickedEngine/cullingShaderHF.hlsli index 6d50fc6b0..c363c18d1 100644 --- a/WickedEngine/cullingShaderHF.hlsli +++ b/WickedEngine/cullingShaderHF.hlsli @@ -4,14 +4,14 @@ CBUFFER(DispatchParams, CBSLOT_RENDERER_DISPATCHPARAMS) { // Number of groups dispatched. (This parameter is not available as an HLSL system value!) - uint3 numThreadGroups; - uint padding0; // implicit padding to 16 bytes. + uint3 xDispatchParams_numThreadGroups; + uint xDispatchParams_value0; // extra value / padding // Total number of threads dispatched. (Also not available as an HLSL system value!) // Note: This value may be less than the actual number of threads executed // if the screen size is not evenly divisible by the block size. - uint3 numThreads; - uint padding1; // implicit padding to 16 bytes. + uint3 xDispatchParams_numThreads; + uint xDispatchParams_value1; // extra value / padding } struct Plane @@ -85,10 +85,7 @@ bool SphereInsideFrustum(Sphere sphere, Frustum frustum, float zNear, float zFar { bool result = true; - // First check depth - // Note: Here, the view vector points in the -Z axis so the - // far depth value will be approaching -infinity. - if (sphere.c.z - sphere.r > zNear || sphere.c.z + sphere.r < zFar) + if (sphere.c.z + sphere.r < zNear || sphere.c.z - sphere.r > zFar) { result = false; } diff --git a/WickedEngine/lightCullingCS.hlsl b/WickedEngine/lightCullingCS.hlsl index 3308439dc..f5b40c2b7 100644 --- a/WickedEngine/lightCullingCS.hlsl +++ b/WickedEngine/lightCullingCS.hlsl @@ -12,7 +12,7 @@ struct Light float4 col; }; STRUCTUREDBUFFER(Lights, Light, SBSLOT_LIGHTARRAY); -#define lightCount ((uint)g_xColor.x) +#define lightCount xDispatchParams_value0 groupshared uint uMinDepth; @@ -40,7 +40,48 @@ void main(ComputeShaderInput IN) uMaxDepth = 0; //o_LightCount = 0; //t_LightCount = 0; - GroupFrustum = in_Frustums[IN.groupID.x + (IN.groupID.y * numThreadGroups.x)]; + + //// Get frustum from frustum buffer: + //GroupFrustum = in_Frustums[IN.groupID.x + (IN.groupID.y * xDispatchParams_numThreadGroups.x)]; + + // 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(); @@ -53,6 +94,9 @@ 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; @@ -60,7 +104,7 @@ void main(ComputeShaderInput IN) // Clipping plane for minimum depth value // (used for testing lights within the bounds of opaque geometry). - Plane minPlane = { float3(0, 0, -1), -minDepthVS }; + Plane minPlane = { float3(0, 0, 1), minDepthVS }; // Cull lights // Each thread in a group will cull 1 light until all lights have been culled. @@ -80,13 +124,14 @@ void main(ComputeShaderInput IN) //// Add light to light list for transparent geometry. //t_AppendLight(i); - //if (!SphereInsidePlane(sphere, minPlane)) - //{ - // // Add light to light list for opaque geometry. - // o_AppendLight(i); - //} + if (!SphereInsidePlane(sphere, minPlane)) + { + // Add light to light list for opaque geometry. + //o_AppendLight(i); + + InterlockedAdd(_counter, 1); + } - InterlockedAdd(_counter, 1); } //} //break; diff --git a/WickedEngine/tileFrustumsCS.hlsl b/WickedEngine/tileFrustumsCS.hlsl index 4cf254c7b..5c04adeb9 100644 --- a/WickedEngine/tileFrustumsCS.hlsl +++ b/WickedEngine/tileFrustumsCS.hlsl @@ -43,10 +43,9 @@ void main(ComputeShaderInput IN) frustum.planes[3] = ComputePlane(eyePos, viewSpace[3], viewSpace[2]); // Store the computed frustum in global memory (if our thread ID is in bounds of the grid). - if (IN.dispatchThreadID.x < numThreads.x && IN.dispatchThreadID.y < numThreads.y) + if (IN.dispatchThreadID.x < xDispatchParams_numThreads.x && IN.dispatchThreadID.y < xDispatchParams_numThreads.y) { - uint index = IN.dispatchThreadID.x + (IN.dispatchThreadID.y * numThreads.x); + uint index = IN.dispatchThreadID.x + (IN.dispatchThreadID.y * xDispatchParams_numThreads.x); out_Frustums[index] = frustum; } - //out_Frustums[0].planes[0].N = float3(1, 0, 1); } \ No newline at end of file diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 6fbe364e5..38386d958 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -3316,16 +3316,48 @@ Texture2D* wiRenderer::ComputeTiledLightCulling(GRAPHICSTHREAD threadID) // Calc dispatchparams - int _B = 16; + UINT _B = 16; DispatchParamsCB dispatchParams; - dispatchParams.numThreads[0] = (UINT)ceilf((float)_width / _B); - dispatchParams.numThreads[1] = (UINT)ceilf((float)_height / _B); - dispatchParams.numThreads[2] = 1; - dispatchParams.numThreadGroups[0] = (UINT)ceilf((float)dispatchParams.numThreads[0] / _B); - dispatchParams.numThreadGroups[1] = (UINT)ceilf((float)dispatchParams.numThreads[1] / _B); - dispatchParams.numThreadGroups[2] = 1; - device->UpdateBuffer(constantBuffers[CBTYPE_DISPATCHPARAMS], &dispatchParams, threadID); - device->BindConstantBufferCS(constantBuffers[CBTYPE_DISPATCHPARAMS], CB_GETBINDSLOT(DispatchParamsCB), threadID); + { + dispatchParams.numThreads[0] = (UINT)ceilf(_width / (float)_B); + dispatchParams.numThreads[1] = (UINT)ceilf(_height / (float)_B); + dispatchParams.numThreads[2] = 1; + dispatchParams.numThreadGroups[0] = (UINT)ceilf(dispatchParams.numThreads[0] / (float)_B); + dispatchParams.numThreadGroups[1] = (UINT)ceilf(dispatchParams.numThreads[1] / (float)_B); + 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); + static LightArrayType lightArray[1024]; + ZeroMemory(lightArray, sizeof(lightArray)); + + UINT lightCounter = 0; + for (Cullable* c : culledObjects) + { + Light* l = (Light*)c; + + //lightArray[counter].pos = l->translation; + XMStoreFloat3(&lightArray[lightCounter].pos, XMVector3TransformCoord(XMLoadFloat3(&l->translation), cam->GetView())); + lightArray[lightCounter].radius = l->enerDis.y; + lightArray[lightCounter].col = l->color; + + lightCounter++; + if (lightCounter == 1024) + { + assert(0 && "Over 1024 lights are in the frustum!"); + break; + } + } + device->UpdateBuffer(resourceBuffers[RBTYPE_LIGHTARRAY], lightArray, threadID, (int)(sizeof(LightArrayType)*lightCounter)); + + dispatchParams.value0 = lightCounter; + + device->UpdateBuffer(constantBuffers[CBTYPE_DISPATCHPARAMS], &dispatchParams, threadID); + device->BindConstantBufferCS(constantBuffers[CBTYPE_DISPATCHPARAMS], CB_GETBINDSLOT(DispatchParamsCB), threadID); + } + static GPUBuffer* frustumBuffer = nullptr; if (frustumBuffer == nullptr) @@ -3378,42 +3410,12 @@ Texture2D* wiRenderer::ComputeTiledLightCulling(GRAPHICSTHREAD threadID) } if (uav != nullptr) { - // Fill Light Array with lights in the frustum - CulledList culledObjects; - if (spTree_lights) - wiSPTree::getVisible(spTree_lights->root, getCamera()->frustum, culledObjects); GetDevice()->EventBegin(L"Light Culling", threadID); - - static LightArrayType lightArray[1024]; - memset(lightArray, 0, sizeof(lightArray)); - int counter = 0; - for (Cullable* c : culledObjects) - { - Light* l = (Light*)c; - - //lightArray[counter].pos = l->translation; - XMStoreFloat3(&lightArray[counter].pos, XMVector3TransformCoord(XMLoadFloat3(&l->translation), cam->GetView())); - lightArray[counter].radius = l->enerDis.y; - lightArray[counter].col = l->color; - - counter++; - if (counter == 1024) - { - assert(0 && "Over 1024 lights are in the frustum!"); - break; - } - } - device->UpdateBuffer(resourceBuffers[RBTYPE_LIGHTARRAY], lightArray, threadID, (int)(sizeof(LightArrayType)*counter)); device->BindResourceCS(resourceBuffers[RBTYPE_LIGHTARRAY], STRUCTUREDBUFFER_GETBINDSLOT(LightArrayType), threadID); device->BindResourceCS(frustumBuffer, SBSLOT_TILEFRUSTUMS, threadID); - - MiscCB cb; - cb.mColor.x = (float)counter; - device->UpdateBuffer(constantBuffers[CBTYPE_MISC], &cb, threadID); - device->BindConstantBufferCS(constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), threadID); Texture2DDesc uav_desc = uav->GetDesc(); device->BindCS(computeShaders[CSTYPE_TILEDLIGHTCULLING], threadID); diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index f739e0b40..0c5fc1186 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -257,8 +257,10 @@ public: }; GFX_STRUCT DispatchParamsCB { - UINT numThreadGroups[3]; UINT pad0; - UINT numThreads[3]; UINT pad1; + UINT numThreadGroups[3]; + UINT value0; + UINT numThreads[3]; + UINT value1; CB_SETBINDSLOT(CBSLOT_RENDERER_DISPATCHPARAMS)