void ProcessedShaderMaterial::setSceneInfo(SceneRenderState * state, const SceneData& sgData, U32 pass) { PROFILE_SCOPE( ProcessedShaderMaterial_setSceneInfo ); GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass); ShaderConstHandles* handles = _getShaderConstHandles(pass); // Set cubemap stuff here (it's convenient!) const Point3F &eyePosWorld = state->getCameraPosition(); if ( handles->mCubeEyePosSC->isValid() ) { if(_hasCubemap(pass) || mMaterial->mDynamicCubemap) { Point3F cubeEyePos = eyePosWorld - sgData.objTrans->getPosition(); shaderConsts->set(handles->mCubeEyePosSC, cubeEyePos); } } shaderConsts->setSafe(handles->mVisiblitySC, sgData.visibility); shaderConsts->setSafe(handles->mEyePosWorldSC, eyePosWorld); if ( handles->mEyePosSC->isValid() ) { MatrixF tempMat( *sgData.objTrans ); tempMat.inverse(); Point3F eyepos; tempMat.mulP( eyePosWorld, &eyepos ); shaderConsts->set(handles->mEyePosSC, eyepos); } shaderConsts->setSafe(handles->mEyeMatSC, state->getCameraTransform()); ShaderRenderPassData *rpd = _getRPD( pass ); for ( U32 i=0; i < rpd->featureShaderHandles.size(); i++ ) rpd->featureShaderHandles[i]->setConsts( state, sgData, shaderConsts ); LIGHTMGR->setLightInfo( this, mMaterial, sgData, state, pass, shaderConsts ); }
bool ProcessedCustomMaterial::setupPass( SceneRenderState *state, const SceneData& sgData, U32 pass ) { PROFILE_SCOPE( ProcessedCustomMaterial_SetupPass ); // Make sure we have a pass. if ( pass >= mPasses.size() ) return false; ShaderRenderPassData* rpd = _getRPD( pass ); U32 currState = _getRenderStateIndex( state, sgData ); GFX->setStateBlock(rpd->mRenderStates[currState]); // activate shader if ( rpd->shader ) GFX->setShader( rpd->shader ); else GFX->disableShaders(); // Set our textures setTextureStages( state, sgData, pass ); GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass); GFX->setShaderConstBuffer(shaderConsts); // Set our shader constants. _setTextureTransforms(pass); _setShaderConstants(state, sgData, pass); LightManager* lm = state ? LIGHTMGR : NULL; if (lm) lm->setLightInfo(this, NULL, sgData, state, pass, shaderConsts); shaderConsts->setSafe(rpd->shaderHandles.mAccumTimeSC, MATMGR->getTotalTime()); return true; }
void ProcessedShaderMaterial::_setShaderConstants(SceneRenderState * state, const SceneData &sgData, U32 pass) { PROFILE_SCOPE( ProcessedShaderMaterial_SetShaderConstants ); GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass); ShaderConstHandles* handles = _getShaderConstHandles(pass); U32 stageNum = getStageFromPass(pass); // First we do all the constants which are not // controlled via the material... we have to // set these all the time as they could change. if ( handles->mFogDataSC->isValid() ) { Point3F fogData; fogData.x = sgData.fogDensity; fogData.y = sgData.fogDensityOffset; fogData.z = sgData.fogHeightFalloff; shaderConsts->set( handles->mFogDataSC, fogData ); } shaderConsts->setSafe(handles->mFogColorSC, sgData.fogColor); if( handles->mOneOverFarplane->isValid() ) { const F32 &invfp = 1.0f / state->getFarPlane(); Point4F oneOverFP(invfp, invfp, invfp, invfp); shaderConsts->set( handles->mOneOverFarplane, oneOverFP ); } shaderConsts->setSafe( handles->mAccumTimeSC, MATMGR->getTotalTime() ); // If the shader constants have not been lost then // they contain the content from a previous render pass. // // In this case we can skip updating the material constants // which do not change frame to frame. // // NOTE: This assumes we're not animating material parameters // in a way that doesn't cause a shader reload... this isn't // being done now, but it could change in the future. // if ( !shaderConsts->wasLost() ) return; shaderConsts->setSafe(handles->mSpecularColorSC, mMaterial->mSpecular[stageNum]); shaderConsts->setSafe(handles->mSpecularPowerSC, mMaterial->mSpecularPower[stageNum]); shaderConsts->setSafe(handles->mParallaxInfoSC, mMaterial->mParallaxScale[stageNum]); shaderConsts->setSafe(handles->mMinnaertConstantSC, mMaterial->mMinnaertConstant[stageNum]); if ( handles->mSubSurfaceParamsSC->isValid() ) { Point4F subSurfParams; dMemcpy( &subSurfParams, &mMaterial->mSubSurfaceColor[stageNum], sizeof(ColorF) ); subSurfParams.w = mMaterial->mSubSurfaceRolloff[stageNum]; shaderConsts->set(handles->mSubSurfaceParamsSC, subSurfParams); } if ( handles->mRTSizeSC->isValid() ) { const Point2I &resolution = GFX->getActiveRenderTarget()->getSize(); Point2F pixelShaderConstantData; pixelShaderConstantData.x = resolution.x; pixelShaderConstantData.y = resolution.y; shaderConsts->set( handles->mRTSizeSC, pixelShaderConstantData ); } if ( handles->mOneOverRTSizeSC->isValid() ) { const Point2I &resolution = GFX->getActiveRenderTarget()->getSize(); Point2F oneOverTargetSize( 1.0f / (F32)resolution.x, 1.0f / (F32)resolution.y ); shaderConsts->set( handles->mOneOverRTSizeSC, oneOverTargetSize ); } // set detail scale shaderConsts->setSafe(handles->mDetailScaleSC, mMaterial->mDetailScale[stageNum]); shaderConsts->setSafe(handles->mDetailBumpStrength, mMaterial->mDetailNormalMapStrength[stageNum]); // MFT_ImposterVert if ( handles->mImposterUVs->isValid() ) { U32 uvCount = getMin( mMaterial->mImposterUVs.size(), 64 ); // See imposter.hlsl AlignedArray<Point4F> imposterUVs( uvCount, sizeof( Point4F ), (U8*)mMaterial->mImposterUVs.address(), false ); shaderConsts->set( handles->mImposterUVs, imposterUVs ); } shaderConsts->setSafe( handles->mImposterLimits, mMaterial->mImposterLimits ); // Diffuse shaderConsts->setSafe(handles->mDiffuseColorSC, mMaterial->mDiffuse[stageNum]); shaderConsts->setSafe( handles->mAlphaTestValueSC, mClampF( (F32)mMaterial->mAlphaRef / 255.0f, 0.0f, 1.0f ) ); if(handles->mDiffuseAtlasParamsSC) { Point4F atlasParams(1.0f / mMaterial->mCellLayout[stageNum].x, // 1 / num_horizontal 1.0f / mMaterial->mCellLayout[stageNum].y, // 1 / num_vertical mMaterial->mCellSize[stageNum], // tile size in pixels getBinLog2(mMaterial->mCellSize[stageNum]) ); // pow of 2 of tile size in pixels 2^9 = 512, 2^10=1024 etc shaderConsts->setSafe(handles->mDiffuseAtlasParamsSC, atlasParams); } if(handles->mBumpAtlasParamsSC) { Point4F atlasParams(1.0f / mMaterial->mCellLayout[stageNum].x, // 1 / num_horizontal 1.0f / mMaterial->mCellLayout[stageNum].y, // 1 / num_vertical mMaterial->mCellSize[stageNum], // tile size in pixels getBinLog2(mMaterial->mCellSize[stageNum]) ); // pow of 2 of tile size in pixels 2^9 = 512, 2^10=1024 etc shaderConsts->setSafe(handles->mBumpAtlasParamsSC, atlasParams); } if(handles->mDiffuseAtlasTileSC) { // Sanity check the wrap flags //AssertWarn(mMaterial->mTextureAddressModeU == mMaterial->mTextureAddressModeV, "Addresing mode mismatch, texture atlasing will be confused"); Point4F atlasTileParams( mMaterial->mCellIndex[stageNum].x, // Tile co-ordinate, ie: [0, 3] mMaterial->mCellIndex[stageNum].y, 0.0f, 0.0f ); // TODO: Wrap mode flags? shaderConsts->setSafe(handles->mDiffuseAtlasTileSC, atlasTileParams); } if(handles->mBumpAtlasTileSC) { // Sanity check the wrap flags //AssertWarn(mMaterial->mTextureAddressModeU == mMaterial->mTextureAddressModeV, "Addresing mode mismatch, texture atlasing will be confused"); Point4F atlasTileParams( mMaterial->mCellIndex[stageNum].x, // Tile co-ordinate, ie: [0, 3] mMaterial->mCellIndex[stageNum].y, 0.0f, 0.0f ); // TODO: Wrap mode flags? shaderConsts->setSafe(handles->mBumpAtlasTileSC, atlasTileParams); } }
void ProcessedShaderMaterial::_setTextureTransforms(const U32 pass) { PROFILE_SCOPE( ProcessedShaderMaterial_SetTextureTransforms ); ShaderConstHandles* handles = _getShaderConstHandles(pass); if (handles->mTexMatSC->isValid()) { MatrixF texMat( true ); mMaterial->updateTimeBasedParams(); F32 waveOffset = _getWaveOffset( pass ); // offset is between 0.0 and 1.0 // handle scroll anim type if( mMaterial->mAnimFlags[pass] & Material::Scroll ) { if( mMaterial->mAnimFlags[pass] & Material::Wave ) { Point3F scrollOffset; scrollOffset.x = mMaterial->mScrollDir[pass].x * waveOffset; scrollOffset.y = mMaterial->mScrollDir[pass].y * waveOffset; scrollOffset.z = 1.0; texMat.setColumn( 3, scrollOffset ); } else { Point3F offset( mMaterial->mScrollOffset[pass].x, mMaterial->mScrollOffset[pass].y, 1.0 ); texMat.setColumn( 3, offset ); } } // handle rotation if( mMaterial->mAnimFlags[pass] & Material::Rotate ) { if( mMaterial->mAnimFlags[pass] & Material::Wave ) { F32 rotPos = waveOffset * M_2PI; texMat.set( EulerF( 0.0, 0.0, rotPos ) ); texMat.setColumn( 3, Point3F( 0.5, 0.5, 0.0 ) ); MatrixF test( true ); test.setColumn( 3, Point3F( mMaterial->mRotPivotOffset[pass].x, mMaterial->mRotPivotOffset[pass].y, 0.0 ) ); texMat.mul( test ); } else { texMat.set( EulerF( 0.0, 0.0, mMaterial->mRotPos[pass] ) ); texMat.setColumn( 3, Point3F( 0.5, 0.5, 0.0 ) ); MatrixF test( true ); test.setColumn( 3, Point3F( mMaterial->mRotPivotOffset[pass].x, mMaterial->mRotPivotOffset[pass].y, 0.0 ) ); texMat.mul( test ); } } // Handle scale + wave offset if( mMaterial->mAnimFlags[pass] & Material::Scale && mMaterial->mAnimFlags[pass] & Material::Wave ) { F32 wOffset = fabs( waveOffset ); texMat.setColumn( 3, Point3F( 0.5, 0.5, 0.0 ) ); MatrixF temp( true ); temp.setRow( 0, Point3F( wOffset, 0.0, 0.0 ) ); temp.setRow( 1, Point3F( 0.0, wOffset, 0.0 ) ); temp.setRow( 2, Point3F( 0.0, 0.0, wOffset ) ); temp.setColumn( 3, Point3F( -wOffset * 0.5, -wOffset * 0.5, 0.0 ) ); texMat.mul( temp ); } // handle sequence if( mMaterial->mAnimFlags[pass] & Material::Sequence ) { U32 frameNum = (U32)(MATMGR->getTotalTime() * mMaterial->mSeqFramePerSec[pass]); F32 offset = frameNum * mMaterial->mSeqSegSize[pass]; if ( mMaterial->mAnimFlags[pass] & Material::Scale ) texMat.scale( Point3F( mMaterial->mSeqSegSize[pass], 1.0f, 1.0f ) ); Point3F texOffset = texMat.getPosition(); texOffset.x += offset; texMat.setPosition( texOffset ); } GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass); shaderConsts->setSafe(handles->mTexMatSC, texMat); } }
void ProcessedShaderMaterial::setTextureStages( SceneRenderState *state, const SceneData &sgData, U32 pass ) { PROFILE_SCOPE( ProcessedShaderMaterial_SetTextureStages ); ShaderConstHandles *handles = _getShaderConstHandles(pass); // Set all of the textures we need to render the give pass. #ifdef TORQUE_DEBUG AssertFatal( pass<mPasses.size(), "Pass out of bounds" ); #endif RenderPassData *rpd = mPasses[pass]; GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass); NamedTexTarget *texTarget; GFXTextureObject *texObject; for( U32 i=0; i<rpd->mNumTex; i++ ) { U32 currTexFlag = rpd->mTexType[i]; if (!LIGHTMGR || !LIGHTMGR->setTextureStage(sgData, currTexFlag, i, shaderConsts, handles)) { switch( currTexFlag ) { // If the flag is unset then assume its just // a regular texture to set... nothing special. case 0: default: GFX->setTexture(i, rpd->mTexSlot[i].texObject); break; case Material::NormalizeCube: GFX->setCubeTexture(i, Material::GetNormalizeCube()); break; case Material::Lightmap: GFX->setTexture( i, sgData.lightmap ); break; case Material::ToneMapTex: shaderConsts->setSafe(handles->mToneMapTexSC, (S32)i); GFX->setTexture(i, rpd->mTexSlot[i].texObject); break; case Material::Cube: GFX->setCubeTexture( i, rpd->mCubeMap ); break; case Material::SGCube: GFX->setCubeTexture( i, sgData.cubemap ); break; case Material::BackBuff: GFX->setTexture( i, sgData.backBuffTex ); break; case Material::TexTarget: { texTarget = rpd->mTexSlot[i].texTarget; if ( !texTarget ) { GFX->setTexture( i, NULL ); break; } texObject = texTarget->getTexture(); // If no texture is available then map the default 2x2 // black texture to it. This at least will ensure that // we get consistant behavior across GPUs and platforms. if ( !texObject ) texObject = GFXTexHandle::ZERO; if ( handles->mRTParamsSC[i]->isValid() && texObject ) { const Point3I &targetSz = texObject->getSize(); const RectI &targetVp = texTarget->getViewport(); Point4F rtParams; ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams); shaderConsts->set(handles->mRTParamsSC[i], rtParams); } GFX->setTexture( i, texObject ); break; } } } } }