示例#1
0
	void DiFocusedShadowPolicy::calculateB(const DiSceneManager& sm, const DiCamera& cam,
		const DiLight& light, const DiAABB& sceneBB, const DiAABB& receiverBB, 
		PointListBody *out_bodyB) const
	{
		DI_ASSERT_MESSAGE(out_bodyB != NULL, "bodyB vertex list is NULL");

		/// perform convex intersection of the form B = ((V \cap S) + l) \cap S \cap L

		// get V
		mBodyB.define(cam);

		if (light.GetType() != LIGHT_DIRECTIONAL)
		{
			if (mUseAggressiveRegion)
				mBodyB.clip(sceneBB);

			// form a convex hull of bodyB with the light position
			mBodyB.extend(light.GetDerivedPosition());

			// clip bodyB with sceneBB
			mBodyB.clip(sceneBB);

			// clip with the light frustum
			// set up light camera to clip with the resulting frustum planes
			if (!mLightFrustumCameraCalculated)
			{
				calculateShadowMappingMatrix(sm, cam, light, NULL, NULL, mLightFrustumCamera);
				mLightFrustumCameraCalculated = true;
			}
			mBodyB.clip(*mLightFrustumCamera);

			// extract bodyB vertices
			out_bodyB->build(mBodyB);

		}
		else
		{
			// For directional lights, all we care about is projecting the receivers
			// backwards towards the light, clipped by the camera region
			mBodyB.clip(receiverBB);

			// Also clip based on shadow far distance if appropriate
			float farDist = sm.GetShadowFarDistance();
			if (farDist)
			{
				DiVec3 pointOnPlane = cam.GetDerivedPosition() +
					(cam.GetDerivedDirection() * farDist);
				DiPlane p(cam.GetDerivedDirection(), pointOnPlane);
				mBodyB.clip(p);
			}

			// Extrude the intersection bodyB into the inverted light direction and store 
			// the info in the point list.
			// Maximum extrusion extent is to the shadow far distance
			out_bodyB->buildAndIncludeDirection(mBodyB, 
				farDist ? farDist : cam.GetNearClipDistance() * 3000,
				-light.GetDerivedDirection());
		}
	}
示例#2
0
	void DiFocusedShadowPolicy::calculateShadowMappingMatrix(const DiSceneManager& sm,
		const DiCamera& cam, const DiLight& light, DiMat4 *out_view, DiMat4 *out_proj, 
		DiCamera *out_cam) const
	{
        DiVec3 lightPos = light.GetDerivedPosition();
        DiVec3 lightDir = light.GetDerivedDirection();
        
		// get the shadow frustum's far distance
		float shadowDist = sm.GetShadowFarDistance();
		if (!shadowDist)
		{
			// need a shadow distance, make one up
			shadowDist = cam.GetNearClipDistance() * 3000;
		}
		float shadowOffset = shadowDist * sm.GetShadowDirLightTextureOffset();

		if (light.GetType() == LIGHT_DIRECTIONAL)
		{
			// generate view matrix if requested
			if (out_view != NULL)
			{
				DiVec3 pos;
#if 0
				if (sm.getCameraRelativeRendering())
				{
					pos = DiVec3::ZERO;
				}
				else
#endif
				{
					pos = cam.GetDerivedPosition();
				}
				*out_view = buildViewMatrix(pos, 
					lightDir,
					cam.GetDerivedUp());
			}

			// generate projection matrix if requested
			if (out_proj != NULL)
			{
				*out_proj = DiMat4::getScale(1, 1, -1);
				//*out_proj = DiMat4::IDENTITY;
			}

			// set up camera if requested
			if (out_cam != NULL)
			{
				out_cam->SetProjectionType(PT_ORTHOGRAPHIC);
				out_cam->SetDirection(lightDir);
				out_cam->SetPosition(cam.GetDerivedPosition());
				out_cam->SetFOVy(DiDegree(90));
				out_cam->SetNearClipDistance(shadowOffset);
			}
		}
        else if (light.GetType() == LIGHT_SPOT)
        {
            const DiSpotLight* spot = static_cast<const DiSpotLight*>(&light);
            // generate view matrix if requested
			if (out_view != NULL)
			{
				*out_view = buildViewMatrix(light.GetDerivedPosition(),
                                            light.GetDerivedDirection(),
                                            cam.GetDerivedUp());
			}
            
			// generate projection matrix if requested
			if (out_proj != NULL)
			{
				// set FOV slightly larger than spotlight range
				mTempFrustum->SetFOVy(DiMath::Clamp<DiRadian>(spot->GetOuterAngle() * 1.2, DiRadian(0), DiRadian(DiMath::PI/2.0f)));
                
				mTempFrustum->SetNearClipDistance(light.DeriveShadowNearClipDistance(&cam));
				mTempFrustum->SetFarClipDistance(light.DeriveShadowFarClipDistance(&cam));
                
				*out_proj = mTempFrustum->GetProjectionMatrix();
			}
            
			// set up camera if requested
			if (out_cam != NULL)
			{
				out_cam->SetProjectionType(PT_PERSPECTIVE);
				out_cam->SetDirection(light.GetDerivedDirection());
				out_cam->SetPosition(light.GetDerivedPosition());
				out_cam->SetFOVy(DiMath::Clamp<DiRadian>(spot->GetOuterAngle() * 1.2, DiRadian(0), DiRadian(DiMath::PI/2.0f)));
				out_cam->SetNearClipDistance(light.DeriveShadowNearClipDistance(&cam));
				out_cam->SetFarClipDistance(light.DeriveShadowFarClipDistance(&cam));
			}
        }
#if 0
		else if (light.GetType() == LIGHT_POINT)
		{
			// target analogue to the default shadow textures
			// Calculate look at position
			// We want to look at a spot shadowOffset away from near plane
			// 0.5 is a little too close for angles
			DiVec3 target = cam.GetDerivedPosition() +
				(cam.GetDerivedDirection() * shadowOffset);
			lightDir = target - lightPos;
			lightDir.normalise();

			// generate view matrix if requested
			if (out_view != NULL)
			{
				*out_view = buildViewMatrix(lightPos,
					lightDir, 
					cam.GetDerivedUp());
			}

			// generate projection matrix if requested
			if (out_proj)
			{
				// set FOV to 120 degrees
				mTempFrustum->SetFOVy(DiDegree(120));

				mTempFrustum->SetNearClipDistance(light._deriveShadowNearClipDistance(&cam));
				mTempFrustum->SetFarClipDistance(light._deriveShadowFarClipDistance(&cam));

				*out_proj = mTempFrustum->GetProjectionMatrix();
			}

			// set up camera if requested
			if (out_cam)
			{
				out_cam->SetProjectionType(PT_PERSPECTIVE);
				out_cam->SetDirection(lightDir);
				out_cam->SetPosition(lightPos);
				out_cam->SetFOVy(DiDegree(120));
				out_cam->SetNearClipDistance(light._deriveShadowNearClipDistance(&cam));
				out_cam->SetFarClipDistance(light._deriveShadowFarClipDistance(&cam));
			}
		}
#endif
    }