void updateMatrices(const float *cameraView)
	{
		float bias = getBias();
		if(shadowMap)
			properties.targetPos = shadowMap->pos;

		properties.resolutionX = 2 * SHADOW_WIDTH;
		properties.resolutionY = 2 * SHADOW_HEIGHT;
		properties.updateMatrices(cameraView, bias);

		camera.SetPosition(properties.position);
		camera.SetTarget(properties.position + properties.direction);
		camera.SetFieldOfView(D3DXToRadian(properties.fov));
		camera.SetVisibilityRange(properties.range);
	}
Exemple #2
0
void Storm3D_SpotlightShared::updateMatricesOffCenter(const D3DXMATRIX &cameraView, const VC2 &min, const VC2 &max, float height, Storm3D_Camera &camera)
{
	// Position of the light in global coordinates
	// Y-axis is height
	D3DXVECTOR3 lightPosition(position.x, position.y, position.z);
	// Up vector (z-axis)
	D3DXVECTOR3 up(0.f, 0.f, 1.f);
	// Look direction
	D3DXVECTOR3 lookAt = lightPosition;
	lookAt.y -= 1.f;

	{
		// max and min define the extents of light area in local coordinates
		// Z-axis is height
		float zmin = 0.2f;
		//float zmax = std::max(range, height) * 1.4f;
		// height is light height from light properties
		float zmax = height;
		float factor = 1.5f * zmin / height;
		float xmin = min.x * factor;
		float xmax = max.x * factor;
		float ymin = min.y * factor;
		float ymax = max.y * factor;
		D3DXMatrixPerspectiveOffCenterLH(&lightProjection, xmin, xmax, ymin, ymax, zmin, zmax);

		// Calculate the extents of light area in global coordinates
		VC2 worldMin = min;
		worldMin.x += position.x;
		worldMin.y += position.z;
		VC2 worldMax = max;
		worldMax.x += position.x;
		worldMax.y += position.z;

		// Generate approximate camera for culling.

		// Calculate range of the camera.
		// Y-axis is height
		float planeY = position.y - height;
		// Calculate distances from light position to light plane edges
		VC3 p1 = VC3( worldMin.x, planeY, worldMin.y ) - position;
		VC3 p2 = VC3( worldMax.x, planeY, worldMin.y ) - position;
		VC3 p3 = VC3( worldMax.x, planeY, worldMax.y ) - position;
		VC3 p4 = VC3( worldMin.x, planeY, worldMax.y ) - position;
		float d1 = p1.GetLength();
		float d2 = p2.GetLength();
		float d3 = p3.GetLength();
		float d4 = p4.GetLength();
		float maxRange = 0.0f;
		maxRange = MAX( maxRange, d1 );
		maxRange = MAX( maxRange, d2 );
		maxRange = MAX( maxRange, d3 );
		maxRange = MAX( maxRange, d4 );
		//maxRange = sqrtf(maxRange);

		// Calculate FOV of the camera.
		VC3 planeCenter = VC3( (worldMin.x + worldMax.x) * 0.5f, planeY, (worldMin.y + worldMax.y) * 0.5f );
		VC3 camVec = planeCenter - position;
		camVec.Normalize();
		float minDot = 10000.0f;
		float t1 = camVec.GetDotWith( p1 ) / d1;
		float t2 = camVec.GetDotWith( p2 ) / d2;
		float t3 = camVec.GetDotWith( p3 ) / d3;
		float t4 = camVec.GetDotWith( p4 ) / d4;
		minDot = MIN( minDot, t1 );
		minDot = MIN( minDot, t2 );
		minDot = MIN( minDot, t3 );
		minDot = MIN( minDot, t4 );
		float maxAngle = acosf( minDot );

		// Place camera to light position
		camera.SetPosition(position);
		camera.SetUpVec(VC3(0.f, 0.f, 1.f));
		// Point camera at light plane center
		camera.SetTarget(planeCenter);
		camera.SetFieldOfView( maxAngle );
		camera.SetVisibilityRange( maxRange );
	}
	
	D3DXMATRIX cameraMatrix(cameraView);
	float det = D3DXMatrixDeterminant(&cameraMatrix);
	D3DXMatrixInverse(&cameraMatrix, &det, &cameraMatrix);

	unsigned int tweakRange = 1;
	float bias = 0.f;
	float currentBias = 0.f;
	for(int i = 0; i < 2; ++i)
	{	
		D3DXMatrixLookAtLH(&lightView[i], &lightPosition, &lookAt, &up);
		if(i == 1)
			currentBias = 0;

		// Tweak matrix
		float soffsetX = 0.5f;
		float soffsetY = 0.5f;
		float scale = 0.5f;

		D3DXMATRIX shadowTweak( scale,    0.0f,     0.0f,				0.0f,
								0.0f,     -scale,   0.0f,				0.0f,
								0.0f,      0.0f,     float(tweakRange),	0.0f,
								soffsetX,  soffsetY, currentBias,		1.0f );

		D3DXMatrixMultiply(&shadowProjection[i], &lightProjection, &shadowTweak);
		D3DXMatrixMultiply(&shadowProjection[i], &lightView[i], &shadowProjection[i]);
		D3DXMatrixMultiply(&lightViewProjection[i], &lightView[i], &lightProjection);

		shaderProjection[i] = shadowProjection[i];
		D3DXMatrixMultiply(&shadowProjection[i], &cameraMatrix, &shadowProjection[i]);
	}

	{
		float xf = (1.f / resolutionX * .5f);
		float yf = (1.f / resolutionY * .5f);
		float sX = soffsetX + (2 * targetPos.x * soffsetX) - xf;
		float sY = soffsetY + (2 * targetPos.y * soffsetY) - yf;

		D3DXMATRIX shadowTweak( scaleX,    0.0f,	0.0f,				0.0f,
								0.0f,    -scaleY,	0.0f,				0.0f,
								0.0f,     0.0f,     float(tweakRange),	0.0f,
								sX,       sY,		bias,				1.0f );

		D3DXMatrixMultiply(&targetProjection, &lightProjection, &shadowTweak);
		D3DXMatrixMultiply(&targetProjection, &lightView[0], &targetProjection);
	}
}