void VTerrainVisibilityInfo::Set(IVisVisibilityCollector_cl *pCollector,const VTerrainConfig &config)
{
  hkvVec3 vCamPos(hkvNoInitialization), vCamDir(hkvNoInitialization);
  
  pCollector->GetSourceObject()->GetPosition(vCamPos);
  vCamDir = pCollector->GetSourceObject()->GetDirection();

  VisRenderContext_cl *pLODContext = pCollector->GetLODReferenceRenderContext();
  VASSERT(pLODContext!=NULL && pLODContext->GetCamera()!=NULL);
  pLODContext->GetCamera()->GetPosition(m_vCamLODPos);

  m_vCamPos.FromRenderSpace(config,(const hkvVec3& )vCamPos);
  m_vCamVisPos = vCamPos;
  m_CameraPlane.setFromPointAndNormal(vCamPos,vCamDir);
  VASSERT(m_vCamPos.IsValid(config));

  // compute the rest
  float fNear,fFar;
  pCollector->GetClipPlanes(fNear,fFar);
  m_fMaxViewDistance = fFar;

  m_fLODDistanceInvScale = pLODContext->GetLODDistanceScaling() * VTerrainSectorManager::g_fDecorationDistanceInvScaling;
  if (m_fLODDistanceInvScale>0.f)
    m_fLODDistanceScale = 1.f/m_fLODDistanceInvScale;
  else 
    m_fLODDistanceScale = 0.f;

  // overestimate
  config.GetViewDistanceBox(m_CamBBox, m_vCamVisPos, fFar);
  m_VisibleRangeBox.FromRenderSpace(config,m_CamBBox);
  m_iContextFilterMask = pCollector->GetFilterBitmask();

  // reset min/max
  m_iVisibleSectorRange[0] = m_iVisibleSectorRange[1] = 32000;
  m_iVisibleSectorRange[2] = m_iVisibleSectorRange[3] = -32000;

  // reset some of the values:
  m_iVisibleDecorationCount = 0;
  m_iEstimatedDecorationCount = 0;

  static bool bEnableOpt = true;

  // shadowmap related:
  if (bEnableOpt && pCollector->GetTypeId()==V_RUNTIME_CLASS(VShadowmapVisibilityCollector))
  {
    m_pSMGenerator = ((VShadowmapVisibilityCollector *)pCollector)->m_pSMGenerator;
    float fShadowExtrusionFactor = m_pSMGenerator->GetShadowMapComponent()->GetShadowBoxExtrudeMultiplier();
    m_vShadowExtrusion = m_pSMGenerator->GetDirection();
    if (m_vShadowExtrusion.z<-0.01f) // normalize height
      m_vShadowExtrusion.z *= (-1.f/m_vShadowExtrusion.z);
    m_vShadowExtrusion *= fShadowExtrusionFactor;
    m_bCastDynamicShadows = (m_pSMGenerator->GetShadowMapComponent()->GetGeometryTypes()&SHADOW_CASTER_TERRAIN)>0;
  }
  else
    m_pSMGenerator = NULL;

}
int VMobileForwardRenderLoop::GetLightInfluenceArea(VisLightSource_cl *pLight)
{
  VASSERT(pLight != NULL);

  VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext();
  int iScreenWidth,iScreenHeight;
  pContext->GetSize(iScreenWidth, iScreenHeight);
  if (pLight->GetType() == VIS_LIGHT_DIRECTED)
  {
    // directional lights influence the whole screen
    return (iScreenWidth*iScreenHeight); 
  }

  hkvMat4 projMatrix = pContext->GetViewProperties()->getProjectionMatrix(hkvClipSpaceYRange::MinusOneToOne);
  hkvMat4 viewMatrix = pContext->GetCamera()->GetWorldToCameraTransformation();

  // get position/ radius of bounding sphere
  hkvVec3 vPosition;
  float fRadius = 0.0f;
  if (pLight->GetType() == VIS_LIGHT_POINT)
  {
    vPosition = pLight->GetPosition();
    fRadius = pLight->GetRadius();
  }
  else if (pLight->GetType() == VIS_LIGHT_SPOTLIGHT)
  {
    hkvAlignedBBox bBox;
    pLight->GetBoundingBox(bBox);
    vPosition = bBox.getBoundingSphere().m_vCenter;
    fRadius = bBox.getBoundingSphere().m_fRadius;
  }
  else
    VASSERT_MSG(false, "Unsupported light type"); 
  
  // get corners of bounding rectangle in view space
  hkvVec4 vPositionVS = viewMatrix*vPosition.getAsVec4(1.0f);
  hkvVec4 vCorners[4];
  vCorners[0] = vPositionVS+hkvVec4(-fRadius, -fRadius, 0.0f, 0.0f);
  vCorners[1] = vPositionVS+hkvVec4(fRadius, -fRadius, 0.0f, 0.0f);
  vCorners[2] = vPositionVS+hkvVec4(fRadius, fRadius, 0.0f, 0.0f);
  vCorners[3] = vPositionVS+hkvVec4(-fRadius, fRadius, 0.0f, 0.0f); 

  // get corners of bounding rectangle in normalized device coordinates
  for (int i=0;i<4;i++)
  {
    vCorners[i] = projMatrix*vCorners[i];
    vCorners[i] /= vCorners[i].w;
  }

  // clip corners of bounding rectangle
  hkvVec2 vMin(vCorners[0].x, vCorners[0].y); 
  vMin.clampTo(hkvVec2(-1.0f, -1.0f), hkvVec2(1.0f, 1.0f));
  hkvVec2 vMax(vCorners[2].x, vCorners[2].y); 
  vMax.clampTo(hkvVec2(-1.0f, -1.0f), hkvVec2(1.0f, 1.0f));

  // calculate influence area 
  int iWidth = (int)((vMax.x-vMin.x)*0.5f*iScreenWidth);
  int iHeight = (int)((vMax.y-vMin.y)*0.5f*iScreenHeight);
  return (iWidth*iHeight);
}
void VMobileForwardRenderLoop::DetermineRelevantLights()
{
  m_DynamicLightCollection.Clear();
  m_pBasePassLight = NULL;
  m_iBasePassLightPriority = 0;

  // Get all visible light sources
  IVisVisibilityCollector_cl *pVisColl = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector();
  if (pVisColl == NULL)
    return;
  const VisLightSrcCollection_cl *pLightSourceCollection = pVisColl->GetVisibleLights();
  if (pLightSourceCollection == NULL)
    return;

  unsigned int iNumLights = pLightSourceCollection->GetNumEntries();
  if (iNumLights == 0)
    return;
  
  VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext();
  const hkvVec3 &vCamPos = pContext->GetCamera()->GetPosition();

  for (unsigned i=0;i<iNumLights;i++)
  {
    VisLightSource_cl *pLight = pLightSourceCollection->GetEntry(i);

    // We are only interested in dynamic lights or static lights with attached shadow map component
    if ((!pLight->IsDynamic() && !GetCompatibleShadowMapComponent(pLight)) || pLight->GetRadius()<=HKVMATH_LARGE_EPSILON)  
      continue;

    const float fFade = pLight->GetMultiplier()*pLight->GetFadeWeight(vCamPos);
    if (fFade <= HKVMATH_LARGE_EPSILON)
      continue;

    // See which geometry types have to cast shadows
    int iReceiverFlags = GetLightReceiverFlags(pLight);

    // If nothing receives light from this light source, we can proceed to the next light.
    if (!iReceiverFlags)
      continue;

    // Find light with highest priority. This light will be rendered in the base pass, in contrast to all 
    // additional lights that are rendered additively after the base pass. The search ignores lights with 
    // attached light clipping volume, since light clipping volumes can't be rendered before the base pass.
    if (!pLight->HasClipVolumeComponent())
    {
      // get the light with highest priority (largest influence area in screen space combined with weighting factor)
      int iLightPriority = GetLightPriority(pLight);
      if (iLightPriority > m_iBasePassLightPriority)
      {
        m_pBasePassLight = pLight;
        m_iBasePassLightPriority = iLightPriority;
      }
    } 
   
    if (pLight->IsDynamic())
      m_DynamicLightCollection.AppendEntry(pLight); 
  }
}
void VLensFlareComponent::UpdateVisibility (float& fLastVisibilityQuery, float& fCurrentVisibility)
{
  // Make sure we are actually attached to an object
  if (GetOwner())
  {
    // Get Camera
    VisRenderContext_cl* pContext = VisRenderContext_cl::GetCurrentContext();
    const hkvVec3 vCameraPos = pContext->GetCamera()->GetPosition();

    // Get Light
    VisLightSource_cl* pLight = (VisLightSource_cl*)GetOwner();
    hkvVec3 vPos;
    pLight->GetVirtualPosition( vPos, pContext );

    hkvVec3 vDist = vCameraPos - vPos;
    float fDist = vDist.getLength();
    float fFactor = 1.0f;

    // Distance FadeOut
    if (FadeOutEnd != 0 && FadeOutStart < FadeOutEnd)
    {
      if (fDist > FadeOutEnd)
      {
        fFactor = 0.0f;
      }
      else if (fDist > FadeOutStart)
      {
        fFactor = 1.0f - (fDist - FadeOutStart) / (FadeOutEnd - FadeOutStart);
      }
    }

    // Apply distance fade out
    fLastVisibilityQuery *= fFactor;

    // PreGlow/AfterGlow
    if (fLastVisibilityQuery > fCurrentVisibility)
    {
      float fSpeed = Vision::GetTimer()->GetTimeDifference() / ((PreGlowMS + 1) * 0.001f);
      fCurrentVisibility = hkvMath::Min(fCurrentVisibility + fSpeed, fLastVisibilityQuery);
    }
    else if (fLastVisibilityQuery < fCurrentVisibility)
    {
      float fSpeed = Vision::GetTimer()->GetTimeDifference() / ((AfterGlowMS + 1) * 0.001f);
      fCurrentVisibility = hkvMath::Max(fCurrentVisibility - fSpeed, fLastVisibilityQuery);
    }

    fCurrentVisibility = hkvMath::clamp(fCurrentVisibility, 0.0f, 1.0f);
  }
}
bool VOcclusionQueryObjectPixelCounterLensFlare::Render(VOcclusionQuery &query, const hkvAlignedBBox &safeBox)
{
  if (m_pLensFlare != NULL && m_pLensFlare->GetOwner() != NULL)
  {
    SetState(VISQUERY_RENDERSTATE_BILLBOARD);
    
    VisRenderContext_cl* pContext = VisRenderContext_cl::GetCurrentContext();

    VisLightSource_cl* pLight = (VisLightSource_cl*)m_pLensFlare->GetOwner();
    hkvVec3 vPos(hkvNoInitialization);
    pLight->GetVirtualPosition(vPos, pContext);

    hkvVec3 vCameraDir = pContext->GetCamera()->GetPosition() - vPos;
    vCameraDir /= hkvMath::Max(vCameraDir.getLength(), HKVMATH_LARGE_EPSILON);

    vPos += vCameraDir * m_pLensFlare->GetDepthBias();

    query.DoHardwareOcclusionTest_Billboard(&vPos.x, m_pLensFlare->GetCheckBlockSize());
    return true;
  }
  return false;
}
Пример #6
0
/// update all internal data
//////////////////////////////////////////////////////////////////////////
bool CScaler::UpdateInternalsAndGetVisibility()
{
	VisRenderContext_cl* pCtx = Vision::Contexts.GetCurrentContext();
	const VisMatrix4x4_cl& mtxProjection = pCtx->GetProjectionMatrix();
	VisContextCamera_cl* pContextCam = pCtx->GetCamera();
	pContextCam->GetWorldMatrix( m_mtxViewProjection ); // it`s View mtx and not all cells are filled?!?, fix below

	// ogl View to dx View mtx crap
	float* pGlmatrix = m_mtxViewProjection.GetFloatPtr();
	pGlmatrix[ 2 ]  = -pGlmatrix[ 2 ];
	pGlmatrix[ 6 ]  = -pGlmatrix[ 6 ];
	pGlmatrix[ 10 ] = -pGlmatrix[ 10 ];
	pGlmatrix[ 14 ] = -pGlmatrix[ 14 ];
	pGlmatrix[ 15 ] = 1.f; //this must be here, GetWorldMatrix DOES NOT fill all cells !!!

	// multiply is now DX style  (ogl is projection*view*world)
	m_mtxViewProjection *= mtxProjection;

	// get transpose mtx of ViewProjection
	m_mtxViewProjectionT = m_mtxViewProjection;
	m_mtxViewProjectionT.Transpose();

	// gen VPInverse mtx (if sended to shader, must be transposed)
	m_mtxViewProjectionInv = m_mtxViewProjection;
	m_mtxViewProjectionInv.InvertEx();

	// calculate -far & far plane vectors (homogeneous space)
	m_NearPlane.v1.SetXYZW( -1, 1, 0, 1 );
	m_NearPlane.v2.SetXYZW( 1, 1, 0, 1 );
	m_NearPlane.v3.SetXYZW( 1, -1, 0, 1 );
	m_NearPlane.v4.SetXYZW( -1, -1, 0, 1 );

	m_FarPlane.v1.SetXYZW( -1, 1, 1, 1 );
	m_FarPlane.v2.SetXYZW( 1, 1, 1, 1 );
	m_FarPlane.v3.SetXYZW( 1, -1, 1, 1 );
	m_FarPlane.v4.SetXYZW( -1, -1, 1, 1 );

	// w are all ones so Vision may be used
	m_NearPlane.v1 *= m_mtxViewProjectionInv;
	m_NearPlane.v2 *= m_mtxViewProjectionInv;
	m_NearPlane.v3 *= m_mtxViewProjectionInv;
	m_NearPlane.v4 *= m_mtxViewProjectionInv;

	m_FarPlane.v1 *= m_mtxViewProjectionInv;
	m_FarPlane.v2 *= m_mtxViewProjectionInv;
	m_FarPlane.v3 *= m_mtxViewProjectionInv;
	m_FarPlane.v4 *= m_mtxViewProjectionInv;

	_GetWorldPos( m_NearPlane, m_WorldNearPlane );
	_GetWorldPos( m_FarPlane, m_WorldFarPlane );

	GetIntersectionsAndPointsBeetween(); // will fill m_aIntesections & counter

	// skip if can`t generate proper matrix ( volume is outside of frustum )
	if( m_iInterectionsCount >= 4 ) // valid
	{
		// get clip space coords to calculate XY span
		for( int i=0; i<m_iInterectionsCount; i++ )
		{
			//m_aIntersections[ i ].w = 1.f; // Vision use w as 1 so don`t set
			m_aIntersections[ i ].z = 0.f; // TODO: should be water level
			m_aIntersections[ i ] *= m_mtxViewProjectionT; // use transposed mtx
			m_aIntersections[ i ].x /= m_aIntersections[ i ].w;
			m_aIntersections[ i ].y /= m_aIntersections[ i ].w;
			//m_aIntersections[ i ].z /= m_aIntersections[ i ].w; // we dont need Z
		}

		float fXMin = FLT_MAX; float fXMax = -FLT_MAX;
		float fYMin = FLT_MAX; float fYMax = -FLT_MAX;

		for( int i=0; i<m_iInterectionsCount; i++ )
		{
			if( m_aIntersections[ i ].x > fXMax )
				fXMax = m_aIntersections[ i ].x;
			if ( m_aIntersections[ i ].x < fXMin )
				fXMin = m_aIntersections[ i ].x;
			if( m_aIntersections[ i ].y > fYMax )
				fYMax = m_aIntersections[ i ].y;
			if ( m_aIntersections[ i ].y < fYMin )
				fYMin = m_aIntersections[ i ].y;
		}

		// build scaling matrix. it prevents h-space verts in shader to run out of range

		/* normal way
		VisMatrix4x4_cl mtxScale;
		mtxScale.Identity();
		mtxScale[ 0 ] = fXMax - fXMin;
		mtxScale[ 5 ] = fYMax - fYMin;
		mtxScale[ 12 ] = fXMin;
		mtxScale[ 13 ] = fYMin;
		mtxScale.Transpose();
		*/

		// faster way
		m_mtxScale[ 0 ] = fXMax - fXMin;
		m_mtxScale[ 5 ] = fYMax - fYMin;
		m_mtxScale[ 3 ] = fXMin;
		m_mtxScale[ 7 ] = fYMin;


		m_mtxViewProjectionInv *= m_mtxScale;

		m_NearPlane.v1.SetXYZW( 0, 1, 0, 1 );
		m_NearPlane.v2.SetXYZW( 1, 1, 0, 1 );
		m_NearPlane.v3.SetXYZW( 1, 0, 0, 1 );
		m_NearPlane.v4.SetXYZW( 0, 0, 0, 1 );

		m_FarPlane.v1.SetXYZW( 0, 1, 1, 1 );
		m_FarPlane.v2.SetXYZW( 1, 1, 1, 1 );
		m_FarPlane.v3.SetXYZW( 1, 0, 1, 1 );
		m_FarPlane.v4.SetXYZW( 0, 0, 1, 1 );

		m_NearPlane.v1 *= m_mtxViewProjectionInv;
		m_NearPlane.v2 *= m_mtxViewProjectionInv;
		m_NearPlane.v3 *= m_mtxViewProjectionInv;
		m_NearPlane.v4 *= m_mtxViewProjectionInv;

		m_FarPlane.v1 *= m_mtxViewProjectionInv;
		m_FarPlane.v2 *= m_mtxViewProjectionInv;
		m_FarPlane.v3 *= m_mtxViewProjectionInv;
		m_FarPlane.v4 *= m_mtxViewProjectionInv;
		return true;
	}else
	{
		// do not render
		return false;
	}
}
Пример #7
0
// TODO: This doesn't handle opaque fullbright surfaces correctly yet, and translucent fullbright surfaces are simply ignored.
void MirrorRenderLoop_cl::OnDoRenderLoop(void *pUserData)
{
  INSERT_PERF_MARKER_SCOPE("MirrorRenderLoop_cl::OnDoRenderLoop");

#if defined (WIN32) || defined (_VISION_XENON) || defined (_VISION_PS3) || defined(_VISION_PSP2) || defined(_VISION_WIIU)
  if (Vision::Editor.GetIgnoreAdvancedEffects())
  {
    // force a black reflection because it won't work with orthographic views
    Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_All, V_RGBA_BLACK);
    return;
  }
