예제 #1
0
/*
========================
R_MirrorViewBySurface
========================
*/
static viewDef_t *R_MirrorViewBySurface( drawSurf_t *drawSurf ) {
	viewDef_t		*parms;
	orientation_t	surface, camera;
	idPlane			originalPlane, plane;

	// copy the viewport size from the original
	parms = (viewDef_t *)R_FrameAlloc( sizeof( *parms ) );
	*parms = *tr.viewDef;
	parms->renderView.viewID = 0;	// clear to allow player bodies to show up, and suppress view weapons

	parms->isSubview = true;
	parms->isMirror = true;

	// create plane axis for the portal we are seeing
	R_PlaneForSurface( drawSurf->geo, originalPlane );
	R_LocalPlaneToGlobal( drawSurf->space->modelMatrix, originalPlane, plane );

	surface.origin = plane.Normal() * -plane[3];
	surface.axis[0] = plane.Normal();
	surface.axis[0].NormalVectors( surface.axis[1], surface.axis[2] );
	surface.axis[2] = -surface.axis[2];

	camera.origin = surface.origin;
	camera.axis[0] = -surface.axis[0];
	camera.axis[1] = surface.axis[1];
	camera.axis[2] = surface.axis[2];

	// set the mirrored origin and axis
	R_MirrorPoint( tr.viewDef->renderView.vieworg, &surface, &camera, parms->renderView.vieworg );

	R_MirrorVector( tr.viewDef->renderView.viewaxis[0], &surface, &camera, parms->renderView.viewaxis[0] );
	R_MirrorVector( tr.viewDef->renderView.viewaxis[1], &surface, &camera, parms->renderView.viewaxis[1] );
	R_MirrorVector( tr.viewDef->renderView.viewaxis[2], &surface, &camera, parms->renderView.viewaxis[2] );

	// make the view origin 16 units away from the center of the surface
	idVec3	viewOrigin = ( drawSurf->geo->bounds[0] + drawSurf->geo->bounds[1] ) * 0.5;
	viewOrigin += ( originalPlane.Normal() * 16 );

	R_LocalPointToGlobal( drawSurf->space->modelMatrix, viewOrigin, parms->initialViewAreaOrigin );

	// set the mirror clip plane
	parms->numClipPlanes = 1;
	parms->clipPlanes[0] = -camera.axis[0];

	parms->clipPlanes[0][3] = -( camera.origin * parms->clipPlanes[0].Normal() );
	
	return parms;
}
예제 #2
0
/*
=================
R_DeriveLightData

Fills everything in based on light->parms
=================
*/
void R_DeriveLightData( idRenderLightLocal* light )
{

	// decide which light shader we are going to use
	if( light->parms.shader != NULL )
	{
		light->lightShader = light->parms.shader;
	}
	else if( light->lightShader == NULL )
	{
		if( light->parms.pointLight )
		{
			light->lightShader = tr.defaultPointLight;
		}
		else
		{
			light->lightShader = tr.defaultProjectedLight;
		}
	}
	
	// get the falloff image
	light->falloffImage = light->lightShader->LightFalloffImage();
	
	if( light->falloffImage == NULL )
	{
		// use the falloff from the default shader of the correct type
		const idMaterial* defaultShader;
		
		if( light->parms.pointLight )
		{
			defaultShader = tr.defaultPointLight;
			
			// Touch the default shader. to make sure it's decl has been parsed ( it might have been purged ).
			declManager->Touch( static_cast< const idDecl*>( defaultShader ) );
			
			light->falloffImage = defaultShader->LightFalloffImage();
			
		}
		else
		{
			// projected lights by default don't diminish with distance
			defaultShader = tr.defaultProjectedLight;
			
			// Touch the light shader. to make sure it's decl has been parsed ( it might have been purged ).
			declManager->Touch( static_cast< const idDecl*>( defaultShader ) );
			
			light->falloffImage = defaultShader->LightFalloffImage();
		}
	}
	
	// ------------------------------------
	// compute the light projection matrix
	// ------------------------------------
	
	idRenderMatrix localProject;
	float zScale = 1.0f;
	if( light->parms.parallel )
	{
		zScale = R_ComputeParallelLightProjectionMatrix( light, localProject );
	}
	else if( light->parms.pointLight )
	{
		zScale = R_ComputePointLightProjectionMatrix( light, localProject );
	}
	else
	{
		zScale = R_ComputeSpotLightProjectionMatrix( light, localProject );
	}
	
	// set the old style light projection where Z and W are flipped and
	// for projected lights lightProject[3] is divided by ( zNear + zFar )
	light->lightProject[0][0] = localProject[0][0];
	light->lightProject[0][1] = localProject[0][1];
	light->lightProject[0][2] = localProject[0][2];
	light->lightProject[0][3] = localProject[0][3];
	
	light->lightProject[1][0] = localProject[1][0];
	light->lightProject[1][1] = localProject[1][1];
	light->lightProject[1][2] = localProject[1][2];
	light->lightProject[1][3] = localProject[1][3];
	
	light->lightProject[2][0] = localProject[3][0];
	light->lightProject[2][1] = localProject[3][1];
	light->lightProject[2][2] = localProject[3][2];
	light->lightProject[2][3] = localProject[3][3];
	
	light->lightProject[3][0] = localProject[2][0] * zScale;
	light->lightProject[3][1] = localProject[2][1] * zScale;
	light->lightProject[3][2] = localProject[2][2] * zScale;
	light->lightProject[3][3] = localProject[2][3] * zScale;
	
	// transform the lightProject
	float lightTransform[16];
	R_AxisToModelMatrix( light->parms.axis, light->parms.origin, lightTransform );
	for( int i = 0; i < 4; i++ )
	{
		idPlane temp = light->lightProject[i];
		R_LocalPlaneToGlobal( lightTransform, temp, light->lightProject[i] );
	}
	
	// adjust global light origin for off center projections and parallel projections
	// we are just faking parallel by making it a very far off center for now
	if( light->parms.parallel )
	{
		idVec3 dir = light->parms.lightCenter;
		if( dir.Normalize() == 0.0f )
		{
			// make point straight up if not specified
			dir[2] = 1.0f;
		}
		light->globalLightOrigin = light->parms.origin + dir * 100000.0f;
	}
	else
	{
		light->globalLightOrigin = light->parms.origin + light->parms.axis * light->parms.lightCenter;
	}
	
	// Rotate and translate the light projection by the light matrix.
	// 99% of lights remain axis aligned in world space.
	idRenderMatrix lightMatrix;
	idRenderMatrix::CreateFromOriginAxis( light->parms.origin, light->parms.axis, lightMatrix );
	
	idRenderMatrix inverseLightMatrix;
	if( !idRenderMatrix::Inverse( lightMatrix, inverseLightMatrix ) )
	{
		idLib::Warning( "lightMatrix invert failed" );
	}
	
	// 'baseLightProject' goes from global space -> light local space -> light projective space
	idRenderMatrix::Multiply( localProject, inverseLightMatrix, light->baseLightProject );
	
	// Invert the light projection so we can deform zero-to-one cubes into
	// the light model and calculate global bounds.
	if( !idRenderMatrix::Inverse( light->baseLightProject, light->inverseBaseLightProject ) )
	{
		idLib::Warning( "baseLightProject invert failed" );
	}
	
	// calculate the global light bounds by inverse projecting the zero to one cube with the 'inverseBaseLightProject'
	idRenderMatrix::ProjectedBounds( light->globalLightBounds, light->inverseBaseLightProject, bounds_zeroOneCube, false );
}
/*
========================
R_MirrorViewBySurface
========================
*/
static viewDef_t* R_MirrorViewBySurface( const drawSurf_t* drawSurf )
{
	// copy the viewport size from the original
	viewDef_t* parms = ( viewDef_t* )R_FrameAlloc( sizeof( *parms ) );
	*parms = *tr.viewDef;
	parms->renderView.viewID = 0;	// clear to allow player bodies to show up, and suppress view weapons
	
	parms->isSubview = true;
	parms->isMirror = true;
	parms->isObliqueProjection = false;
	
	// create plane axis for the portal we are seeing
	idPlane originalPlane, plane;
	R_PlaneForSurface( drawSurf->frontEndGeo, originalPlane );
	R_LocalPlaneToGlobal( drawSurf->space->modelMatrix, originalPlane, plane );
	
	orientation_t surface;
	surface.origin = plane.Normal() * -plane[3];
	surface.axis[0] = plane.Normal();
	surface.axis[0].NormalVectors( surface.axis[1], surface.axis[2] );
	surface.axis[2] = -surface.axis[2];
	
	orientation_t camera;
	camera.origin = surface.origin;
	camera.axis[0] = -surface.axis[0];
	camera.axis[1] = surface.axis[1];
	camera.axis[2] = surface.axis[2];
	
	// set the mirrored origin and axis
	R_MirrorPoint( tr.viewDef->renderView.vieworg, &surface, &camera, parms->renderView.vieworg );
	
	R_MirrorVector( tr.viewDef->renderView.viewaxis[0], &surface, &camera, parms->renderView.viewaxis[0] );
	R_MirrorVector( tr.viewDef->renderView.viewaxis[1], &surface, &camera, parms->renderView.viewaxis[1] );
	R_MirrorVector( tr.viewDef->renderView.viewaxis[2], &surface, &camera, parms->renderView.viewaxis[2] );
	
	// make the view origin 16 units away from the center of the surface
	const idVec3 center = (drawSurf->frontEndGeo->bounds[0] + drawSurf->frontEndGeo->bounds[1]) * 0.5f;
	const idVec3 viewOrigin = center + (originalPlane.Normal() * 16.0f);

	R_LocalPointToGlobal(drawSurf->space->modelMatrix, viewOrigin, parms->initialViewAreaOrigin);

	// set the mirror clip plane
	parms->numClipPlanes = 1;
	parms->clipPlanes[0] = -camera.axis[0];
	
	parms->clipPlanes[0][3] = -( camera.origin * parms->clipPlanes[0].Normal() );
	
	if (r_waterReflectFix.GetBool() && !parms->is2Dgui && drawSurf->material->GetSurfaceType() == SURFTYPE_MIRROR)
	{
		parms->isObliqueProjection = true;
		float dist = parms->clipPlanes[0].Dist();
		float viewdist = parms->renderView.vieworg * parms->clipPlanes[0].Normal();
		float fDist = -dist + viewdist;
		static const float fudge = 2.f;	//fudge avoids depth precision artifacts when performing oblique projection
		if (fDist > fudge || fDist < -fudge)
		{
			if (fDist < 0.f)
				fDist += fudge;
			else
				fDist -= fudge;
		}

		parms->clipPlanes[0][3] = fDist;		

		R_SetupViewMatrix(parms);
		R_SetupProjectionMatrix(parms);
		R_ObliqueProjection(parms);
	}

	return parms;
}