Exemplo n.º 1
0
void CloudLayer::renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mi )
{
   GFXTransformSaver saver;

   const Point3F &camPos = state->getCameraPosition();
   MatrixF xfm(true);
   xfm.setPosition(camPos);
   GFX->multWorld(xfm);   

   if ( state->isReflectPass() )
      GFX->setProjectionMatrix( state->getSceneManager()->getNonClipProjection() );

   GFX->setShader( mShader );
   GFX->setShaderConstBuffer( mShaderConsts );
   GFX->setStateBlock( mStateblock );

   // Set all the shader consts...

   MatrixF xform(GFX->getProjectionMatrix());
   xform *= GFX->getViewMatrix();
   xform *= GFX->getWorldMatrix();

   mShaderConsts->setSafe( mModelViewProjSC, xform );

   mShaderConsts->setSafe( mEyePosWorldSC, camPos );

   LightInfo *lightinfo = LIGHTMGR->getSpecialLight(LightManager::slSunLightType);
   const ColorF &sunlight = state->getAmbientLightColor();

   Point3F ambientColor( sunlight.red, sunlight.green, sunlight.blue );
   mShaderConsts->setSafe( mAmbientColorSC, ambientColor );   

   const ColorF &sunColor = lightinfo->getColor();
   Point3F data( sunColor.red, sunColor.green, sunColor.blue );
   mShaderConsts->setSafe( mSunColorSC, data );

   mShaderConsts->setSafe( mSunVecSC, lightinfo->getDirection() );

   for ( U32 i = 0; i < TEX_COUNT; i++ )         
      mShaderConsts->setSafe( mTexOffsetSC[i], mTexOffset[i] );

   Point3F scale( mTexScale[0], mTexScale[1], mTexScale[2] );
   mShaderConsts->setSafe( mTexScaleSC, scale );

   Point3F color;
   color.set( mBaseColor.red, mBaseColor.green, mBaseColor.blue );
   mShaderConsts->setSafe( mBaseColorSC, color );

   mShaderConsts->setSafe( mCoverageSC, mCoverage );

   mShaderConsts->setSafe( mExposureSC, mExposure );

   GFX->setTexture( mNormalHeightMapSC->getSamplerRegister(), mTexture );                            
   GFX->setVertexBuffer( mVB );            
   GFX->setPrimitiveBuffer( mPB );

   GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, smVertCount, 0, smTriangleCount );
}
void AdvancedLightBinManager::render( SceneRenderState *state )
{
   PROFILE_SCOPE( AdvancedLightManager_Render );

   // Take a look at the SceneRenderState and see if we should skip drawing the pre-pass
   if( state->disableAdvancedLightingBins() )
      return;

   // Automagically save & restore our viewport and transforms.
   GFXTransformSaver saver;

   if( !mLightManager )
      return;

   // Get the sunlight. If there's no sun, and no lights in the bins, no draw
   LightInfo *sunLight = mLightManager->getSpecialLight( LightManager::slSunLightType );
   if( !sunLight && mLightBin.empty() )
      return;

   GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render, ColorI::RED );

   // Tell the superclass we're about to render
   if ( !_onPreRender( state ) )
      return;

   // Clear as long as there isn't MRT population of light buffer with lightmap data
   if ( !MRTLightmapsDuringPrePass() )
      GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);

   // Restore transforms
   MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
   matrixSet.restoreSceneViewProjection();

   const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();

   // Set up the SG Data
   SceneData sgData;
   sgData.init( state );

   // There are cases where shadow rendering is disabled.
   const bool disableShadows = state->isReflectPass() || ShadowMapPass::smDisableShadows;

   // Pick the right material for rendering the sunlight... we only
   // cast shadows when its enabled and we're not in a reflection.
   LightMaterialInfo *vectorMatInfo;
   if (  sunLight &&
         sunLight->getCastShadows() &&
         !disableShadows &&
         sunLight->getExtended<ShadowMapParams>() )
      vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_PSSM, false );
   else
      vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_None, false );

   // Initialize and set the per-frame parameters after getting
   // the vector light material as we use lazy creation.
   _setupPerFrameParameters( state );
   
   // Draw sunlight/ambient
   if ( sunLight && vectorMatInfo )
   {
      GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render_Sunlight, ColorI::RED );

      // Set up SG data
      setupSGData( sgData, state, sunLight );
      vectorMatInfo->setLightParameters( sunLight, state, worldToCameraXfm );

      // Set light holds the active shadow map.       
      mShadowManager->setLightShadowMapForLight( sunLight );

      // Set geometry
      GFX->setVertexBuffer( mFarFrustumQuadVerts );
      GFX->setPrimitiveBuffer( NULL );

      // Render the material passes
      while( vectorMatInfo->matInstance->setupPass( state, sgData ) )
      {
         vectorMatInfo->matInstance->setSceneInfo( state, sgData );
         vectorMatInfo->matInstance->setTransforms( matrixSet, state );
         GFX->drawPrimitive( GFXTriangleFan, 0, 2 );
      }
   }

   // Blend the lights in the bin to the light buffer
   for( LightBinIterator itr = mLightBin.begin(); itr != mLightBin.end(); itr++ )
   {
      LightBinEntry& curEntry = *itr;
      LightInfo *curLightInfo = curEntry.lightInfo;
      LightMaterialInfo *curLightMat = curEntry.lightMaterial;
      const U32 numPrims = curEntry.numPrims;
      const U32 numVerts = curEntry.vertBuffer->mNumVerts;

      // Skip lights which won't affect the scene.
      if ( !curLightMat || curLightInfo->getBrightness() <= 0.001f )
         continue;

      GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render_Light, ColorI::RED );

      setupSGData( sgData, state, curLightInfo );
      curLightMat->setLightParameters( curLightInfo, state, worldToCameraXfm );
      mShadowManager->setLightShadowMap( curEntry.shadowMap );

      // Let the shadow know we're about to render from it.
      if ( curEntry.shadowMap )
         curEntry.shadowMap->preLightRender();

      // Set geometry
      GFX->setVertexBuffer( curEntry.vertBuffer );
      GFX->setPrimitiveBuffer( curEntry.primBuffer );

      // Render the material passes
      while( curLightMat->matInstance->setupPass( state, sgData ) )
      {
         // Set transforms
         matrixSet.setWorld(*sgData.objTrans);
         curLightMat->matInstance->setTransforms(matrixSet, state);
         curLightMat->matInstance->setSceneInfo(state, sgData);

         if(curEntry.primBuffer)
            GFX->drawIndexedPrimitive(GFXTriangleList, 0, 0, numVerts, 0, numPrims);
         else
            GFX->drawPrimitive(GFXTriangleList, 0, numPrims);
      }

      // Tell it we're done rendering.
      if ( curEntry.shadowMap )
         curEntry.shadowMap->postLightRender();
   }

   // Set NULL for active shadow map (so nothing gets confused)
   mShadowManager->setLightShadowMap(NULL);
   GFX->setVertexBuffer( NULL );
   GFX->setPrimitiveBuffer( NULL );

   // Fire off a signal to let others know that light-bin rendering is ending now
   getRenderSignal().trigger(state, this);

   // Finish up the rendering
   _onPostRender();
}
Exemplo n.º 3
0
void WaterObject::setShaderParams( SceneRenderState *state, BaseMatInstance *mat, const WaterMatParams &paramHandles )
{
   MaterialParameters* matParams = mat->getMaterialParameters();

   matParams->setSafe( paramHandles.mElapsedTimeSC, (F32)Sim::getCurrentTime() / 1000.0f );
   
   // set vertex shader constants
   //-----------------------------------   
   
   Point2F reflectTexSize( mPlaneReflector.reflectTex.getWidth(), mPlaneReflector.reflectTex.getHeight() );
   matParams->setSafe( paramHandles.mReflectTexSizeSC, reflectTexSize );

   static AlignedArray<Point2F> mConstArray( MAX_WAVES, sizeof( Point4F ) );   

   // Ripples...

   for ( U32 i = 0; i < MAX_WAVES; i++ )
      mConstArray[i].set( -mRippleDir[i].x, -mRippleDir[i].y );
   matParams->setSafe( paramHandles.mRippleDirSC, mConstArray );

   Point3F rippleSpeed( mRippleSpeed[0], mRippleSpeed[1], mRippleSpeed[2] );        
   matParams->setSafe( paramHandles.mRippleSpeedSC, rippleSpeed );

   Point4F rippleMagnitude( mRippleMagnitude[0], 
                            mRippleMagnitude[1], 
                            mRippleMagnitude[2],
                            mOverallRippleMagnitude );
   matParams->setSafe( paramHandles.mRippleMagnitudeSC, rippleMagnitude );

   for ( U32 i = 0; i < MAX_WAVES; i++ )
   {
      Point2F texScale = mRippleTexScale[i];
      if ( texScale.x > 0.0 )
         texScale.x = 1.0 / texScale.x;
      if ( texScale.y > 0.0 )
         texScale.y = 1.0 / texScale.y;

      mConstArray[i].set( texScale.x, texScale.y );
   }
   matParams->setSafe(paramHandles.mRippleTexScaleSC, mConstArray);

   static AlignedArray<Point4F> mConstArray4F( 3, sizeof( Point4F ) );

   F32 angle, cosine, sine;

   for ( U32 i = 0; i < MAX_WAVES; i++ )
   {
      angle = mAtan2( mRippleDir[i].x, -mRippleDir[i].y );
      cosine = mCos( angle );
      sine = mSin( angle );

      mConstArray4F[i].set( cosine, sine, -sine, cosine );
      matParams->setSafe( paramHandles.mRippleMatSC, mConstArray4F );
   }

   // Waves...

   for ( U32 i = 0; i < MAX_WAVES; i++ )
      mConstArray[i].set( -mWaveDir[i].x, -mWaveDir[i].y );
   matParams->setSafe( paramHandles.mWaveDirSC, mConstArray );

   for ( U32 i = 0; i < MAX_WAVES; i++ )
      mConstArray[i].set( mWaveSpeed[i], mWaveMagnitude[i] * mOverallWaveMagnitude );   
   matParams->setSafe( paramHandles.mWaveDataSC, mConstArray );   

   // Foam...

   Point4F foamDir( mFoamDir[0].x, mFoamDir[0].y, mFoamDir[1].x, mFoamDir[1].y );
   matParams->setSafe( paramHandles.mFoamDirSC, foamDir );

   Point2F foamSpeed( mFoamSpeed[0], mFoamSpeed[1] );        
   matParams->setSafe( paramHandles.mFoamSpeedSC, foamSpeed );

   //Point3F rippleMagnitude( mRippleMagnitude[0] * mOverallRippleMagnitude, 
   //                         mRippleMagnitude[1] * mOverallRippleMagnitude, 
   //                         mRippleMagnitude[2] * mOverallRippleMagnitude );
   //matParams->setSafe( paramHandles.mRippleMagnitudeSC, rippleMagnitude );

   Point4F foamTexScale( mFoamTexScale[0].x, mFoamTexScale[0].y, mFoamTexScale[1].x, mFoamTexScale[1].y );

   for ( U32 i = 0; i < 4; i++ )
   {
      if ( foamTexScale[i] > 0.0f )
         foamTexScale[i] = 1.0 / foamTexScale[i];      
   }

   matParams->setSafe(paramHandles.mFoamTexScaleSC, foamTexScale);

   // Other vert params...

   matParams->setSafe( paramHandles.mUndulateMaxDistSC, mUndulateMaxDist );

   // set pixel shader constants
   //-----------------------------------

   Point2F fogParams( mWaterFogData.density, mWaterFogData.densityOffset );
   matParams->setSafe(paramHandles.mFogParamsSC, fogParams );

   matParams->setSafe(paramHandles.mFarPlaneDistSC, (F32)state->getFarPlane() );

   Point2F wetnessParams( mWaterFogData.wetDepth, mWaterFogData.wetDarkening );
   matParams->setSafe(paramHandles.mWetnessParamsSC, wetnessParams );

   Point3F distortionParams( mDistortStartDist, mDistortEndDist, mDistortFullDepth );
   matParams->setSafe(paramHandles.mDistortionParamsSC, distortionParams );

   LightInfo *sun = LIGHTMGR->getSpecialLight(LightManager::slSunLightType);
   const ColorF &sunlight = state->getAmbientLightColor();
   Point3F ambientColor = mEmissive ? Point3F::One : sunlight;
   matParams->setSafe(paramHandles.mAmbientColorSC, ambientColor );
   matParams->setSafe(paramHandles.mLightDirSC, sun->getDirection() );

   Point4F foamParams( mOverallFoamOpacity, mFoamMaxDepth, mFoamAmbientLerp, mFoamRippleInfluence );
   matParams->setSafe(paramHandles.mFoamParamsSC, foamParams );   

   Point4F miscParams( mFresnelBias, mFresnelPower, mClarity, mMiscParamW );
   matParams->setSafe( paramHandles.mMiscParamsSC, miscParams );
   
   Point4F specularParams( mSpecularColor.red, mSpecularColor.green, mSpecularColor.blue, mSpecularPower );   
   if ( !mEmissive )
   {
      const ColorF &sunColor = sun->getColor();
      F32 brightness = sun->getBrightness();
      specularParams.x *= sunColor.red * brightness;
      specularParams.y *= sunColor.green * brightness;
      specularParams.z *= sunColor.blue * brightness;
   }
   matParams->setSafe( paramHandles.mSpecularParamsSC, specularParams );

   matParams->setSafe( paramHandles.mDepthGradMaxSC, mDepthGradientMax );

   matParams->setSafe( paramHandles.mReflectivitySC, mReflectivity );
}
Exemplo n.º 4
0
    void testLightInfo( void ) {
		//test LightInfo functionality
		Meshdata md;
		
		Node ned;
		ned.parent = NullNodeIndex;
		md.nodes.push_back(ned);
		md.rootNodes.push_back(0);

		LightInstance li;
		li.lightIndex = 0;
		li.parentNode = 0;
		
		//LightInfo
		LightInfo info;

		info.setCastsShadow(true);
		info.setLightAmbientColor(Vector3f(100, 234, 234));
		info.setLightDiffuseColor(Vector3f(5, 78, 186));

		info.setLightFalloff(32, 65, 23);
		info.setLightPower(4);
		info.setLightRange(100);

		info.setLightShadowColor(Vector3f(67, 45, 23));
		info.setLightSpecularColor(Vector3f(32, 54, 76));

		info.setLightSpotlightCone(2, 4, 3);
		info.setLightType(LightInfo::SPOTLIGHT);

		md.lightInstances.push_back(li);
		md.lights.push_back(info);

		//LightInstanceIterator
		LightInstanceIterator lithium = md.getLightInstanceIterator();
		uint32 u;
		Matrix4x4f m;
		
		//successes
		bool success = lithium.next(&u, &m);
        TS_ASSERT_EQUALS(success, true);
		TS_ASSERT_EQUALS(u, 0);

		TS_ASSERT_EQUALS(md.lights[0].mCastsShadow, true);
		vAssert(md.lights[0].mAmbientColor, Vector3f(100, 234, 234));
		vAssert(md.lights[0].mDiffuseColor, Vector3f(5, 78, 186));

		TS_ASSERT_EQUALS(md.lights[0].mConstantFalloff, 32);
		TS_ASSERT_EQUALS(md.lights[0].mLinearFalloff, 65);
		TS_ASSERT_EQUALS(md.lights[0].mQuadraticFalloff, 23);
		TS_ASSERT_EQUALS(md.lights[0].mPower, 4);
		TS_ASSERT_EQUALS(md.lights[0].mLightRange, 100);

		vAssert(md.lights[0].mShadowColor, Vector3f(67, 45, 23));
		vAssert(md.lights[0].mSpecularColor, Vector3f(32, 54, 76));

		TS_ASSERT_EQUALS(md.lights[0].mConeInnerRadians, 2);
		TS_ASSERT_EQUALS(md.lights[0].mConeOuterRadians, 4);
		TS_ASSERT_EQUALS(md.lights[0].mConeFalloff, 3);
		TS_ASSERT_EQUALS(md.lights[0].mType, LightInfo::SPOTLIGHT);
    }