#endif

  VisRenderContext_cl *pContext = Vision::Contexts.GetCurrentContext();

  const int iRenderFlags = pContext->GetRenderFlags();

  const float fFarClipDist = m_pMirror->GetActualFarClipDistance();

  const VFogParameters &fog = Vision::World.GetFogParameters();
  VColorRef clearColor = (fog.depthMode != VFogParameters::Off) ? fog.iDepthColor : Vision::Renderer.GetDefaultClearColor();
  Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_All, clearColor);

  // set the oblique clipping plane...
  pContext->SetCustomProjectionMatrix (m_pMirror->GetObliqueClippingProjection().getPointer ());

  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesPrimaryOpaquePass;
  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesSecondaryOpaquePass;
  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesTransparentPass;
  const VisEntityCollection_cl *pVisEntities;


  // === Visibility Determination ===

  IVisVisibilityCollector_cl *pVisColl = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector();
  if (pVisColl == NULL)
    return;
  const VisVisibilityObjectCollection_cl *pVisObjectCollection = pVisColl->GetVisibleVisObjects();

  hkvAlignedBBox box;
  int iVoCount = m_pMirror->GetVisibilityObjectCount();
  int iFrustumCount = 0;
  bool bUseCommonFrustum = false;

  // === Determine Scissor Rect ===
  hkvVec2 vMinScreenSpace, vMaxScreenSpace;
  const hkvAlignedBBox &worldSpaceBox = m_pMirror->GetBoundingBox();

  hkvVec3 vCorners[8];
  worldSpaceBox.getCorners (vCorners);

  VRectanglef scissorRect;
  bool bUseScissorRect = true;
  for (int i=0; i<8; i++)
  {
    float x2d, y2d;
    BOOL bInFrontOfCamera = pContext->Project2D(vCorners[i], x2d, y2d);
    if (bInFrontOfCamera)
    {
      scissorRect.Add(hkvVec2(x2d, y2d));
    }
    else
    {
      bUseScissorRect = false;
      break;
    }
  }

  if (bUseScissorRect)
    Vision::RenderLoopHelper.SetScissorRect(&scissorRect);

  for (int iVo = 0; iVo < iVoCount; iVo++)
  {
    VisVisibilityObject_cl *pVisObj = m_pMirror->GetVisibilityObject(iVo);
    if (pVisObj != NULL && pVisObj->WasVisibleInAnyLastFrame())
    {
      if (iFrustumCount <= MAX_SEPARATE_FRUSTA)
      {
        const hkvAlignedBBox &voBox = pVisObj->GetWorldSpaceBoundingBox();
        box.expandToInclude(voBox);
        if (m_Frustum[iFrustumCount].Set(pContext->GetCamera()->GetPosition(), voBox, true, fFarClipDist))
        {
          iFrustumCount++;
        }
        else
        {
          bUseCommonFrustum = true;
        }
      }
      else
      {
        const hkvAlignedBBox &voBox = pVisObj->GetWorldSpaceBoundingBox();
        box.expandToInclude(voBox);
        bUseCommonFrustum = true;
      }
    }
  }

  if (bUseCommonFrustum)
  {
    iFrustumCount = 1;
    if (!m_Frustum[0].Set(pContext->GetCamera()->GetPosition(), box, true, fFarClipDist))
      iFrustumCount = 0;
  }

  if (iFrustumCount>0)
  {
    for (int i=0; i<iFrustumCount; i++)
    {
      m_visiblePrimaryOpaquePassGeoInstances.Clear();
      m_visibleSecondaryOpaquePassGeoInstances.Clear();
      m_visibleTransparentOpaquePassGeoInstances.Clear();
      m_visEntities.Clear();
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass)->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visiblePrimaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass)->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visibleSecondaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass)->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visibleTransparentOpaquePassGeoInstances);
      pVisColl->GetVisibleEntities()->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visEntities);
      if (iFrustumCount == 1)
        break;
      m_visiblePrimaryOpaquePassGeoInstances.TagEntries();
      m_visibleSecondaryOpaquePassGeoInstances.TagEntries();
      m_visibleTransparentOpaquePassGeoInstances.TagEntries();
      m_visEntities.TagEntries();
    }
    if (iFrustumCount > 1)
    {
      m_visiblePrimaryOpaquePassGeoInstances.Clear();
      m_visibleSecondaryOpaquePassGeoInstances.Clear();
      m_visibleTransparentOpaquePassGeoInstances.Clear();
      m_visEntities.Clear();
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass)->GetTaggedEntries(m_visiblePrimaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass)->GetTaggedEntries(m_visibleSecondaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass)->GetTaggedEntries(m_visibleTransparentOpaquePassGeoInstances);
      pVisColl->GetVisibleEntities()->GetTaggedEntries(m_visEntities);
    }
    pVisibleGeoInstancesPrimaryOpaquePass = &m_visiblePrimaryOpaquePassGeoInstances;
    pVisibleGeoInstancesSecondaryOpaquePass = &m_visibleSecondaryOpaquePassGeoInstances;
    pVisibleGeoInstancesTransparentPass = &m_visibleTransparentOpaquePassGeoInstances;
    pVisEntities = &m_visEntities;
  }
  else
  {
    pVisibleGeoInstancesPrimaryOpaquePass = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass);
    pVisibleGeoInstancesSecondaryOpaquePass = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass);
    pVisibleGeoInstancesTransparentPass = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass);
    pVisEntities = pVisColl->GetVisibleEntities();
  }

  // === End Visibility Determination ===

  if (m_pMirror->GetExecuteRenderHooks())
  {
    VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook,VRH_PRE_PRIMARY_OPAQUE_PASS_GEOMETRY);
    Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data);
  }

  // Render opaque static geometry
  VASSERT(m_spDefaultLightMapping->m_Shaders.Count()==1);

  TRIGGER_MIRROR_HOOK(VRH_PRE_PRIMARY_OPAQUE_PASS_GEOMETRY)
  VisMirror_cl::VReflectionShaderSets_e shaderMode = m_pMirror->m_eReflectionShaderMode;
  DrawStaticGeometry(*pVisibleGeoInstancesPrimaryOpaquePass, VPT_PrimaryOpaquePass);
  DrawStaticGeometry(*pVisibleGeoInstancesSecondaryOpaquePass, VPT_SecondaryOpaquePass);

  // Render entities
  const VisEntityCollection_cl *pEntities = pVisEntities;
  int iCount = pEntities->GetNumEntries();
  VASSERT(m_spDefaultLightGrid->m_Shaders.Count()==1);
  //VCompiledShaderPass *pLightgridShader = m_spDefaultLightGrid->m_Shaders.GetAt(0);
  int i;
  //bool bUseSimpleShader = shaderMode==VisMirror_cl::AlwaysSimple;

  Vision::RenderLoopHelper.BeginEntityRendering();

  for (i=0;i<iCount;i++)
  { 
    VisBaseEntity_cl *pEnt = pEntities->GetEntry(i);

//    Vision::RenderLoopHelper.TrackLightGridInfo(pEnt);  // important: need to be done in RenderEntityWithSurfaceShaderList

    //if (bUseSimpleShader)
    //{
    //  Vision::RenderLoopHelper.RenderEntityWithShaders(pEnt,1,&pLightgridShader);
    //}
    //else
    {
      VisDrawCallInfo_t surfaceShaderList[RLP_MAX_ENTITY_SURFACES];
      VDynamicMesh *pMesh = pEnt->GetMesh();
      VisSurface_cl **ppSurfaces = pEnt->GetSurfaceArray();
      int iNumSubmeshes = pMesh->GetSubmeshCount();
      for (int j=0; j<iNumSubmeshes; j++)
      {
        VisDrawCallInfo_t &info(surfaceShaderList[j]);
        VBaseSubmesh* pSubmesh = pMesh->GetSubmesh(j);
        VisSurface_cl* pSurface = ppSurfaces[pSubmesh->m_iMaterialIndex];
        info.Set(pSubmesh, pSurface, GetMirrorShader (pSurface, shaderMode));
      }

      Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEnt, iNumSubmeshes, surfaceShaderList);
    }
  }

  Vision::RenderLoopHelper.EndEntityRendering();

  // Render Sky
  if (VSky::IsVisible())
  {
    // The sky has to be rendered without oblique clipping
    pContext->SetCustomProjectionMatrix(NULL);
    Vision::RenderLoopHelper.RenderSky();
    // set the oblique clipping plane after sky...
    pContext->SetCustomProjectionMatrix (m_pMirror->GetObliqueClippingProjection().getPointer ());
  }

  if (m_pMirror->GetExecuteRenderHooks())
  {
    VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook,VRH_PRE_OCCLUSION_TESTS);
    Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data);
  }

  // Render Coronas / Lens Flares
  VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook,VRH_CORONAS_AND_FLARES);
  Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data);
  TRIGGER_MIRROR_HOOK(VRH_PRE_OCCLUSION_TESTS)  

  if (iRenderFlags&VIS_RENDERCONTEXT_FLAG_USE_OCCLUSIONQUERY)
    Vision::RenderLoopHelper.PerformHardwareOcclusionQuery();

  if (iRenderFlags&VIS_RENDERCONTEXT_FLAG_USE_PIXELCOUNTER)
    Vision::RenderLoopHelper.PerformHardwarePixelCounterQuery();

  DrawDynamicLight();

  TRIGGER_MIRROR_HOOK(VRH_DECALS)
  TRIGGER_MIRROR_HOOK(VRH_CORONAS_AND_FLARES)

  TRIGGER_MIRROR_HOOK(VRH_PRE_TRANSPARENT_PASS_GEOMETRY)
  DrawStaticGeometry(*pVisibleGeoInstancesTransparentPass, VPT_TransparentPass);
  TRIGGER_MIRROR_HOOK(VRH_POST_TRANSPARENT_PASS_GEOMETRY)

  if (bUseScissorRect)
    Vision::RenderLoopHelper.SetScissorRect(NULL);
}
Пример #8
0
// renders visible wallmarks of specified pass type (pre or post, which is relevant in deferred context)
void VWallmarkManager::RenderProjectedWallmarks(VPassType_e ePassType)
{
  INSERT_PERF_MARKER_SCOPE("Wallmark Rendering (VWallmarkManager::RenderProjectedWallmarks)");

  const int iWallmarkCount = m_AllProjectedWallmarks.Count();
  IVisVisibilityCollector_cl *pVisCollector = Vision::Contexts.GetCurrentContext()->GetVisibilityCollector();
  if (!pVisCollector || !iWallmarkCount)
    return;

  const VisStaticGeometryInstanceCollection_cl *pGeoInstances = pVisCollector->GetVisibleStaticGeometryInstances();

  VisStaticGeometryInstance_cl::ResetTags();
  pGeoInstances->TagEntries();
  VisStaticGeometryInstanceCollection_cl &targetGiCollection = m_TempGeoInstanceCollection;

  VisRenderContext_cl *pContext = Vision::Contexts.GetCurrentContext();
  VisRenderContext_cl *pLODContext = pContext->GetLODReferenceContext();
  hkvVec3 vLODPos = pLODContext ? pLODContext->GetCamera()->GetPosition() : pContext->GetCamera()->GetPosition();

  unsigned int iContextFilter = pContext->GetRenderFilterMask();
  const VisFrustum_cl *pFrustum = pVisCollector->GetBaseFrustum();

  int i;
  for (i=0;i<iWallmarkCount;i++)
  {
    VProjectedWallmark *pProjWallmark = m_AllProjectedWallmarks.GetAt(i);
    if ((pProjWallmark->GetVisibleBitmask() & iContextFilter)==0 || (ePassType & pProjWallmark->m_ePassType) == 0)
      continue;
    pProjWallmark->PrepareForRendering();
    const VisStaticGeometryInstanceCollection_cl &wmGiList = pProjWallmark->GetStaticGeometryCollection();  

#ifdef HK_DEBUG
    const int iNum = wmGiList.GetNumEntries();
    for (int j=0;j<iNum;j++)
    {
      VisStaticGeometryInstance_cl *pInst = wmGiList.GetEntry(j);
      VASSERT_MSG(pInst && (pInst->GetGeometryType()==STATIC_GEOMETRY_TYPE_MESHINSTANCE || pInst->GetGeometryType()==STATIC_GEOMETRY_TYPE_TERRAIN), "The wallmark conains invalid primitive references")
    }
#endif

    // clip against its bounding box (primitive visibility might overestimate visible parts)
    const hkvAlignedBBox &bbox = pProjWallmark->GetBoundingBox();
    if (pProjWallmark->m_fFarClipDistance>0.f && pProjWallmark->m_fFarClipDistance<bbox.getDistanceTo(vLODPos))
      continue;
    if (pFrustum && !pFrustum->Overlaps(bbox))
      continue;

    const int iGeomFilter = pProjWallmark->GetGeometryTypeFilterMask();
    if (iGeomFilter&PROJECTOR_AFFECTS_STATICMESHES)
    {
      // standard geometry
      targetGiCollection.Clear();
      wmGiList.GetTaggedEntriesOfType(targetGiCollection,STATIC_GEOMETRY_TYPE_MESHINSTANCE);
      if (targetGiCollection.GetNumEntries())
      {
        // render the static geometry instances using lightmapped or non-lightmapped shader
        VProjectorShaderPass *pShader = GetWallmarkShader(pProjWallmark,STATIC_GEOMETRY_TYPE_MESHINSTANCE);
        Vision::RenderLoopHelper.RenderStaticGeometryWithShader(targetGiCollection, *pShader);
      }
    }

    if (iGeomFilter&PROJECTOR_AFFECTS_TERRAIN)
    {
      // terrain geometry (different shader)
      targetGiCollection.Clear();
      wmGiList.GetTaggedEntriesOfType(targetGiCollection,STATIC_GEOMETRY_TYPE_TERRAIN);
      if (targetGiCollection.GetNumEntries()>0)
      {
        // render the static geometry instances using lightmapped or non-lightmapped shader
        VProjectorShaderPass *pShader = GetWallmarkShader(pProjWallmark,STATIC_GEOMETRY_TYPE_TERRAIN);
        if (pShader)
          Vision::RenderLoopHelper.RenderStaticGeometryWithShader(targetGiCollection, *pShader);
      }
    }

    // entities
    if (iGeomFilter&PROJECTOR_AFFECTS_ENTITIES)
    {
      const VisEntityCollection_cl *pVisibleEntities = pVisCollector->GetVisibleEntities();
      const unsigned int iInfluenceMask = pProjWallmark->GetInfluenceBitmask();
      m_TempEntityCollection.Clear();
      const int iEntCount = pVisibleEntities->GetNumEntries();
      for (int j=0;j<iEntCount;j++)
      {
        VisBaseEntity_cl *pEntity = pVisibleEntities->GetEntry(j);
        if (pEntity==NULL || (pEntity->GetVisibleBitmask()&iInfluenceMask)==0)
          continue;
        const hkvAlignedBBox &entityBox(*pEntity->GetCurrentVisBoundingBoxPtr());
        if (!entityBox.overlaps(bbox))
          continue;
        m_TempEntityCollection.AppendEntry(pEntity);
      }
      if (m_TempEntityCollection.GetNumEntries()>0)
      {
        VProjectorShaderPass *pShader = GetWallmarkShader(pProjWallmark,STATIC_GEOMETRY_TYPE_MESHINSTANCE); // we can use this shader - VS skinning is used implicitly
        Vision::RenderLoopHelper.RenderEntitiesWithShader(m_TempEntityCollection, *pShader);
      }
    }

  }
}
void VMobileForwardRenderLoop::RenderLitGeometry(VisLightSource_cl *pLight, IVShadowMapComponent *pShadowMapComponent, bool bBasePass, bool bUsesLightClippingVolume, bool bEntities, bool bStaticGeometry)
{
  if (!pLight)
    return;

  // Some local variables for storing surfaces, shaders, surface shaders, and the like.
  VCompiledTechnique *pTechnique = NULL;
  VisDrawCallInfo_t SurfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];

  VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext();
  const hkvVec3 &vCamPos = pContext->GetCamera()->GetPosition();
 
  const float fFade = pLight->GetFadeWeight(vCamPos);

  VisStaticGeometryInstanceCollection_cl *pLitGeoInstanceCollection = NULL;
  VisEntityCollection_cl *pLitEntityCollection = NULL;

  if (bBasePass || pLight != m_pBasePassLight)
  {
    if (bStaticGeometry)
    {
      pLitGeoInstanceCollection = &s_LitGeoInstanceCollection;
      pLitGeoInstanceCollection->Clear();
    }
    if (bEntities)
    {
      pLitEntityCollection = &s_LitEntityCollection;
      pLitEntityCollection->Clear();
    }

    Vision::RenderLoopHelper.GetVisibleGeometryInLightsourceRange(pLitGeoInstanceCollection, pLitEntityCollection, NULL, *pLight);
  }
  else
  {
    if (bStaticGeometry)
      pLitGeoInstanceCollection = &m_AdditiveLitGeoInstanceCollection;
    if (bEntities)
      pLitEntityCollection = &m_AdditiveLitEntityCollection;
  }

