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(); }
void WaterObject::setShaderParams( SceneRenderState *state, BaseMatInstance *mat, const WaterMatParams ¶mHandles ) { 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 ); }
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); }
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 ); }
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() ); } } }