Example #1
0
void LightList::QueueClusteredLightCulling(Renderer& rRenderer, const Camera& rCamera)
{
	RdrResourceCommandList* pResCommandList = rRenderer.GetActionCommandList();
	Vec2 viewportSize = rRenderer.GetViewportSize();

	// Determine the cluster tile size given two rules:
	//	1) The larger viewport dimension will have 16 tiles.
	//	2) Tile size must be a multiple of 8.
	const uint kMaxTilesPerDimension = 16;
	float maxDim = max(viewportSize.x, viewportSize.y);
	m_clusteredLightData.clusterTileSize = ((uint)ceil(maxDim / kMaxTilesPerDimension) + 7) & ~7;

	int clusterCountX = (int)ceil(viewportSize.x / m_clusteredLightData.clusterTileSize);
	int clusterCountY = (int)ceil(viewportSize.y / m_clusteredLightData.clusterTileSize);

	if (m_clusteredLightData.clusterCountX < clusterCountX || m_clusteredLightData.clusterCountY < clusterCountY)
	{
		// Resize buffers
		m_clusteredLightData.clusterCountX = max(16, clusterCountX);
		m_clusteredLightData.clusterCountY = max(16, clusterCountY);

		if (m_clusteredLightData.hLightIndices)
			pResCommandList->ReleaseResource(m_clusteredLightData.hLightIndices);
		m_clusteredLightData.hLightIndices = pResCommandList->CreateDataBuffer(nullptr, m_clusteredLightData.clusterCountX * m_clusteredLightData.clusterCountY * CLUSTEREDLIGHTING_DEPTH_SLICES * CLUSTEREDLIGHTING_BLOCK_SIZE, RdrResourceFormat::R16_UINT, RdrResourceUsage::Default);
	}

	RdrComputeOp* pCullOp = RdrFrameMem::AllocComputeOp();
	pCullOp->shader = RdrComputeShader::ClusteredLightCull;
	pCullOp->threads[0] = clusterCountX;
	pCullOp->threads[1] = clusterCountY;
	pCullOp->threads[2] = CLUSTEREDLIGHTING_DEPTH_SLICES;
	pCullOp->ahWritableResources.assign(0, m_clusteredLightData.hLightIndices);
	pCullOp->ahResources.assign(0, m_hSpotLightListRes);
	pCullOp->ahResources.assign(1, m_hPointLightListRes);

	uint constantsSize = sizeof(ClusteredLightCullingParams);
	ClusteredLightCullingParams* pParams = (ClusteredLightCullingParams*)RdrFrameMem::AllocAligned(constantsSize, 16);

	Matrix44 mtxProj;
	rCamera.GetMatrices(pParams->mtxView, mtxProj);

	pParams->mtxView = Matrix44Transpose(pParams->mtxView);
	pParams->proj_11 = mtxProj._11;
	pParams->proj_22 = mtxProj._22;
	pParams->screenSize = viewportSize;
	pParams->fovY = rCamera.GetFieldOfViewY();
	pParams->aspectRatio = rCamera.GetAspectRatio();
	pParams->clusterCountX = clusterCountX;
	pParams->clusterCountY = clusterCountY;
	pParams->clusterCountZ = CLUSTEREDLIGHTING_DEPTH_SLICES;
	pParams->clusterTileSize = m_clusteredLightData.clusterTileSize;
	pParams->spotLightCount = m_spotLights.size();
	pParams->pointLightCount = m_pointLights.size();

	m_clusteredLightData.hCullConstants = pResCommandList->CreateUpdateConstantBuffer(m_clusteredLightData.hCullConstants,
		pParams, constantsSize, RdrCpuAccessFlags::Write, RdrResourceUsage::Dynamic);
	pCullOp->ahConstantBuffers.assign(0, m_clusteredLightData.hCullConstants);

	rRenderer.AddComputeOpToPass(pCullOp, RdrPass::LightCulling);
}
Example #2
0
static void updateJointMatricesNoJob( tAnimHierarchy* pAnimHierarchy,
                                      tMatrix44* aAnimMatrices )
{
    // update joint matrices in hierarchy
    // use worker threads
    int iJoint = 0;
    int iLevel = 0;
    for( ;; )
    {
        if( iJoint >= pAnimHierarchy->miNumJoints )
        {
            break;
        }
        
        tJoint* pJoint = &pAnimHierarchy->maJoints[iJoint];
        if( pJoint->miLevel > iLevel )
        {
            // update next level
            ++iLevel;
        }
        
        int iJointIndex = 0;
        int iNumHierarchyJoints = pAnimHierarchy->miNumJoints;
        for( iJointIndex = 0; iJointIndex < iNumHierarchyJoints; iJointIndex++ )
        {
            if( !strcmp( pAnimHierarchy->maJoints[iJointIndex].mszName, pJoint->mszName ) )
            {
                break;
            }
        }
        
        WTFASSERT2( iJointIndex < iNumHierarchyJoints, "can't find joint in hierarchy" );
        
        // transform
        tMatrix44 const* pParentMatrix = &gIdentityMat;
        if( pJoint->mpParent )
        {
            pParentMatrix = pJoint->mpParent->mpTotalMatrix;
        }
        
        // M(total) = M(parent) * M(local) * M(anim)
        tMatrix44 parentLocalMatrix;
        tMatrix44* pTotalMatrix = pJoint->mpTotalMatrix;
        tMatrix44* pSkinMatrix = pJoint->mpSkinMatrix;
        
        Matrix44Multiply( &parentLocalMatrix, pParentMatrix, pJoint->mpLocalMatrix );
        //Matrix44Multiply( pTotalMatrix, &parentLocalMatrix, pJoint->mpAnimMatrix );
        Matrix44Multiply( pTotalMatrix, &parentLocalMatrix, &aAnimMatrices[iJointIndex]);
        
        // M(skin) = M(total) * M(invPose)
        Matrix44Multiply( pJoint->mpSkinMatrix, pTotalMatrix, pJoint->mpInvPoseMatrix );
        
        // M(invTransposeSkin)
        tMatrix44 invSkinMatrix;
        Matrix44Inverse( &invSkinMatrix, pSkinMatrix );
        Matrix44Transpose( pJoint->mpInvTransSkinningMatrix, &invSkinMatrix );
        
        ++iJoint;
    }
}
Example #3
0
void LightList::QueueTiledLightCulling(Renderer& rRenderer, const Camera& rCamera)
{
	RdrResourceCommandList* pResCommandList = rRenderer.GetActionCommandList();
	Vec2 viewportSize = rRenderer.GetViewportSize();

	uint tileCountX = RdrComputeOp::getThreadGroupCount((uint)viewportSize.x, TILEDLIGHTING_TILE_SIZE);
	uint tileCountY = RdrComputeOp::getThreadGroupCount((uint)viewportSize.y, TILEDLIGHTING_TILE_SIZE);
	bool tileCountChanged = false;

	if (m_tiledLightData.tileCountX != tileCountX || m_tiledLightData.tileCountY != tileCountY)
	{
		m_tiledLightData.tileCountX = tileCountX;
		m_tiledLightData.tileCountY = tileCountY;
		tileCountChanged = true;
	}

	//////////////////////////////////////
	// Depth min max
	if (tileCountChanged)
	{
		if (m_tiledLightData.hDepthMinMaxTex)
			pResCommandList->ReleaseResource(m_tiledLightData.hDepthMinMaxTex);
		m_tiledLightData.hDepthMinMaxTex = pResCommandList->CreateTexture2D(tileCountX, tileCountY, RdrResourceFormat::R16G16_FLOAT, RdrResourceUsage::Default, nullptr);
	}

	// Update constants
	Matrix44 viewMtx;
	Matrix44 invProjMtx;
	rCamera.GetMatrices(viewMtx, invProjMtx);
	invProjMtx = Matrix44Inverse(invProjMtx);
	invProjMtx = Matrix44Transpose(invProjMtx);

	uint constantsSize = sizeof(Vec4) * 4;
	Vec4* pConstants = (Vec4*)RdrFrameMem::AllocAligned(constantsSize, 16);
	for (int i = 0; i < 4; ++i)
	{
		pConstants[i].x = invProjMtx.m[i][0];
		pConstants[i].y = invProjMtx.m[i][1];
		pConstants[i].z = invProjMtx.m[i][2];
		pConstants[i].w = invProjMtx.m[i][3];
	}

	m_tiledLightData.hDepthMinMaxConstants = pResCommandList->CreateUpdateConstantBuffer(m_tiledLightData.hDepthMinMaxConstants,
		pConstants, constantsSize, RdrCpuAccessFlags::Write, RdrResourceUsage::Dynamic);

	// Fill draw op
	RdrComputeOp* pDepthOp = RdrFrameMem::AllocComputeOp();
	pDepthOp->shader = RdrComputeShader::TiledDepthMinMax;
	pDepthOp->threads[0] = tileCountX;
	pDepthOp->threads[1] = tileCountY;
	pDepthOp->threads[2] = 1;
	pDepthOp->ahWritableResources.assign(0, m_tiledLightData.hDepthMinMaxTex);
	pDepthOp->ahResources.assign(0, rRenderer.GetPrimaryDepthBuffer());
	pDepthOp->ahConstantBuffers.assign(0, m_tiledLightData.hDepthMinMaxConstants);

	rRenderer.AddComputeOpToPass(pDepthOp, RdrPass::LightCulling);

	//////////////////////////////////////
	// Light culling
	if (tileCountChanged)
	{
		if (m_tiledLightData.hLightIndices)
			pResCommandList->ReleaseResource(m_tiledLightData.hLightIndices);
		m_tiledLightData.hLightIndices = pResCommandList->CreateDataBuffer(nullptr, tileCountX * tileCountY * TILEDLIGHTING_BLOCK_SIZE, RdrResourceFormat::R16_UINT, RdrResourceUsage::Default);
	}

	// Update constants
	constantsSize = sizeof(TiledLightCullingParams);
	TiledLightCullingParams* pParams = (TiledLightCullingParams*)RdrFrameMem::AllocAligned(constantsSize, 16);

	Matrix44 mtxProj;
	rCamera.GetMatrices(pParams->mtxView, mtxProj);

	pParams->mtxView = Matrix44Transpose(pParams->mtxView);
	pParams->proj_11 = mtxProj._11;
	pParams->proj_22 = mtxProj._22;
	pParams->cameraNearDist = rCamera.GetNearDist();
	pParams->cameraFarDist = rCamera.GetFarDist();
	pParams->screenSize = viewportSize;
	pParams->fovY = rCamera.GetFieldOfViewY();
	pParams->aspectRatio = rCamera.GetAspectRatio();
	pParams->spotLightCount = m_spotLights.size();
	pParams->pointLightCount = m_pointLights.size();
	pParams->tileCountX = tileCountX;
	pParams->tileCountY = tileCountY;

	m_tiledLightData.hCullConstants = pResCommandList->CreateUpdateConstantBuffer(m_tiledLightData.hCullConstants,
		pParams, constantsSize, RdrCpuAccessFlags::Write, RdrResourceUsage::Dynamic);

	// Fill draw op
	RdrComputeOp* pCullOp = RdrFrameMem::AllocComputeOp();
	pCullOp->threads[0] = tileCountX;
	pCullOp->threads[1] = tileCountY;
	pCullOp->threads[2] = 1;
	pCullOp->ahWritableResources.assign(0, m_tiledLightData.hLightIndices);
	pCullOp->ahResources.assign(0, m_hSpotLightListRes);
	pCullOp->ahResources.assign(1, m_hPointLightListRes);
	pCullOp->ahResources.assign(2, m_tiledLightData.hDepthMinMaxTex);
	pCullOp->ahConstantBuffers.assign(0, m_tiledLightData.hCullConstants);

	rRenderer.AddComputeOpToPass(pCullOp, RdrPass::LightCulling);
}
Example #4
0
void LightList::QueueDraw(Renderer& rRenderer, const Sky& rSky, const Camera& rCamera, const float sceneDepthMin, const float sceneDepthMax,
	RdrLightingMethod lightingMethod, RdrLightResources* pOutResources)
{
	Camera lightCamera;
	int curShadowMapIndex = 0;
	int curShadowCubeMapIndex = 0;
	int shadowMapsThisFrame = 0;

	// Update shadow casting lights and the global light constants
	// todo: Choose shadow lights based on location and dynamic object movement
	GlobalLightData* pGlobalLights = (GlobalLightData*)RdrFrameMem::AllocAligned(sizeof(GlobalLightData), 16);

	// Temporarily add sky light to the light list.
	m_directionalLights.push(rSky.GetSunLight());

	for (uint i = 0, count = m_directionalLights.size(); i < count; ++i)
	{
		DirectionalLight& rDirLight = m_directionalLights[i];
		int remainingShadowMaps = MAX_SHADOW_MAPS - curShadowMapIndex - 1;
		const int kNumCascades = 4;
		if (remainingShadowMaps >= kNumCascades)
		{
			// Directional lights always change because they're based on camera position/rotation
			rDirLight.shadowMapIndex = curShadowMapIndex;

			Rect viewport(0.f, 0.f, (float)s_shadowMapSize, (float)s_shadowMapSize);
			float zMin = sceneDepthMin;
			float zMax = sceneDepthMax;
			float zDiff = (zMax - zMin);

			float nearDepth = zMin;
			float lamda = rSky.GetPssmLambda();

			for (int iPartition = 0; iPartition < kNumCascades; ++iPartition)
			{
				float zUni = zMin + (zDiff / kNumCascades) * (iPartition + 1);
				float zLog = zMin * powf(zMax / zMin, (iPartition + 1) / (float)kNumCascades);
				float farDepth = lamda * zLog + (1.f - lamda) * zUni;

				Vec3 center = rCamera.GetPosition() + rCamera.GetDirection() * ((farDepth + nearDepth) * 0.5f);
				Matrix44 lightViewMtx = getLightViewMatrix(center, rDirLight.direction);

				Quad nearQuad = rCamera.GetFrustumQuad(nearDepth);
				QuadTransform(nearQuad, lightViewMtx);

				Quad farQuad = rCamera.GetFrustumQuad(farDepth);
				QuadTransform(farQuad, lightViewMtx);

				Vec3 boundsMin(FLT_MAX, FLT_MAX, FLT_MAX);
				Vec3 boundsMax(-FLT_MAX, -FLT_MAX, -FLT_MAX);
				accumQuadMinMax(nearQuad, boundsMin, boundsMax);
				accumQuadMinMax(farQuad, boundsMin, boundsMax);

				float height = (boundsMax.y - boundsMin.y);
				float width = (boundsMax.x - boundsMin.x);
				lightCamera.SetAsOrtho(center, rDirLight.direction, std::max(width, height), -500.f, 500.f);

				rRenderer.QueueShadowMapPass(lightCamera, m_shadowMapDepthViews[curShadowMapIndex], viewport);

				Matrix44 mtxView;
				Matrix44 mtxProj;
				lightCamera.GetMatrices(mtxView, mtxProj);
				pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj = Matrix44Multiply(mtxView, mtxProj);
				pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj = Matrix44Transpose(pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj);
				pGlobalLights->shadowData[curShadowMapIndex].partitionEndZ = (iPartition == kNumCascades - 1) ? FLT_MAX : farDepth;

				++shadowMapsThisFrame;
				++curShadowMapIndex;
				nearDepth = farDepth;
			}
		}
		else
		{
			rDirLight.shadowMapIndex = -1;
		}
	}

	for (uint i = 0, count = m_spotLights.size(); i < count; ++i)
	{
		SpotLight& rSpotLight = m_spotLights[i];
		int remainingShadowMaps = MAX_SHADOW_MAPS - curShadowMapIndex - 1;
		if (remainingShadowMaps)
		{
			Matrix44 mtxView;
			Matrix44 mtxProj;

			float angle = rSpotLight.outerConeAngle + Maths::DegToRad(5.f);
			lightCamera.SetAsPerspective(rSpotLight.position, rSpotLight.direction, angle * 2.f, 1.f, 0.1f, 1000.f);
			lightCamera.GetMatrices(mtxView, mtxProj);

			pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj = Matrix44Multiply(mtxView, mtxProj);
			pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj = Matrix44Transpose(pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj);

			Rect viewport(0.f, 0.f, (float)s_shadowMapSize, (float)s_shadowMapSize);
			rRenderer.QueueShadowMapPass(lightCamera, m_shadowMapDepthViews[curShadowMapIndex], viewport);

			rSpotLight.shadowMapIndex = curShadowMapIndex;
			++shadowMapsThisFrame;
			++curShadowMapIndex;
		}
		else
		{
			rSpotLight.shadowMapIndex = -1;
		}
	}

	for (uint i = 0, count = m_pointLights.size(); i < count; ++i)
	{
		PointLight& rPointLight = m_pointLights[i];
		int remainingShadowCubeMaps = MAX_SHADOW_CUBEMAPS - curShadowCubeMapIndex - 1;
		if (remainingShadowCubeMaps)
		{
			rPointLight.shadowMapIndex = curShadowCubeMapIndex + MAX_SHADOW_MAPS;

			Rect viewport(0.f, 0.f, (float)s_shadowCubeMapSize, (float)s_shadowCubeMapSize);
#if USE_SINGLEPASS_SHADOW_CUBEMAP
			rRenderer.QueueShadowCubeMapPass(rPointLight, m_shadowCubeMapDepthViews[curShadowCubeMapIndex], viewport);
#else
			for (uint face = 0; face < 6; ++face)
			{
				lightCamera.SetAsCubemapFace(light.position, (CubemapFace)face, 0.1f, light.radius * 2.f);
				rRenderer.QueueShadowMapPass(lightCamera, m_shadowCubeMapDepthViews[curShadowCubeMapIndex * 6 + face], viewport);
			}
#endif
			++shadowMapsThisFrame;
			++curShadowCubeMapIndex;
		}
		else
		{
			rPointLight.shadowMapIndex = -1;
		}
	}

	//////////////////////////////////////////////////////////////////////////
	// Apply resource updates
	RdrResourceCommandList* pResCommandList = rRenderer.GetActionCommandList();

	// Update spot lights
	SpotLight* pSpotLights = (SpotLight*)RdrFrameMem::Alloc(sizeof(SpotLight) * m_spotLights.size());
	memcpy(pSpotLights, m_spotLights.getData(), sizeof(SpotLight) * m_spotLights.size());
	if (!m_hSpotLightListRes)
		m_hSpotLightListRes = pResCommandList->CreateStructuredBuffer(pSpotLights, m_spotLights.capacity(), sizeof(SpotLight), RdrResourceUsage::Dynamic);
	else
		pResCommandList->UpdateBuffer(m_hSpotLightListRes, pSpotLights, sizeof(SpotLight) * m_spotLights.size());

	// Update point lights
	PointLight* pPointLights = (PointLight*)RdrFrameMem::Alloc(sizeof(PointLight) * m_pointLights.size());
	memcpy(pPointLights, m_pointLights.getData(), sizeof(PointLight) * m_pointLights.size());
	if (!m_hPointLightListRes)
		m_hPointLightListRes = pResCommandList->CreateStructuredBuffer(pPointLights, m_pointLights.capacity(), sizeof(PointLight), RdrResourceUsage::Dynamic);
	else
		pResCommandList->UpdateBuffer(m_hPointLightListRes, pPointLights, sizeof(PointLight) * m_pointLights.size());

	// Update environment lights
	EnvironmentLight* pEnvironmentLights = (EnvironmentLight*)RdrFrameMem::Alloc(sizeof(EnvironmentLight) * m_environmentLights.size());
	memcpy(pEnvironmentLights, m_environmentLights.getData(), sizeof(EnvironmentLight) * m_environmentLights.size());
	if (!m_hEnvironmentLightListRes)
		m_hEnvironmentLightListRes = pResCommandList->CreateStructuredBuffer(pEnvironmentLights, m_environmentLights.capacity(), sizeof(EnvironmentLight), RdrResourceUsage::Dynamic);
	else
		pResCommandList->UpdateBuffer(m_hEnvironmentLightListRes, pEnvironmentLights, sizeof(EnvironmentLight) * m_environmentLights.size());

	// Light culling
	if (lightingMethod == RdrLightingMethod::Clustered)
	{
		QueueClusteredLightCulling(rRenderer, rCamera);
	}
	else
	{
		QueueTiledLightCulling(rRenderer, rCamera);
	}

	// Update global lights constant buffer last so the light culling data is up to date.
	pGlobalLights->numDirectionalLights = m_directionalLights.size();
	pGlobalLights->globalEnvironmentLight = m_globalEnvironmentLight;
	pGlobalLights->clusterTileSize = m_clusteredLightData.clusterTileSize;
	memcpy(pGlobalLights->directionalLights, m_directionalLights.getData(), sizeof(DirectionalLight) * pGlobalLights->numDirectionalLights);
	m_hGlobalLightsCb = pResCommandList->CreateUpdateConstantBuffer(m_hGlobalLightsCb,
		pGlobalLights, sizeof(GlobalLightData), RdrCpuAccessFlags::Write, RdrResourceUsage::Dynamic);

	// Remove sky light.
	m_directionalLights.pop();


	// Fill out resource params
	pOutResources->hGlobalLightsCb = m_hGlobalLightsCb;
	pOutResources->hSpotLightListRes = m_hSpotLightListRes;
	pOutResources->hPointLightListRes = m_hPointLightListRes;
	pOutResources->hEnvironmentLightListRes = m_hEnvironmentLightListRes;
	pOutResources->hShadowCubeMapTexArray = m_hShadowCubeMapTexArray;
	pOutResources->hShadowMapTexArray = m_hShadowMapTexArray;
	pOutResources->hEnvironmentMapTexArray = m_hEnvironmentMapTexArray;
	pOutResources->hLightIndicesRes = (lightingMethod == RdrLightingMethod::Clustered) ? 
		m_clusteredLightData.hLightIndices : m_tiledLightData.hLightIndices;
}