#ifdef SUPPORTS_SHADOW_MAPS
  VShadowMapGenSpotDir *pShadowMapGenDir = NULL;
  if (pShadowMapComponent)
  {
    VShadowMapGenerator *pShadowMapGen = pShadowMapComponent->GetShadowMapGenerator();
    if (pShadowMapGen->GetProjectionType()==SHADOW_PROJECTION_ORTHOGRAPHIC)
      pShadowMapGenDir = static_cast<VShadowMapGenSpotDir*>(pShadowMapGen);
  }
#endif

  // Set the stencil render state for reading light clipping volume information
  if(bUsesLightClippingVolume)
  {
    const VLightClippingVolumeComponent* pLightClippingComponent = pLight->Components().GetComponentOfBaseType<VLightClippingVolumeComponent>();
    VASSERT(pLightClippingComponent != NULL && V_ARRAY_SIZE(m_lightClippingStencilStatesRead)==2);
    VisRenderStates_cl::SetDepthStencilState(m_lightClippingStencilStatesRead[pLightClippingComponent->GetClipHandedness()]);
  }
  else
    VisRenderStates_cl::SetDepthStencilState(m_dynLightDefaultState);

  // For all illuminated entities: Render a dynamic lighting pass now.
  if (pLight->GetLightInfluenceBitMaskEntity() != 0  && bEntities)
  {
    int iNumLitEntities = pLitEntityCollection->GetNumEntries();

    Vision::RenderLoopHelper.BeginEntityRendering();

    for (int j=0; j<iNumLitEntities; j++)
    {
      VisBaseEntity_cl *pEntity = pLitEntityCollection->GetEntry(j);

      if (!(pEntity->GetLightInfluenceBitMask() & pLight->GetLightInfluenceBitMaskEntity()))
        continue;

      VDynamicMesh *pMesh = pEntity->GetMesh();
      VisSurface_cl **ppSurfaces = pEntity->GetSurfaceArray();

      // Get list of all the surfaces in the model
      int iNumSubmeshes = pMesh->GetSubmeshCount();
      int iNumSurfaceShaders = 0;

      // For all the surfaces...
      for (int k=0; k<iNumSubmeshes; k++)
      {
        VDynamicSubmesh *pSubmesh = pMesh->GetSubmesh(k);
        VisSurface_cl *pSurface = ppSurfaces[pSubmesh->m_iMaterialIndex];

        // Full-bright surfaces can't be rendered in the compound base pass, since such surfaces are not illuminated. Since tagging
        // of already rendered geometry happens per entity instance, in case an entity contains full-bright surfaces, all surfaces 
        // of this entity have to be rendered in the normal rendering pipeline.
        const VisLightingMethod_e eLightingMethod = pSurface->GetLightingMode();
        if (bBasePass)
        {
          // Since entities can contain several surfaces with different lighting methods (full-bright, dynamic only, etc.), entities 
          // with full-bright surfaces have to be also added to the additive lit entity collection, in order to ensure rendering of 
          // dynamic only surfaces.
          if (eLightingMethod==VIS_LIGHTING_FULLBRIGHT)
          {
            iNumSurfaceShaders = 0;
            m_AdditiveLitEntityCollection.AppendEntry(pEntity);
            break; 
          }
        }
        else
        {
          if (eLightingMethod == VIS_LIGHTING_FULLBRIGHT)
            continue;
        }

        // If not all surfaces have a primary opaque pass type in the base pass, then render corresponding entity 
        // in the additive lighting pass.
        if (bBasePass && pSurface->GetResolvedPassType()!=VPT_PrimaryOpaquePass)
        {
          iNumSurfaceShaders = 0;
          m_AdditiveLitEntityCollection.AppendEntry(pEntity);
          break; 
        }

        // Check whether entity is in current shadow volume for orthographic shadows. In that case the entity is rendered
        // without shadows since it is not in the relevant shadow volume.
        IVShadowMapComponent *pTmpShadowMapComponent = pShadowMapComponent;
#ifdef SUPPORTS_SHADOW_MAPS
        if (pShadowMapGenDir)
        {
          if (!pShadowMapGenDir->IsEntityInsideOrthoShadowVolume(pEntity))
            pTmpShadowMapComponent = NULL;
        }
#endif

        pTechnique = GetLightShader(pLight, bBasePass, pSurface, fFade, pTmpShadowMapComponent);
        if (!pTechnique || !pTechnique->GetShaderCount()) // do not light this surface
        {
          // If base-pass lighting technique could not be retrieved, render lit entity in the additive pass.
          if (bBasePass && pLight->IsDynamic())
            m_AdditiveLitEntityCollection.AppendEntry(pEntity);
          iNumSurfaceShaders = 0;
          break; 
        }

        // Generate a list of surface shader from the combined surface/shader information
        VisDrawCallInfo_t &info(SurfaceShaderList[iNumSurfaceShaders++]);
        info.Set(pSubmesh, pSurface, pTechnique->m_Shaders.GetAt(0));
      }

      // Finally, render the entity with a surface shader list.
      if (iNumSurfaceShaders>0)
      {
        Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEntity, iNumSurfaceShaders, SurfaceShaderList);
        if (bBasePass)
          pEntity->Tag();
      }
    }

    Vision::RenderLoopHelper.EndEntityRendering();
  }

  // For all illuminated world primitives: Render a dynamic lighting pass now.
  if (pLight->GetLightInfluenceBitMaskWorld() != 0 && bStaticGeometry)
  {
    VisSurface_cl *pSurface;
    VisSurface_cl *pLastSurface = NULL;
    VCompiledTechnique *pLastTechnique = NULL;

    // We start collecting illuminated mesh instances. Whenever a relevant property changes, we set the
    // shader information, render all collected world instances, and start collecting from scratch.
    int iNumLitGeoInstances = pLitGeoInstanceCollection->GetNumEntries();
    pLastSurface = NULL;
    s_RenderGeoInstanceCollection.Clear();
    pLastTechnique = NULL;

    for (int j=0; j<iNumLitGeoInstances; j++)
    {
      VisStaticGeometryInstance_cl *pGI = pLitGeoInstanceCollection->GetEntry(j);

      pSurface = pGI->GetSurface();
      VASSERT(pSurface);
      if (pSurface->IsFullbright()) 
        continue; 

      // If surface does not have a primary opaque pass type in the base pass, then render corresponding static
      // mesh instance in the additive lighting pass.
      if (bBasePass && pSurface->GetResolvedPassType()!=VPT_PrimaryOpaquePass)
      {
        m_AdditiveLitGeoInstanceCollection.AppendEntry(pGI);
        continue;
      }

      // Check whether mesh is in current shadow volume for orthographic shadows. In that case the mesh is rendered
      // without shadows since it is not in the relevant shadow volume.
      IVShadowMapComponent *pTmpShadowMapComponent = pShadowMapComponent;
#ifdef SUPPORTS_SHADOW_MAPS
      if (pShadowMapGenDir)
      {
        if (!pShadowMapGenDir->IsMeshInsideOrthoShadowVolume(pGI))
          pTmpShadowMapComponent = NULL;
      }
#endif

      if (pLastSurface!=pSurface)
      { 
        pTechnique = GetLightShader(pLight, bBasePass, pSurface, fFade, pTmpShadowMapComponent);          
        pLastSurface = pSurface;
      }
      if (pTechnique == NULL || !pTechnique->GetShaderCount())
      {
        // If base-pass lighting technique could not be retrieved, render lit mesh in the additive pass.
        if (bBasePass && pLight->IsDynamic())
          m_AdditiveLitGeoInstanceCollection.AppendEntry(pGI);
        continue; 
      }

      // If the state information is different from the previous one, we have to render the world primitives we
      // have collected so far
      if (pLastTechnique!=pTechnique)
      {
        if (s_RenderGeoInstanceCollection.GetNumEntries()!=0)
        {
          VASSERT(pLastTechnique != NULL);
          Vision::RenderLoopHelper.RenderStaticGeometryWithShader(s_RenderGeoInstanceCollection, *pLastTechnique->m_Shaders.GetAt(0));
          if (bBasePass)
            s_RenderGeoInstanceCollection.TagEntries();
          s_RenderGeoInstanceCollection.Clear();      
        }
        // Update the stored state information
        pLastTechnique = pTechnique;
      }
      // Naturally, we have to append the primitive to our collection (otherwise it won't be collected =) ).
      s_RenderGeoInstanceCollection.AppendEntry(pGI);
    }

    // If there's still something left in the collection, render it as well.
    if (s_RenderGeoInstanceCollection.GetNumEntries()!=0)
    {
      if (pLastTechnique && pLastTechnique->GetShaderCount()>0)
      {
        Vision::RenderLoopHelper.RenderStaticGeometryWithShader(s_RenderGeoInstanceCollection, *pLastTechnique->m_Shaders.GetAt(0));
        if (bBasePass)
          s_RenderGeoInstanceCollection.TagEntries();
      } 
      s_RenderGeoInstanceCollection.Clear();
    }
  }

  // Restore default render state
  VisRenderStates_cl::SetDepthStencilState(*VisRenderStates_cl::GetDepthStencilDefaultState());
}
Пример #10
0
void VCoronaManager::RenderCorona (VCoronaCandidate& coronaCandidate, VTextureObject*& pTexture)
{
#ifdef SUPPORTS_CORONAS
  VCoronaComponent *pCorona = coronaCandidate.m_pCorona;
  VisRenderContext_cl* pContext = VisRenderContext_cl::GetCurrentContext();
  VisLightSource_cl* pLight = (VisLightSource_cl*)pCorona->GetOwner();

  hkvVec3 vLightPos(hkvNoInitialization);
  pLight->GetVirtualPosition(vLightPos, pContext);
  hkvVec3 vEyePos(hkvNoInitialization);
  pContext->GetCamera()->GetPosition(vEyePos);
  hkvVec3 vDir = pContext->GetCamera()->GetDirection();

  // Corona texture
  VTextureObject *pTex = pCorona->GetCoronaTexture();
  if (pTex == NULL)
    return;

  if (pTexture != pTex)
  {
    pTexture = pTex;
    Vision::RenderLoopHelper.BindMeshTexture(pTexture,0);
  }

  // Get light color
  VColorRef color = pLight->GetColor();
  hkvVec3 vDist = vLightPos - vEyePos;
  float fEyeDist = vDir.dot(vDist);

  //determine if camera is in light cone if the light is directional
  float fDirectionalDampening = 1.0f;
  if ( pLight->GetType() == VIS_LIGHT_SPOTLIGHT && pCorona->GetOnlyVisibleInSpotLight() )
  {
    fDirectionalDampening = 0.0f;
    float fConeAngle = pLight->GetProjectionAngle();
    float fConeLength = pLight->GetRadius();
    hkvVec3 fConeDirection = pLight->GetDirection();
    fConeDirection.normalize();

    hkvVec3 vLightEyeDist = vEyePos - vLightPos;

    //#2 check if the camera is inside the angle of the cone
    float cosinusAngle = (vLightEyeDist/vLightEyeDist.getLength()).dot(fConeDirection);
    float fDegree = hkvMath::acosDeg(cosinusAngle);
    float normRadius = fDegree / (fConeAngle/2.0f);

    if (normRadius < 1.0f)
    {
      //hardcoded falloff. For better performance, we avoid sampling the projection texture here.
      const float fEpsilon = 64.0f/256.0f;
      const float fQuadFactor = 1.0f/fEpsilon - 1.0f;
      fDirectionalDampening = 1.0f / (1.0f + fQuadFactor*normRadius*normRadius);

      // scale the function so that the value is exactly 0.0 at the edge and 1.0 in the center
      fDirectionalDampening = (fDirectionalDampening - fEpsilon) / (1.0f - fEpsilon);  
    }
  }
  // Fog params
  float fFogDampening = 1.0f;
  if (pLight->GetType() != VIS_LIGHT_DIRECTED && Vision::World.IsLinearDepthFogEnabled())
  {  
    const VFogParameters &fog = Vision::World.GetFogParameters();
    float fFogStart = fog.fDepthStart;
    float fFogEnd = fog.fDepthEnd;

    float fFogFactor = (fFogEnd > fFogStart) ? ((fEyeDist - fFogStart) / (fFogEnd - fFogStart)) : 0.f;
    fFogDampening = 1.0f - hkvMath::clamp(fFogFactor, 0.0f, 1.0f);
  }

  // Get corona rotation
  float fRotation = 0.0f;
  hkvVec4 vRotation(1.0f, 0.0f, 0.0f, 1.0f);
  if (pCorona->CoronaFlags & VIS_CORONASCALE_ROTATING)
  { 
    fRotation = hkvMath::mod (fEyeDist * 0.5f, 360.f);

    vRotation.x = hkvMath::cosDeg (fRotation);
    vRotation.y = -hkvMath::sinDeg (fRotation);
    vRotation.z = -vRotation.y;
    vRotation.w = vRotation.x;
  }

  // Texture dimensions
  int iSizeX, iSizeY, depth;
  pTex->GetTextureDimensions(iSizeX, iSizeY, depth);

  hkvVec4 vScale(0.0f, 0.0f, 0.0f, 0.0f);

  int iMainWidth, iMainHeight, iWidth, iHeight;
  pContext->GetSize(iWidth, iHeight);
  VisRenderContext_cl::GetMainRenderContext()->GetSize(iMainWidth, iMainHeight);

  // Preserve texture aspect ratio
  int iTexHeight = pTex->GetTextureHeight();
  int iTexWidth = pTex->GetTextureWidth();

  // Perspective scaling
  // This scaling ensures roughly the same size on 720p as the old implementation.
  vScale.z = iTexWidth * pCorona->CoronaScaling * 0.25f;
  vScale.w = iTexHeight * pCorona->CoronaScaling * 0.25f;

  // Screen-space scaling
  // This scaling ensures roughly the same size on 720p as the old implementation.
  const float fScaleFactor = pCorona->CoronaScaling * iMainHeight / 11.0f;
  vScale.x = ((float)iTexWidth / 128.0f) * fScaleFactor * (float(iWidth) / float(iMainWidth));
  vScale.y = ((float)iTexHeight / 128.0f) * fScaleFactor * (float(iHeight) / float(iMainHeight));
  vScale.x *= 2.0f / iWidth;
  vScale.y *= 2.0f / iHeight;
  
  // Scale by visibility
  if (pCorona->CoronaFlags & VIS_CORONASCALE_VISIBLEAREA)
  {
    vScale.x *= coronaCandidate.m_fCurrentVisibility;
    vScale.y *= coronaCandidate.m_fCurrentVisibility;
    vScale.z *= coronaCandidate.m_fCurrentVisibility;
    vScale.w *= coronaCandidate.m_fCurrentVisibility;
  }

  VCompiledShaderPass* pShader = m_spCoronaTechnique->GetShader(0);
  VShaderConstantBuffer *pVertexConstBuffer = pShader->GetConstantBuffer(VSS_VertexShader);
  // xyz = worldspace position, w = 1.0 if VIS_CORONASCALE_DISTANCE is true, otherwise zero.
  pVertexConstBuffer->SetSingleParameterF("coronaPosition", vLightPos.x, vLightPos.y, vLightPos.z, (pCorona->CoronaFlags & VIS_CORONASCALE_DISTANCE) ? 1.0f : 0.0f);
  // xyz = light color, w = corona visibility.
  pVertexConstBuffer->SetSingleParameterF("coronaColor", color.r/255.0f, color.g/255.0f, color.b/255.0f, coronaCandidate.m_fCurrentVisibility * fFogDampening * fDirectionalDampening);
  // xyzw = 2x2 rotation matrix. float2x2 is not supported in shader model 2, so a float4 is used and multiplication is done manually in the shader.
  pVertexConstBuffer->SetSingleParameterF("coronaRotation", vRotation.x, vRotation.y, vRotation.z, vRotation.w);
  // xy = screen-space scaling. zw = view-space scaling.
  pVertexConstBuffer->SetSingleParameterF("coronaScale", vScale.x, vScale.y, vScale.z, vScale.w);
    
  Vision::RenderLoopHelper.RenderMeshes(pShader, VisMeshBuffer_cl::MB_PRIMTYPE_TRILIST, 0, 2, 6);
#endif
}
Пример #11
0
void VCoronaManager::RenderAllVisibleCoronas()
{
#ifdef SUPPORTS_CORONAS
  VisRenderContext_cl* pContext = VisRenderContext_cl::GetCurrentContext();

  // Determine relevant render context and visibility collector
  IVisVisibilityCollector_cl *pVisCollector = pContext->GetVisibilityCollector();
  if (!pVisCollector)
    return;
  VisRenderContext_cl *pOQContext = pVisCollector->GetOcclusionQueryRenderContext();
  if (pOQContext != NULL)
    pContext = pOQContext;


  if ((pContext->GetRenderFlags() & VIS_RENDERCONTEXT_FLAG_USE_PIXELCOUNTER) == 0)
    return;

  if ((pContext->GetRenderFlags() & VIS_RENDERCONTEXT_FLAG_RENDER_CORONAS) == 0)
    return;

  INSERT_PERF_MARKER_SCOPE("VCoronaManager::RenderAllVisibleCoronas");
  VISION_PROFILE_FUNCTION(PROFILING_CORONA_RENDER);

  // Force for the queries to finish so they are available in this frame.
  if (m_bTeleportedLastFrame && m_bForceQueryOnTeleport)
  {
    UpdateCoronas(VCUF_UPDATE | VCUF_FORCE_FETCH | VCUF_USE_OC_CONTEXT);
  }

  // Ensure size of corona state structure.
  int iContextIndex = pContext->GetNumber();
  if (iContextIndex + 1 > m_State.GetSize())
    m_State.SetSize(iContextIndex + 1, -1);
  VCoronaRenderContextState& state = m_State[iContextIndex];
  int iCapacity = m_Instances.GetCapacity();
  state.EnsureSize(iCapacity);

  const int iCoronasToRender = state.m_Candidates.GetSize();

  // Sort candidates by texture?
  
  VTextureObject* pTexture = NULL;

  // Render all corona components
  Vision::RenderLoopHelper.BeginMeshRendering();
  Vision::RenderLoopHelper.AddMeshStreams(m_spBillboardMesh,VERTEX_STREAM_POSITION);

  for (int i=0; i < iCoronasToRender; ++i)
  {
    VCoronaCandidate& coronaCandidate = state.m_Candidates.ElementAt(i);
    if (coronaCandidate.m_fCurrentVisibility > 0.0f)
    {
      RenderCorona (coronaCandidate, pTexture);
    }
  }

  Vision::RenderLoopHelper.EndMeshRendering();

  m_bTeleportedLastFrame = (pContext->GetCamera()->GetLastTeleported() >= pContext->GetLastRenderedFrame());
#endif
}
void VFakeSpecularGenerator::OnDoRenderLoop(void *pUserData)
{
  VFrustumMeshHelper::UpdateMeshBuffer(m_spMeshBuffer, Vision::Contexts.GetCurrentContext(), VFrustumMeshHelper::IN_WORLD_SPACE);

  Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_All, VColorRef(0, 0, 0, 0));

  VisRenderContext_cl* pContext = Vision::Contexts.GetCurrentContext();

  const VisLightSrcCollection_cl* pLights = pContext->GetVisibilityCollector()->GetVisibleLights();

  Vision::RenderLoopHelper.BeginMeshRendering();
  Vision::RenderLoopHelper.ResetMeshStreams();
  Vision::RenderLoopHelper.AddMeshStreams(m_spMeshBuffer, m_spShader->GetStreamMask () | VERTEX_STREAM_INDEXBUFFER);
  for(unsigned int iLightIndex = 0; iLightIndex < pLights->GetNumEntries(); iLightIndex++)
  {
    VisLightSource_cl* pLight = pLights->GetEntry(iLightIndex);

    if((pLight->GetVisibleBitmask() & pContext->GetRenderFilterMask()) == 0)
      continue;

    if(!pLight->GetUseSpecular())
      continue;

    hkvVec4 vDirection;

    hkvVec3 vLightPositionRel = pLight->GetPosition() - pContext->GetCamera()->GetPosition();
    hkvVec3 vLightDirection = pLight->GetDirection();

    float fAttenuation = 1;
    switch(pLight->GetType())
    {
    case VIS_LIGHT_DIRECTED:
      vDirection = vLightDirection.getAsVec4(1.0f);
      break;

    case VIS_LIGHT_SPOTLIGHT:
      {
        vDirection = vLightDirection.getAsVec4(1.0f);

        float fAngle = vLightPositionRel.getAngleBetween(-vLightDirection);
        float fConeAngle = pLight->GetProjectionAngle();
        fAttenuation = hkvMath::clamp((fConeAngle - fAngle) / fConeAngle, 0.0f, 1.0f);

        float fDistance = vLightPositionRel.getLength();
        float fRadius = pLight->GetRadius();
        fAttenuation *= hkvMath::clamp((fRadius - fDistance) / fRadius, 0.0f, 1.0f);
      }
      break;

    case VIS_LIGHT_POINT:
      vDirection = (-vLightPositionRel).getNormalized().getAsVec4(1.0f);
      float fDistance = vLightPositionRel.getLength();
      float fRadius = pLight->GetRadius();
      fAttenuation = hkvMath::clamp((fRadius - fDistance) / fRadius, 0.0f, 1.0f);
      break;
    }

    hkvVec4 vColor = pLight->GetColor().getAsVec4() * pLight->GetMultiplier() * fAttenuation;

    hkvVec4 vParams(m_fSpecularPower, 0, 0, 0);

    m_spShader->GetConstantBuffer(VSS_PixelShader)->SetSingleParameterF("fLightDirection", vDirection.data);
    m_spShader->GetConstantBuffer(VSS_PixelShader)->SetSingleParameterF("fLightColor", vColor.data);
    m_spShader->GetConstantBuffer(VSS_PixelShader)->SetSingleParameterF("fParams", vParams.data);

    Vision::RenderLoopHelper.RenderMeshes(m_spShader, VisMeshBuffer_cl::MB_PRIMTYPE_INDEXED_TRILIST, 0, 2, 6);
  }
  Vision::RenderLoopHelper.EndMeshRendering();

  // Trigger pre-screenmask render hook to make the attached cubemap handle flip and blur the cubemap target
  VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook, VRH_PRE_SCREENMASKS);
  Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data);
}