Exemplo n.º 5
0
void LightFlareData::prepRender( SceneState *state, LightFlareState *flareState )
{    
   PROFILE_SCOPE( LightFlareData_prepRender );

   // No elements then nothing to render.
   if ( mElementCount == 0 )
      return;

   // We need these all over the place later.
   const Point3F &camPos = state->getCameraPosition();
   const RectI &viewport = GFX->getViewport();
   const Point3F &lightPos = flareState->lightMat.getPosition();
   LightInfo *lightInfo = flareState->lightInfo;

   bool isVectorLight = lightInfo->getType() == LightInfo::Vector;

   // Perform visibility testing on the light...
   // Project the light position from world to screen space, we need this
   // position later, and it tells us if it is actually onscreen.   
   
   Point3F lightPosSS;
   bool onscreen = MathUtils::mProjectWorldToScreen( lightPos, &lightPosSS, viewport, GFX->getWorldMatrix(), gClientSceneGraph->getNonClipProjection() );  

   U32 visDelta = U32_MAX;
   U32 fadeOutTime = 20;
   U32 fadeInTime = 125;    

   // Fade factor based on amount of occlusion.
   F32 occlusionFade = 1.0f;

   bool lightVisible = true;
   
   if ( !state->isReflectPass() )
   {
      // It is onscreen, so raycast as a simple occlusion test.

      U32 losMask =	STATIC_COLLISION_MASK |
                     ShapeBaseObjectType |
                     StaticTSObjectType |
                     ItemObjectType |
                     PlayerObjectType;

      GameConnection *conn = GameConnection::getConnectionToServer();
      if ( !conn )
         return;

      bool needsRaycast = true;

      // NOTE: if hardware does not support HOQ it will return NULL
      // and we will retry every time but there is not currently a good place
      // for one-shot initialization of LightFlareState
      if ( flareState->occlusionQuery == NULL )
         flareState->occlusionQuery = GFX->createOcclusionQuery();
      if ( flareState->fullPixelQuery == NULL )
         flareState->fullPixelQuery = GFX->createOcclusionQuery();

      if ( flareState->occlusionQuery && 
           ( ( isVectorLight && flareState->worldRadius > 0.0f ) || 
             ( !isVectorLight && mOcclusionRadius > 0.0f ) ) )
      {
         // Always treat light as onscreen if using HOQ
         // it will be faded out if offscreen anyway.
         onscreen = true;

         U32 pixels = -1;
         GFXOcclusionQuery::OcclusionQueryStatus status = flareState->occlusionQuery->getStatus( true, &pixels );

         String str = flareState->occlusionQuery->statusToString( status );
         Con::setVariable( "$Flare::OcclusionStatus", str.c_str() );
         Con::setIntVariable( "$Flare::OcclusionVal", pixels );
         
         if ( status == GFXOcclusionQuery::Occluded )
            occlusionFade = 0.0f;

         if ( status != GFXOcclusionQuery::Unset )         
            needsRaycast = false;

         RenderPassManager *pass = state->getRenderPass();

         OccluderRenderInst *ri = pass->allocInst<OccluderRenderInst>();   

         Point3F scale( Point3F::One );

         if ( isVectorLight && flareState->worldRadius > 0.0f )         
            scale *= flareState->worldRadius;
         else
            scale *= mOcclusionRadius;
         
         ri->type = RenderPassManager::RIT_Occluder;
         ri->query = flareState->occlusionQuery;   
         ri->query2 = flareState->fullPixelQuery;
         ri->position = lightPos;
         ri->scale = scale;
         ri->orientation = pass->allocUniqueXform( lightInfo->getTransform() );         
         ri->isSphere = true;
         state->getRenderPass()->addInst( ri );

         if ( status == GFXOcclusionQuery::NotOccluded )
         {
            U32 fullPixels;
            flareState->fullPixelQuery->getStatus( true, &fullPixels );

            occlusionFade = (F32)pixels / (F32)fullPixels;

            // Approximation of the full pixel count rather than doing
            // two queries, but it is not very accurate.
            /*
            F32 dist = ( camPos - lightPos ).len();
            F32 radius = scale.x;
            radius = ( radius / dist ) * state->getWorldToScreenScale().y;

            occlusionFade = (F32)pixels / (4.0f * radius * radius);
            occlusionFade = mClampF( occlusionFade, 0.0f, 1.0f );            
            */
         }
      }

      Con::setFloatVariable( "$Flare::OcclusionFade", occlusionFade );

      if ( needsRaycast )
      {
         // Use a raycast to determine occlusion.

         bool fps = conn->isFirstPerson();

         GameBase *control = conn->getControlObject();
         if ( control && fps )
            control->disableCollision();

         RayInfo rayInfo;

         if ( gClientContainer.castRayRendered( camPos, lightPos, losMask, &rayInfo ) )
            occlusionFade = 0.0f;

         if ( control && fps )
            control->enableCollision();
      }

      lightVisible = onscreen && occlusionFade > 0.0f;

      // To perform a fade in/out when we gain or lose visibility
      // we must update/store the visibility state and time.

      U32 currentTime = Sim::getCurrentTime();

      if ( lightVisible != flareState->visible )
      {
         flareState->visible = lightVisible;
         flareState->visChangedTime = currentTime;
      }      

      // Save this in the state so that we have it during the reflect pass.
      flareState->occlusion = occlusionFade;

      visDelta = currentTime - flareState->visChangedTime;      
   }
   else // state->isReflectPass()
   {
      occlusionFade = flareState->occlusion;
      lightVisible = flareState->visible;
      visDelta = Sim::getCurrentTime() - flareState->visChangedTime;
   }

   // We can only skip rendering if the light is not visible, and it
   // has elapsed the fadeOutTime.
   if ( !lightVisible && visDelta > fadeOutTime )
      return;

   // In a reflection we only render the elements with zero distance.   
   U32 elementCount = mElementCount;
   if ( state->isReflectPass()  )
   {
      elementCount = 0;
      for ( ; elementCount < mElementCount; elementCount++ )
      {
         if ( mElementDist[elementCount] > 0.0f )
            break;
      }
   }

   if ( elementCount == 0 )
      return;

   // A bunch of preparatory math before generating verts...

   const Point2I &vpExtent = viewport.extent;
   Point3F viewportExtent( vpExtent.x, vpExtent.y, 1.0f );
   Point2I halfViewportExtentI( viewport.extent / 2 );
   Point3F halfViewportExtentF( (F32)halfViewportExtentI.x * 0.5f, (F32)halfViewportExtentI.y, 0.0f );
   Point3F screenCenter( 0,0,0 );
   Point3F oneOverViewportExtent( 1.0f / viewportExtent.x, 1.0f / viewportExtent.y, 1.0f );

   lightPosSS.y -= viewport.point.y;
   lightPosSS *= oneOverViewportExtent;
   lightPosSS = ( lightPosSS * 2.0f ) - Point3F::One;
   lightPosSS.y = -lightPosSS.y;
   lightPosSS.z = 0.0f;

   Point3F flareVec( screenCenter - lightPosSS );
   F32 flareLength = flareVec.len();   
   flareVec.normalizeSafe();

   Point3F basePoints[4];
   basePoints[0] = Point3F( -0.5, 0.5, 0.0 );  
   basePoints[1] = Point3F( -0.5, -0.5, 0.0 );   
   basePoints[2] = Point3F( 0.5, -0.5, 0.0 );   
   basePoints[3] = Point3F( 0.5, 0.5, 0.0 );

   Point3F rotatedBasePoints[4];
   rotatedBasePoints[0] = basePoints[0];
   rotatedBasePoints[1] = basePoints[1];
   rotatedBasePoints[2] = basePoints[2];
   rotatedBasePoints[3] = basePoints[3];

   Point3F fvec( -1, 0, 0 );   
   F32 rot = mAcos( mDot( fvec, flareVec ) );
   Point3F rvec( 0, -1, 0 );
   rot *= mDot( rvec, flareVec ) > 0.0f ? 1.0f : -1.0f;

   vectorRotateZAxis( rotatedBasePoints[0], rot );
   vectorRotateZAxis( rotatedBasePoints[1], rot );
   vectorRotateZAxis( rotatedBasePoints[2], rot );
   vectorRotateZAxis( rotatedBasePoints[3], rot );

   // Here we calculate a the light source's influence on the effect's size
   // and brightness...

   // Scale based on the current light brightness compared to its normal output.
   F32 lightSourceBrightnessScale = lightInfo->getBrightness() / flareState->fullBrightness;
   // Scale based on world space distance from camera to light source.
   F32 lightSourceWSDistanceScale = ( isVectorLight ) ? 1.0f : getMin( 10.0f / ( lightPos - camPos ).len(), 1.5f );   
   // Scale based on screen space distance from screen position of light source to the screen center.
   F32 lightSourceSSDistanceScale = ( 1.5f - ( lightPosSS - screenCenter ).len() ) / 1.5f;

   // Scale based on recent visibility changes, fading in or out.
   F32 fadeInOutScale = 1.0f;
   if ( lightVisible && visDelta < fadeInTime && flareState->occlusion )
      fadeInOutScale = (F32)visDelta / (F32)fadeInTime;
   else if ( !lightVisible && visDelta < fadeOutTime )
      fadeInOutScale = 1.0f - (F32)visDelta / (F32)fadeOutTime;

   // This combined scale influences the size of all elements this effect renders.
   // Note we also add in a scale that is user specified in the Light.
   F32 lightSourceIntensityScale = lightSourceBrightnessScale * 
                                   lightSourceWSDistanceScale * 
                                   lightSourceSSDistanceScale * 
                                   fadeInOutScale * 
                                   flareState->scale *
                                   occlusionFade;

   // The baseColor which modulates the color of all elements.
   ColorF baseColor;
   if ( flareState->fullBrightness == 0.0f )
      baseColor = ColorF::BLACK;
   else
      // These are the factors which affect the "alpha" of the flare effect.
      // Modulate more in as appropriate.
      baseColor = ColorF::WHITE * lightSourceBrightnessScale * occlusionFade;

   // Fill in the vertex buffer...
   const U32 vertCount = 4 * elementCount;
   if (  flareState->vertBuffer.isNull() || 
         flareState->vertBuffer->mNumVerts != vertCount )
         flareState->vertBuffer.set( GFX, vertCount, GFXBufferTypeDynamic );

   GFXVertexPCT *pVert = flareState->vertBuffer.lock();

   const Point2I &widthHeightI = mFlareTexture.getWidthHeight();
   Point2F oneOverTexSize( 1.0f / (F32)widthHeightI.x, 1.0f / (F32)widthHeightI.y );

   for ( U32 i = 0; i < elementCount; i++ )
   {      
      Point3F *basePos = mElementRotate[i] ? rotatedBasePoints : basePoints;

      ColorF elementColor( baseColor * mElementTint[i] );
      if ( mElementUseLightColor[i] )
         elementColor *= lightInfo->getColor();

      Point3F elementPos;
      elementPos = lightPosSS + flareVec * mElementDist[i] * flareLength;      
      elementPos.z = 0.0f;

      F32 maxDist = 1.5f;
      F32 elementDist = mSqrt( ( elementPos.x * elementPos.x ) + ( elementPos.y * elementPos.y ) );
      F32 distanceScale = ( maxDist - elementDist ) / maxDist;
      distanceScale = 1.0f;

      const RectF &elementRect = mElementRect[i];
      Point3F elementSize( elementRect.extent.x, elementRect.extent.y, 1.0f );
      elementSize *= mElementScale[i] * distanceScale * mScale * lightSourceIntensityScale;

      if ( elementSize.x < 100.0f )
      {
         F32 alphaScale = mPow( elementSize.x / 100.0f, 2 );
         elementColor *= alphaScale;
      }

      elementColor.clamp();

      Point2F texCoordMin, texCoordMax;
      texCoordMin = elementRect.point * oneOverTexSize;
      texCoordMax = ( elementRect.point + elementRect.extent ) * oneOverTexSize;          

      pVert->color = elementColor;
      pVert->point = ( basePos[0] * elementSize * oneOverViewportExtent ) + elementPos;      
      pVert->texCoord.set( texCoordMin.x, texCoordMax.y );
      pVert++;

      pVert->color = elementColor;
      pVert->point = ( basePos[1] * elementSize * oneOverViewportExtent ) + elementPos;
      pVert->texCoord.set( texCoordMax.x, texCoordMax.y );
      pVert++;

      pVert->color = elementColor;
      pVert->point = ( basePos[2] * elementSize * oneOverViewportExtent ) + elementPos;
      pVert->texCoord.set( texCoordMax.x, texCoordMin.y );
      pVert++;

      pVert->color = elementColor;
      pVert->point = ( basePos[3] * elementSize * oneOverViewportExtent ) + elementPos;
      pVert->texCoord.set( texCoordMin.x, texCoordMin.y );
      pVert++;
   }   

   flareState->vertBuffer.unlock();   

   // Create and submit the render instance...
   
   RenderPassManager *renderManager = state->getRenderPass();
   ParticleRenderInst *ri = renderManager->allocInst<ParticleRenderInst>();

   ri->vertBuff = &flareState->vertBuffer;
   ri->primBuff = &mFlarePrimBuffer;
   ri->translucentSort = true;
   ri->type = RenderPassManager::RIT_Particle;
   ri->sortDistSq = ( lightPos - camPos ).lenSquared();

   ri->modelViewProj = &MatrixF::Identity;
   ri->bbModelViewProj = ri->modelViewProj;

   ri->count = elementCount;

   // Only draw the light flare in high-res mode, never off-screen mode
   ri->systemState = ParticleRenderInst::AwaitingHighResDraw;

   ri->blendStyle = ParticleRenderInst::BlendGreyscale;

   ri->diffuseTex = &*(mFlareTexture);

   ri->softnessDistance = 1.0f; 

   // Sort by texture too.
   ri->defaultKey = ri->diffuseTex ? (U32)ri->diffuseTex : (U32)ri->vertBuff;

   renderManager->addInst( ri );
}
Exemplo n.º 6
0
void AdvancedLightManager::setLightInfo(  ProcessedMaterial *pmat, 
                                          const Material *mat, 
                                          const SceneData &sgData,
                                          const SceneRenderState *state,
                                          U32 pass, 
                                          GFXShaderConstBuffer *shaderConsts)
{
   // Skip this if we're rendering from the prepass bin.
   if ( sgData.binType == SceneData::PrePassBin )
      return;

   PROFILE_SCOPE(AdvancedLightManager_setLightInfo);

   LightingShaderConstants *lsc = getLightingShaderConstants(shaderConsts);

   LightShadowMap *lsm = SHADOWMGR->getCurrentShadowMap();

   LightInfo *light;
   if ( lsm )
      light = lsm->getLightInfo();
   else
   {
      light = sgData.lights[0];
      if ( !light )
         light = getDefaultLight();
   }

   // NOTE: If you encounter a crash from this point forward
   // while setting a shader constant its probably because the
   // mConstantLookup has bad shaders/constants in it.
   //
   // This is a known crash bug that can occur if materials/shaders
   // are reloaded and the light manager is not reset.
   //
   // We should look to fix this by clearing the table.

   // Update the forward shading light constants.
   _update4LightConsts( sgData,
                        lsc->mLightPositionSC,
                        lsc->mLightDiffuseSC,
                        lsc->mLightAmbientSC,
                        lsc->mLightInvRadiusSqSC,
                        lsc->mLightSpotDirSC,
                        lsc->mLightSpotAngleSC,
						lsc->mLightSpotFalloffSC,
                        shaderConsts );

   if ( lsm && light->getCastShadows() )
   {
      if (  lsc->mWorldToLightProjSC->isValid() )
         shaderConsts->set(   lsc->mWorldToLightProjSC, 
                              lsm->getWorldToLightProj(), 
                              lsc->mWorldToLightProjSC->getType() );

      if (  lsc->mViewToLightProjSC->isValid() )
      {
         // TODO: Should probably cache these results and 
         // not do this mul here on every material that needs
         // this transform.

         shaderConsts->set(   lsc->mViewToLightProjSC, 
                              lsm->getWorldToLightProj() * state->getCameraTransform(), 
                              lsc->mViewToLightProjSC->getType() );
      }

      shaderConsts->setSafe( lsc->mShadowMapSizeSC, 1.0f / (F32)lsm->getTexSize() );

      // Do this last so that overrides can properly override parameters previously set
      lsm->setShaderParameters(shaderConsts, lsc);
   }
   else
   {
      if ( lsc->mViewToLightProjSC->isValid() )
      {
         // TODO: Should probably cache these results and 
         // not do this mul here on every material that needs
         // this transform.
         MatrixF proj;
         light->getWorldToLightProj( &proj );

         shaderConsts->set(   lsc->mViewToLightProjSC, 
                              proj * state->getCameraTransform(), 
                              lsc->mViewToLightProjSC->getType() );
      }
   }
}