Esempio n. 1
0
idScreenRect R_CalcLightScissorRectangle( viewLight_t *vLight )
{
	idScreenRect		r;
	srfTriangles_t		*tri;
	idPlane				eye, clip;
	idVec3				ndc;
	
	if( vLight->lightDef->parms.pointLight )
	{
		idBounds			bounds;
		idRenderLightLocal	*lightDef = vLight->lightDef;
		tr.viewDef->viewFrustum.ProjectionBounds( idBox( lightDef->parms.origin, lightDef->parms.lightRadius, lightDef->parms.axis ), bounds );
		return R_ScreenRectFromViewFrustumBounds( bounds );
	}
	
	if( r_useClippedLightScissors.GetInteger() == 2 )
	{
		return R_ClippedLightScissorRectangle( vLight );
	}
	r.Clear();
	
	tri = vLight->lightDef->frustumTris;
	
	for( int i = 0; i < tri->numVerts; i++ )
	{
		R_TransformModelToClip( tri->verts[i].xyz, tr.viewDef->worldSpace.modelViewMatrix, tr.viewDef->projectionMatrix, eye, clip );
		
		// if it is near clipped, clip the winding polygons to the view frustum
		if( clip[3] <= 1 )
		{
			c_clippedLight++;
			
			if( r_useClippedLightScissors.GetInteger() )
			{
				return R_ClippedLightScissorRectangle( vLight );
			}
			else
			{
				r.x1 = r.y1 = 0;
				r.x2 = ( tr.viewDef->viewport.x2 - tr.viewDef->viewport.x1 ) - 1;
				r.y2 = ( tr.viewDef->viewport.y2 - tr.viewDef->viewport.y1 ) - 1;
				return r;
			}
		}
		R_TransformClipToDevice( clip, ndc );
		
		float windowX = 0.5f * ( 1.0f + ndc[0] ) * ( tr.viewDef->viewport.x2 - tr.viewDef->viewport.x1 );
		float windowY = 0.5f * ( 1.0f + ndc[1] ) * ( tr.viewDef->viewport.y2 - tr.viewDef->viewport.y1 );
		
		if( windowX > tr.viewDef->scissor.x2 )
		{
			windowX = tr.viewDef->scissor.x2;
		}
		else if( windowX < tr.viewDef->scissor.x1 )
		{
			windowX = tr.viewDef->scissor.x1;
		}
		
		if( windowY > tr.viewDef->scissor.y2 )
		{
			windowY = tr.viewDef->scissor.y2;
		}
		else if( windowY < tr.viewDef->scissor.y1 )
		{
			windowY = tr.viewDef->scissor.y1;
		}
		r.AddPoint( windowX, windowY );
	}
	
	// add the fudge boundary
	r.Expand();
	
	c_unclippedLight++;
	
	return r;
}
Esempio n. 2
0
/*
==================
idInteraction::CalcInteractionScissorRectangle
==================
*/
idScreenRect idInteraction::CalcInteractionScissorRectangle( const idFrustum &viewFrustum ) {
    idBounds		projectionBounds;
    idScreenRect	portalRect;
    idScreenRect	scissorRect;

    if ( r_useInteractionScissors.GetInteger() == 0 ) {
        return lightDef->viewLight->scissorRect;
    }

    if ( r_useInteractionScissors.GetInteger() < 0 ) {
        // this is the code from Cass at nvidia, it is more precise, but slower
        return R_CalcIntersectionScissor( lightDef, entityDef, tr.viewDef );
    }

    // the following is Mr.E's code

    // frustum must be initialized and valid
    if ( frustumState == idInteraction::FRUSTUM_UNINITIALIZED || frustumState == idInteraction::FRUSTUM_INVALID ) {
        return lightDef->viewLight->scissorRect;
    }

    // calculate scissors for the portals through which the interaction is visible
    if ( r_useInteractionScissors.GetInteger() > 1 ) {
        areaNumRef_t *area;

        if ( frustumState == idInteraction::FRUSTUM_VALID ) {
            // retrieve all the areas the interaction frustum touches
            for ( areaReference_t *ref = entityDef->entityRefs; ref; ref = ref->ownerNext ) {
                area = entityDef->world->areaNumRefAllocator.Alloc();
                area->areaNum = ref->area->areaNum;
                area->next = frustumAreas;
                frustumAreas = area;
            }
            frustumAreas = tr.viewDef->renderWorld->FloodFrustumAreas( frustum, frustumAreas );
            frustumState = idInteraction::FRUSTUM_VALIDAREAS;
        }

        portalRect.Clear();
        for ( area = frustumAreas; area; area = area->next ) {
            portalRect.Union( entityDef->world->GetAreaScreenRect( area->areaNum ) );
        }
        portalRect.Intersect( lightDef->viewLight->scissorRect );
    } else {
        portalRect = lightDef->viewLight->scissorRect;
    }

    // early out if the interaction is not visible through any portals
    if ( portalRect.IsEmpty() ) {
        return portalRect;
    }

    // calculate bounds of the interaction frustum projected into the view frustum
    if ( lightDef->parms.pointLight ) {
        viewFrustum.ClippedProjectionBounds( frustum, idBox( lightDef->parms.origin, lightDef->parms.lightRadius, lightDef->parms.axis ), projectionBounds );
    } else {
        viewFrustum.ClippedProjectionBounds( frustum, idBox( lightDef->frustumTris->bounds ), projectionBounds );
    }

    if ( projectionBounds.IsCleared() ) {
        return portalRect;
    }

    // derive a scissor rectangle from the projection bounds
    scissorRect = R_ScreenRectFromViewFrustumBounds( projectionBounds );

    // intersect with the portal crossing scissor rectangle
    scissorRect.Intersect( portalRect );

    if ( r_showInteractionScissors.GetInteger() > 0 ) {
        R_ShowColoredScreenRect( scissorRect, lightDef->index );
    }

    return scissorRect;
}