void ScatterSky::_debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) { GFXStateBlockDesc desc; desc.fillMode = GFXFillSolid; desc.setBlend( false, GFXBlendOne, GFXBlendZero ); desc.setZReadWrite( false, false ); GFXStateBlockRef sb = GFX->GFX->createStateBlock( desc ); GFX->setStateBlock( sb ); PrimBuild::begin( GFXLineStrip, mSkyPoints.size() ); PrimBuild::color3i( 255, 0, 255 ); for ( U32 i = 0; i < mSkyPoints.size(); i++ ) { Point3F pnt = mSkyPoints[i]; pnt.normalize(); pnt *= 500; pnt += state->getCameraPosition(); PrimBuild::vertex3fv( pnt ); } PrimBuild::end(); }
void Portal::_renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance* overrideMat ) { if( overrideMat ) return; // Update geometry if necessary. if( mIsGeometryDirty ) _updateGeometry(); // Render portal polygon. GFXStateBlockDesc desc; desc.setBlend( true ); desc.setZReadWrite( true, false ); desc.setCullMode( GFXCullNone ); PlaneF::Side viewSide = mPortalPlane.whichSide( state->getCameraPosition() ); ColorI color; switch( mClassification ) { case InvalidPortal: color = ColorI( 255, 255, 255, 45 ); break; case ExteriorPortal: color = viewSide == PlaneF::Front ? ColorI( 0, 128, 128, 45 ) : ColorI( 0, 255, 255, 45 ); break; case InteriorPortal: color = viewSide == PlaneF::Front ? ColorI( 128, 128, 0, 45 ) : ColorI( 255, 255, 0, 45 ); break; } GFX->getDrawUtil()->drawPolygon( desc, mPortalPolygonWS.address(), mPortalPolygonWS.size(), color ); desc.setFillModeWireframe(); GFX->getDrawUtil()->drawPolygon( desc, mPortalPolygonWS.address(), mPortalPolygonWS.size(), ColorF::RED ); // Render rest. Parent::_renderObject( ri, state, overrideMat ); }
void EditTSCtrl::renderGrid() { if( !isOrthoDisplayType() ) return; GFXDEBUGEVENT_SCOPE( Editor_renderGrid, ColorI::WHITE ); // Calculate the displayed grid size based on view F32 drawnGridSize = mGridPlaneSize; F32 gridPixelSize = projectRadius(1.0f, mGridPlaneSize); if(gridPixelSize < mGridPlaneSizePixelBias) { U32 counter = 1; while(gridPixelSize < mGridPlaneSizePixelBias) { drawnGridSize = mGridPlaneSize * counter * 10.0f; gridPixelSize = projectRadius(1.0f, drawnGridSize); ++counter; // No infinite loops here if(counter > 1000) break; } } F32 minorTickSize = 0; F32 gridSize = drawnGridSize; U32 minorTickMax = mGridPlaneMinorTicks + 1; if(minorTickMax > 0) { minorTickSize = drawnGridSize; gridSize = drawnGridSize * minorTickMax; } // Build the view-based origin VectorF dir; smCamMatrix.getColumn( 1, &dir ); Point3F gridPlanePos = smCamPos + dir; Point2F size(mOrthoWidth + 2 * gridSize, mOrthoHeight + 2 * gridSize); GFXStateBlockDesc desc; desc.setBlend( true ); desc.setZReadWrite( true, false ); GFXDrawUtil::Plane plane = GFXDrawUtil::PlaneXY; switch( getDisplayType() ) { case DisplayTypeTop: case DisplayTypeBottom: plane = GFXDrawUtil::PlaneXY; break; case DisplayTypeLeft: case DisplayTypeRight: plane = GFXDrawUtil::PlaneYZ; break; case DisplayTypeFront: case DisplayTypeBack: plane = GFXDrawUtil::PlaneXZ; break; default: break; } GFX->getDrawUtil()->drawPlaneGrid( desc, gridPlanePos, size, Point2F( minorTickSize, minorTickSize ), mGridPlaneMinorTickColor, plane ); GFX->getDrawUtil()->drawPlaneGrid( desc, gridPlanePos, size, Point2F( gridSize, gridSize ), mGridPlaneColor, plane ); }
void ClipMapBlenderCache::initialize( ClipMap *cm ) { mOwningClipMap = cm; mClipMapSize = cm->mClipMapSize; mLightmapScratchTextures.push_back(GFXTexHandle( mClipMapSize, mClipMapSize, GFXFormatR8G8B8X8, &ClipMapTextureProfile, avar("%s() - mLightmapScratchTextures (line %d)", __FUNCTION__, __LINE__), 1 )); if (GFX->getPixelShaderVersion() == 0.0f) { mFixedfunction = true; // Fixed function stateblock GFXStateBlockDesc sbFF; sbFF.samplersDefined = true; sbFF.samplers[0] = GFXSamplerStateDesc::getClampLinear(); sbFF.samplers[0].textureColorOp = GFXTOPSelectARG1; sbFF.samplers[0].colorArg1 = GFXTATexture; sbFF.samplers[1] = GFXSamplerStateDesc::getWrapLinear(); mFFBaseLayerSB = GFX->createStateBlock(sbFF); sbFF.setBlend(true, GFXBlendOne, GFXBlendOne); mFFAdditionalLayersSB = GFX->createStateBlock(sbFF); sbFF.setBlend(true, GFXBlendDestColor, GFXBlendSrcColor); sbFF.samplers[1].textureColorOp = GFXTOPDisable; mFFLightmapSB = GFX->createStateBlock(sbFF); } else { mFixedfunction = false; // Find and init shaders. ShaderData *sd = NULL; if(GFX->getPixelShaderVersion() >= 2.0f) { if(!Sim::findObject( ( mLM1 ? "AtlasBlender20ShaderLM1" : "AtlasBlender20Shader" ), sd) || (sd->mShader == NULL)) { Con::errorf("ClipMapBlenderCache::initialize - " "Couldn't find shader 'AtlasBlender20Shader'! Terrain will not blend properly on SM2.0 cards!"); } else { mOnePass = sd->mShader; if (mOnePass) mShaderConsts = mOnePass->allocConstBuffer(); if (mShaderConsts) sd->mapSamplerNames(mShaderConsts); } } else { if(!Sim::findObject( ( mLM1 ? "AtlasBlender11AShaderLM1" : "AtlasBlendeer11AShader" ), sd) || (sd->mShader == NULL)) { Con::errorf("ClipMapBlenderCache::initialize - " "Couldn't find shader 'AtlasBlender11AShader'! Terrain will not blend properly on SM1.0 cards!"); } else { mTwoPass[0] = sd->mShader; if (mTwoPass[0]) mShaderConsts = mTwoPass[0]->allocConstBuffer(); if (mShaderConsts) sd->mapSamplerNames(mShaderConsts); } if(!Sim::findObject( ( mLM1 ? "AtlasBlender11BShaderLM1" : "AtlasBlender11BShader" ), sd) || (sd->mShader == NULL)) { Con::errorf("ClipMapBlenderCache::initialize - " "Couldn't find shader 'AtlasBlender11BShader'! Terrain will not blend properly on SM1.0 cards!"); } else { mTwoPass[1] = sd->mShader; } } if (mShaderConsts) { mModelViewProjSC = mShaderConsts->getShader()->getShaderConstHandle(ShaderGenVars::modelview); mOpacityMapSC = mShaderConsts->getShader()->getShaderConstHandle("$opacity"); mLightMapSC = mShaderConsts->getShader()->getShaderConstHandle("$lightMap"); mTex1SC = mShaderConsts->getShader()->getShaderConstHandle("$tex1"); mTex2SC = mShaderConsts->getShader()->getShaderConstHandle("$tex2"); mTex3SC = mShaderConsts->getShader()->getShaderConstHandle("$tex3"); mTex4SC = mShaderConsts->getShader()->getShaderConstHandle("$tex4"); mSourceTexScalesSC = mShaderConsts->getShader()->getShaderConstHandle("$sourceTexScales"); } // Init state blocks GFXStateBlockDesc sbd; sbd.setCullMode(GFXCullNone); sbd.setZEnable(false); sbd.zWriteEnable = false; sbd.samplersDefined = true; sbd.samplers[0] = GFXSamplerStateDesc::getClampLinear(); sbd.samplers[1] = GFXSamplerStateDesc::getClampLinear(); sbd.samplers[2] = GFXSamplerStateDesc::getWrapLinear(); sbd.samplers[3] = GFXSamplerStateDesc::getWrapLinear(); sbd.samplers[4] = GFXSamplerStateDesc::getWrapLinear(); sbd.samplers[5] = GFXSamplerStateDesc::getWrapLinear(); mOnePassSB = GFX->createStateBlock(sbd); sbd.setBlend(true, GFXBlendOne, GFXBlendOne); mTwoPassSB = GFX->createStateBlock(sbd); } createOpacityScratchTextures(); }
void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mat ) { GFXDrawUtil *drawer = GFX->getDrawUtil(); GFX->setTexture( 0, NULL ); // Render world box. if ( false ) { Box3F wbox( mWorldBox ); //if ( getServerObject() ) // Box3F wbox = static_cast<ConvexShape*>( getServerObject() )->mWorldBox; GFXStateBlockDesc desc; desc.setCullMode( GFXCullNone ); desc.setFillModeWireframe(); drawer->drawCube( desc, wbox, ColorI::RED ); } const Vector< Point3F > &pointList = mGeometry.points; const Vector< ConvexShape::Face > &faceList = mGeometry.faces; // Render Edges. if ( false ) { GFXTransformSaver saver; //GFXFrustumSaver fsaver; MatrixF xfm( getRenderTransform() ); xfm.scale( getScale() ); GFX->multWorld( xfm ); GFXStateBlockDesc desc; desc.setZReadWrite( true, false ); desc.setBlend( true ); GFX->setStateBlockByDesc( desc ); //MathUtils::getZBiasProjectionMatrix( 0.01f, state->getFrustum(), ) const Point3F &camFvec = state->getCameraTransform().getForwardVector(); for ( S32 i = 0; i < faceList.size(); i++ ) { const ConvexShape::Face &face = faceList[i]; const Vector< ConvexShape::Edge > &edgeList = face.edges; const Vector< U32 > &facePntList = face.points; PrimBuild::begin( GFXLineList, edgeList.size() * 2 ); PrimBuild::color( ColorI::WHITE * 0.8f ); for ( S32 j = 0; j < edgeList.size(); j++ ) { PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p0 ] ] - camFvec * 0.001f ); PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p1 ] ] - camFvec * 0.001f ); } PrimBuild::end(); } } ColorI faceColorsx[4] = { ColorI( 255, 0, 0 ), ColorI( 0, 255, 0 ), ColorI( 0, 0, 255 ), ColorI( 255, 0, 255 ) }; MatrixF objToWorld( mObjToWorld ); objToWorld.scale( mObjScale ); // Render faces centers/colors. if ( false ) { GFXStateBlockDesc desc; desc.setCullMode( GFXCullNone ); Point3F size( 0.1f ); for ( S32 i = 0; i < faceList.size(); i++ ) { ColorI color = faceColorsx[ i % 4 ]; S32 div = ( i / 4 ) * 4; if ( div > 0 ) color /= div; color.alpha = 255; Point3F pnt; objToWorld.mulP( faceList[i].centroid, &pnt ); drawer->drawCube( desc, size, pnt, color, NULL ); } } // Render winding order. if ( false ) { GFXStateBlockDesc desc; desc.setCullMode( GFXCullNone ); desc.setZReadWrite( true, false ); GFX->setStateBlockByDesc( desc ); U32 pointCount = 0; for ( S32 i = 0; i < faceList.size(); i++ ) pointCount += faceList[i].winding.size(); PrimBuild::begin( GFXLineList, pointCount * 2 ); for ( S32 i = 0; i < faceList.size(); i++ ) { for ( S32 j = 0; j < faceList[i].winding.size(); j++ ) { Point3F p0 = pointList[ faceList[i].points[ faceList[i].winding[j] ] ]; Point3F p1 = p0 + mSurfaces[ faceList[i].id ].getUpVector() * 0.75f * ( Point3F::One / mObjScale ); objToWorld.mulP( p0 ); objToWorld.mulP( p1 ); ColorI color = faceColorsx[ j % 4 ]; S32 div = ( j / 4 ) * 4; if ( div > 0 ) color /= div; color.alpha = 255; PrimBuild::color( color ); PrimBuild::vertex3fv( p0 ); PrimBuild::color( color ); PrimBuild::vertex3fv( p1 ); } } PrimBuild::end(); } // Render Points. if ( false ) { /* GFXTransformSaver saver; MatrixF xfm( getRenderTransform() ); xfm.scale( getScale() ); GFX->multWorld( xfm ); GFXStateBlockDesc desc; Point3F size( 0.05f ); */ } // Render surface transforms. if ( false ) { GFXStateBlockDesc desc; desc.setBlend( false ); desc.setZReadWrite( true, true ); Point3F scale(mNormalLength); for ( S32 i = 0; i < mSurfaces.size(); i++ ) { MatrixF objToWorld( mObjToWorld ); objToWorld.scale( mObjScale ); MatrixF renderMat; renderMat.mul( objToWorld, mSurfaces[i] ); renderMat.setPosition( renderMat.getPosition() + renderMat.getUpVector() * 0.001f ); drawer->drawTransform( desc, renderMat, &scale, NULL ); } } }
void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect) { if (mStateBlock.isNull()) { GFXStateBlockDesc desc; desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha); desc.setZReadWrite(false); desc.zWriteEnable = false; desc.setCullMode(GFXCullNone); mStateBlock = GFX->createStateBlock(desc); } RectI boundsRect(offset, getExtent()); renderColorBox(boundsRect); if (mPositionChanged || mBitmap == NULL) { bool nullBitmap = false; if (mPositionChanged == false && mBitmap == NULL) nullBitmap = true; mPositionChanged = false; Point2I extent = getRoot()->getExtent(); // If we are anything but a pallete, change the pick color if (mDisplayMode != pPallet) { Point2I resolution = getRoot()->getExtent(); U32 buf_x = offset.x + mSelectorPos.x + 1; U32 buf_y = resolution.y - (extent.y - (offset.y + mSelectorPos.y + 1)); GFXTexHandle bb( resolution.x, resolution.y, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, avar("%s() - bb (line %d)", __FUNCTION__, __LINE__) ); Point2I tmpPt(buf_x, buf_y); GFXTarget *targ = GFX->getActiveRenderTarget(); targ->resolveTo(bb); if (mBitmap) { delete mBitmap; mBitmap = NULL; } mBitmap = new GBitmap(bb.getWidth(), bb.getHeight()); bb.copyToBmp(mBitmap); if (!nullBitmap) { if (mSelectColor) { Point2I pos = findColor(mSetColor, offset, resolution, *mBitmap); mSetColor = mSetColor.BLACK; mSelectColor = false; setSelectorPos(pos); } else { ColorI tmp; mBitmap->getColor(buf_x, buf_y, tmp); mPickColor = (ColorF)tmp; // Now do onAction() if we are allowed if (mActionOnMove) onAction(); } } } } //render the children renderChildControls(offset, updateRect); }
bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials, Pass *pass, bool firstPass, bool prePassMat, bool reflectMat, bool baseOnly ) { if ( GFX->getPixelShaderVersion() < 3.0f ) baseOnly = true; // NOTE: At maximum we only try to combine sgMaxTerrainMaterialsPerPass materials // into a single pass. This is sub-optimal for the simplest // cases, but the most common case results in much fewer // shader generation failures and permutations leading to // faster load time and less hiccups during gameplay. U32 matCount = getMin( sgMaxTerrainMaterialsPerPass, materials->size() ); Vector<GFXTexHandle> normalMaps; // See if we're currently running under the // basic lighting manager. // // TODO: This seems ugly... we should trigger // features like this differently in the future. // bool useBLM = dStrcmp( LIGHTMGR->getId(), "BLM" ) == 0; // Do we need to disable normal mapping? const bool disableNormalMaps = MATMGR->getExclusionFeatures().hasFeature( MFT_NormalMap ) || useBLM; // How about parallax? const bool disableParallaxMaps = GFX->getPixelShaderVersion() < 3.0f || MATMGR->getExclusionFeatures().hasFeature( MFT_Parallax ); // Has advanced lightmap support been enabled for prepass. bool advancedLightmapSupport = false; if ( prePassMat ) { // This sucks... but it works. AdvancedLightBinManager *lightBin; if ( Sim::findObject( "AL_LightBinMgr", lightBin ) ) advancedLightmapSupport = lightBin->MRTLightmapsDuringPrePass(); } // Loop till we create a valid shader! while( true ) { FeatureSet features; features.addFeature( MFT_VertTransform ); if ( prePassMat ) { features.addFeature( MFT_EyeSpaceDepthOut ); features.addFeature( MFT_PrePassConditioner ); features.addFeature( MFT_DeferredTerrainBaseMap ); features.addFeature(MFT_isDeferred); if ( advancedLightmapSupport ) features.addFeature( MFT_RenderTarget3_Zero ); } else { features.addFeature( MFT_TerrainBaseMap ); features.addFeature( MFT_RTLighting ); // The HDR feature is always added... it will compile out // if HDR is not enabled in the engine. features.addFeature( MFT_HDROut ); } features.addFeature(MFT_DeferredTerrainBlankInfoMap); // Enable lightmaps and fogging if we're in BL. if ( reflectMat || useBLM ) { features.addFeature( MFT_Fog ); features.addFeature( MFT_ForwardShading ); } if ( useBLM ) features.addFeature( MFT_TerrainLightMap ); // The additional passes need to be lerp blended into the // target to maintain the results of the previous passes. if ( !firstPass ) features.addFeature( MFT_TerrainAdditive ); normalMaps.clear(); pass->materials.clear(); // Now add all the material layer features. for ( U32 i=0; i < matCount && !baseOnly; i++ ) { TerrainMaterial *mat = (*materials)[i]->mat; if ( mat == NULL ) continue; // We only include materials that // have more than a base texture. if ( mat->getDetailSize() <= 0 || mat->getDetailDistance() <= 0 || mat->getDetailMap().isEmpty() ) continue; S32 featureIndex = pass->materials.size(); // check for macro detail texture if ( !(mat->getMacroSize() <= 0 || mat->getMacroDistance() <= 0 || mat->getMacroMap().isEmpty() ) ) { if(prePassMat) features.addFeature( MFT_DeferredTerrainMacroMap, featureIndex ); else features.addFeature( MFT_TerrainMacroMap, featureIndex ); } if(prePassMat) features.addFeature( MFT_DeferredTerrainDetailMap, featureIndex ); else features.addFeature( MFT_TerrainDetailMap, featureIndex ); pass->materials.push_back( (*materials)[i] ); normalMaps.increment(); // Skip normal maps if we need to. if ( !disableNormalMaps && mat->getNormalMap().isNotEmpty() ) { features.addFeature( MFT_TerrainNormalMap, featureIndex ); normalMaps.last().set( mat->getNormalMap(), &GFXDefaultStaticNormalMapProfile, "TerrainCellMaterial::_createPass() - NormalMap" ); if ( normalMaps.last().getFormat() == GFXFormatDXT5 ) features.addFeature( MFT_IsDXTnm, featureIndex ); // Do we need and can we do parallax mapping? if ( !disableParallaxMaps && mat->getParallaxScale() > 0.0f && !mat->useSideProjection() ) features.addFeature( MFT_TerrainParallaxMap, featureIndex ); } // Is this layer got side projection? if ( mat->useSideProjection() ) features.addFeature( MFT_TerrainSideProject, featureIndex ); } MaterialFeatureData featureData; featureData.features = features; featureData.materialFeatures = features; // Check to see how many vertex shader output // registers we're gonna need. U32 numTex = 0; U32 numTexReg = 0; for ( U32 i=0; i < features.getCount(); i++ ) { S32 index; const FeatureType &type = features.getAt( i, &index ); ShaderFeature* sf = FEATUREMGR->getByType( type ); if ( !sf ) continue; sf->setProcessIndex( index ); ShaderFeature::Resources res = sf->getResources( featureData ); numTex += res.numTex; numTexReg += res.numTexReg; } // Can we build the shader? // // NOTE: The 10 is sort of an abitrary SM 3.0 // limit. Its really supposed to be 11, but that // always fails to compile so far. // if ( numTex < GFX->getNumSamplers() && numTexReg <= 10 ) { // NOTE: We really shouldn't be getting errors building the shaders, // but we can generate more instructions than the ps_2_x will allow. // // There is no way to deal with this case that i know of other than // letting the compile fail then recovering by trying to build it // with fewer materials. // // We normally disable the shader error logging so that the user // isn't fooled into thinking there is a real bug. That is until // we get down to a single material. If a single material case // fails it means it cannot generate any passes at all! const bool logErrors = matCount == 1; GFXShader::setLogging( logErrors, true ); pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat<TerrVertex>(), NULL, mSamplerNames ); } // If we got a shader then we can continue. if ( pass->shader ) break; // If the material count is already 1 then this // is a real shader error... give up! if ( matCount <= 1 ) return false; // If we failed we next try half the input materials // so that we can more quickly arrive at a valid shader. matCount -= matCount / 2; } // Setup the constant buffer. pass->consts = pass->shader->allocConstBuffer(); // Prepare the basic constants. pass->modelViewProjConst = pass->shader->getShaderConstHandle( "$modelview" ); pass->worldViewOnly = pass->shader->getShaderConstHandle( "$worldViewOnly" ); pass->viewToObj = pass->shader->getShaderConstHandle( "$viewToObj" ); pass->eyePosWorldConst = pass->shader->getShaderConstHandle( "$eyePosWorld" ); pass->eyePosConst = pass->shader->getShaderConstHandle( "$eyePos" ); pass->vEyeConst = pass->shader->getShaderConstHandle( "$vEye" ); pass->layerSizeConst = pass->shader->getShaderConstHandle( "$layerSize" ); pass->objTransConst = pass->shader->getShaderConstHandle( "$objTrans" ); pass->worldToObjConst = pass->shader->getShaderConstHandle( "$worldToObj" ); pass->lightInfoBufferConst = pass->shader->getShaderConstHandle( "$lightInfoBuffer" ); pass->baseTexMapConst = pass->shader->getShaderConstHandle( "$baseTexMap" ); pass->layerTexConst = pass->shader->getShaderConstHandle( "$layerTex" ); pass->fogDataConst = pass->shader->getShaderConstHandle( "$fogData" ); pass->fogColorConst = pass->shader->getShaderConstHandle( "$fogColor" ); pass->lightMapTexConst = pass->shader->getShaderConstHandle( "$lightMapTex" ); pass->oneOverTerrainSize = pass->shader->getShaderConstHandle( "$oneOverTerrainSize" ); pass->squareSize = pass->shader->getShaderConstHandle( "$squareSize" ); pass->lightParamsConst = pass->shader->getShaderConstHandle( "$rtParamslightInfoBuffer" ); // Now prepare the basic stateblock. GFXStateBlockDesc desc; if ( !firstPass ) { desc.setBlend( true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha ); // If this is the prepass then we don't want to // write to the last two color channels (where // depth is usually encoded). // // This trick works in combination with the // MFT_TerrainAdditive feature to lerp the // output normal with the previous pass. // if ( prePassMat ) desc.setColorWrites( true, true, true, false ); } // We write to the zbuffer if this is a prepass // material or if the prepass is disabled. desc.setZReadWrite( true, !MATMGR->getPrePassEnabled() || prePassMat || reflectMat ); desc.samplersDefined = true; if ( pass->baseTexMapConst->isValid() ) desc.samplers[pass->baseTexMapConst->getSamplerRegister()] = GFXSamplerStateDesc::getWrapLinear(); if ( pass->layerTexConst->isValid() ) desc.samplers[pass->layerTexConst->getSamplerRegister()] = GFXSamplerStateDesc::getClampPoint(); if ( pass->lightInfoBufferConst->isValid() ) desc.samplers[pass->lightInfoBufferConst->getSamplerRegister()] = GFXSamplerStateDesc::getClampPoint(); if ( pass->lightMapTexConst->isValid() ) desc.samplers[pass->lightMapTexConst->getSamplerRegister()] = GFXSamplerStateDesc::getWrapLinear(); const U32 maxAnisotropy = MATMGR->getDefaultAnisotropy(); // Finally setup the material specific shader // constants and stateblock state. // // NOTE: If this changes be sure to check TerrainCellMaterial::_updateDefaultAnisotropy // to see if it needs the same changes. // for ( U32 i=0; i < pass->materials.size(); i++ ) { MaterialInfo *matInfo = pass->materials[i]; matInfo->detailInfoVConst = pass->shader->getShaderConstHandle( avar( "$detailScaleAndFade%d", i ) ); matInfo->detailInfoPConst = pass->shader->getShaderConstHandle( avar( "$detailIdStrengthParallax%d", i ) ); matInfo->detailTexConst = pass->shader->getShaderConstHandle( avar( "$detailMap%d", i ) ); if ( matInfo->detailTexConst->isValid() ) { const S32 sampler = matInfo->detailTexConst->getSamplerRegister(); desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear(); desc.samplers[sampler].magFilter = GFXTextureFilterLinear; desc.samplers[sampler].mipFilter = GFXTextureFilterLinear; if ( maxAnisotropy > 1 ) { desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic; desc.samplers[sampler].maxAnisotropy = maxAnisotropy; } else desc.samplers[sampler].minFilter = GFXTextureFilterLinear; matInfo->detailTex.set( matInfo->mat->getDetailMap(), &GFXDefaultStaticDiffuseProfile, "TerrainCellMaterial::_createPass() - DetailMap" ); } matInfo->macroInfoVConst = pass->shader->getShaderConstHandle( avar( "$macroScaleAndFade%d", i ) ); matInfo->macroInfoPConst = pass->shader->getShaderConstHandle( avar( "$macroIdStrengthParallax%d", i ) ); matInfo->macroTexConst = pass->shader->getShaderConstHandle( avar( "$macroMap%d", i ) ); if ( matInfo->macroTexConst->isValid() ) { const S32 sampler = matInfo->macroTexConst->getSamplerRegister(); desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear(); desc.samplers[sampler].magFilter = GFXTextureFilterLinear; desc.samplers[sampler].mipFilter = GFXTextureFilterLinear; if ( maxAnisotropy > 1 ) { desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic; desc.samplers[sampler].maxAnisotropy = maxAnisotropy; } else desc.samplers[sampler].minFilter = GFXTextureFilterLinear; matInfo->macroTex.set( matInfo->mat->getMacroMap(), &GFXDefaultStaticDiffuseProfile, "TerrainCellMaterial::_createPass() - MacroMap" ); } //end macro texture matInfo->normalTexConst = pass->shader->getShaderConstHandle( avar( "$normalMap%d", i ) ); if ( matInfo->normalTexConst->isValid() ) { const S32 sampler = matInfo->normalTexConst->getSamplerRegister(); desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear(); desc.samplers[sampler].magFilter = GFXTextureFilterLinear; desc.samplers[sampler].mipFilter = GFXTextureFilterLinear; if ( maxAnisotropy > 1 ) { desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic; desc.samplers[sampler].maxAnisotropy = maxAnisotropy; } else desc.samplers[sampler].minFilter = GFXTextureFilterLinear; matInfo->normalTex = normalMaps[i]; } } // Remove the materials we processed and leave the // ones that remain for the next pass. for ( U32 i=0; i < matCount; i++ ) { MaterialInfo *matInfo = materials->first(); if ( baseOnly || pass->materials.find_next( matInfo ) == -1 ) delete matInfo; materials->pop_front(); } // If we're doing prepass it requires some // special stencil settings for it to work. if ( prePassMat ) desc.addDesc( RenderPrePassMgr::getOpaqueStenciWriteDesc( false ) ); desc.setCullMode( GFXCullCCW ); pass->stateBlock = GFX->createStateBlock(desc); //reflection stateblock desc.setCullMode( GFXCullCW ); pass->reflectionStateBlock = GFX->createStateBlock(desc); // Create the wireframe state blocks. GFXStateBlockDesc wireframe( desc ); wireframe.fillMode = GFXFillWireframe; wireframe.setCullMode( GFXCullCCW ); pass->wireframeStateBlock = GFX->createStateBlock( wireframe ); return true; }
void drawActor( NxActor *inActor ) { GFXDrawUtil *drawer = GFX->getDrawUtil(); //drawer->setZRead( false ); // Determine alpha we render shapes with. const U8 enabledAlpha = 255; const U8 disabledAlpha = 100; U8 renderAlpha = inActor->readActorFlag( NX_AF_DISABLE_COLLISION ) ? disabledAlpha : enabledAlpha; // Determine color we render actors and shapes with. ColorI actorColor( 0, 0, 255, 200 ); ColorI shapeColor = ( inActor->isSleeping() ? ColorI( 0, 0, 255, renderAlpha ) : ColorI( 255, 0, 255, renderAlpha ) ); MatrixF actorMat(true); inActor->getGlobalPose().getRowMajor44( actorMat ); GFXStateBlockDesc desc; desc.setBlend( true ); desc.setZReadWrite( true, false ); desc.setCullMode( GFXCullNone ); // Draw an xfm gizmo for the actor's globalPose... //drawer->drawTransform( desc, actorMat, Point3F::One, actorColor ); // Loop through and render all the actor's shapes.... NxShape *const*pShapeArray = inActor->getShapes(); U32 numShapes = inActor->getNbShapes(); for ( U32 i = 0; i < numShapes; i++ ) { const NxShape *shape = pShapeArray[i]; Point3F shapePos = pxCast<Point3F>( shape->getGlobalPosition() ); MatrixF shapeMat(true); shape->getGlobalPose().getRowMajor44(shapeMat); shapeMat.setPosition( Point3F::Zero ); switch ( shape->getType() ) { case NX_SHAPE_SPHERE: { NxSphereShape *sphere = (NxSphereShape*)shape; drawer->drawSphere( desc, sphere->getRadius(), shapePos, shapeColor ); break; } case NX_SHAPE_BOX: { NxBoxShape *box = (NxBoxShape*)shape; Point3F size = pxCast<Point3F>( box->getDimensions() ); drawer->drawCube( desc, size*2, shapePos, shapeColor, &shapeMat ); break; } case NX_SHAPE_CAPSULE: { shapeMat.mul( MatrixF( EulerF( mDegToRad(90.0f), mDegToRad(90.0f), 0 ) ) ); NxCapsuleShape *capsule = (NxCapsuleShape*)shape; drawer->drawCapsule( desc, shapePos, capsule->getRadius(), capsule->getHeight(), shapeColor, &shapeMat ); break; } default: { break; } } } //drawer->clearZDefined(); }
void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) { // Save the current transforms so we can restore // it for child control rendering below. GFXTransformSaver saver; bool renderingToTarget = false; if(!processCameraQuery(&mLastCameraQuery)) { // We have no camera, but render the GUI children // anyway. This makes editing GuiTSCtrl derived // controls easier in the GuiEditor. renderChildControls( offset, updateRect ); return; } GFXTargetRef origTarget = GFX->getActiveRenderTarget(); // Set up the appropriate render style U32 prevRenderStyle = GFX->getCurrentRenderStyle(); Point2F prevProjectionOffset = GFX->getCurrentProjectionOffset(); Point2I renderSize = getExtent(); if(mRenderStyle == RenderStyleStereoSideBySide) { GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSideBySide); GFX->setCurrentProjectionOffset(mLastCameraQuery.projectionOffset); GFX->setStereoEyeOffsets(mLastCameraQuery.eyeOffset); if (!mLastCameraQuery.hasStereoTargets) { // Need to calculate our current viewport here mLastCameraQuery.stereoViewports[0] = updateRect; mLastCameraQuery.stereoViewports[0].extent.x /= 2; mLastCameraQuery.stereoViewports[1] = mLastCameraQuery.stereoViewports[0]; mLastCameraQuery.stereoViewports[1].point.x += mLastCameraQuery.stereoViewports[1].extent.x; } if (!mLastCameraQuery.hasFovPort) { // Need to make our own fovPort mLastCameraQuery.fovPort[0] = CalculateFovPortForCanvas(mLastCameraQuery.stereoViewports[0], mLastCameraQuery); mLastCameraQuery.fovPort[1] = CalculateFovPortForCanvas(mLastCameraQuery.stereoViewports[1], mLastCameraQuery); } GFX->setStereoFovPort(mLastCameraQuery.fovPort); // NOTE: this specifies fov for BOTH eyes GFX->setSteroViewports(mLastCameraQuery.stereoViewports); GFX->setStereoTargets(mLastCameraQuery.stereoTargets); MatrixF myTransforms[2]; if (smUseLatestDisplayTransform) { // Use the view matrix determined from the display device myTransforms[0] = mLastCameraQuery.eyeTransforms[0]; myTransforms[1] = mLastCameraQuery.eyeTransforms[1]; } else { // Use the view matrix determined from the control object myTransforms[0] = mLastCameraQuery.cameraMatrix; myTransforms[1] = mLastCameraQuery.cameraMatrix; QuatF qrot = mLastCameraQuery.cameraMatrix; Point3F pos = mLastCameraQuery.cameraMatrix.getPosition(); Point3F rotEyePos; myTransforms[0].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[0], &rotEyePos)); myTransforms[1].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[1], &rotEyePos)); } GFX->setStereoEyeTransforms(myTransforms); // Allow render size to originate from the render target if (mLastCameraQuery.stereoTargets[0]) { renderSize = mLastCameraQuery.stereoViewports[0].extent; renderingToTarget = true; } } else { GFX->setCurrentRenderStyle(GFXDevice::RS_Standard); } if ( mReflectPriority > 0 ) { // Get the total reflection priority. F32 totalPriority = 0; for ( U32 i=0; i < smAwakeTSCtrls.size(); i++ ) if ( smAwakeTSCtrls[i]->isVisible() ) totalPriority += smAwakeTSCtrls[i]->mReflectPriority; REFLECTMGR->update( mReflectPriority / totalPriority, getExtent(), mLastCameraQuery ); } if(mForceFOV != 0) mLastCameraQuery.fov = mDegToRad(mForceFOV); if(mCameraZRot) { MatrixF rotMat(EulerF(0, 0, mDegToRad(mCameraZRot))); mLastCameraQuery.cameraMatrix.mul(rotMat); } Frustum frustum; if(mRenderStyle == RenderStyleStereoSideBySide) { // NOTE: these calculations are essentially overridden later by the fov port settings when rendering each eye. MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[0]); } else { // set up the camera and viewport stuff: F32 wwidth; F32 wheight; F32 renderWidth = F32(renderSize.x); F32 renderHeight = F32(renderSize.y); F32 aspectRatio = renderWidth / renderHeight; // Use the FOV to calculate the viewport height scale // then generate the width scale from the aspect ratio. if(!mLastCameraQuery.ortho) { wheight = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2.0f); wwidth = aspectRatio * wheight; } else { wheight = mLastCameraQuery.fov; wwidth = aspectRatio * wheight; } F32 hscale = wwidth * 2.0f / renderWidth; F32 vscale = wheight * 2.0f / renderHeight; F32 left = (updateRect.point.x - offset.x) * hscale - wwidth; F32 right = (updateRect.point.x + updateRect.extent.x - offset.x) * hscale - wwidth; F32 top = wheight - vscale * (updateRect.point.y - offset.y); F32 bottom = wheight - vscale * (updateRect.point.y + updateRect.extent.y - offset.y); frustum.set( mLastCameraQuery.ortho, left, right, top, bottom, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane ); } // Manipulate the frustum for tiled screenshots const bool screenShotMode = gScreenShot && gScreenShot->isPending(); if ( screenShotMode ) { gScreenShot->tileFrustum( frustum ); GFX->setViewMatrix(MatrixF::Identity); } RectI tempRect = updateRect; if (!renderingToTarget) { #ifdef TORQUE_OS_MAC Point2I screensize = getRoot()->getWindowSize(); tempRect.point.y = screensize.y - (tempRect.point.y + tempRect.extent.y); #endif GFX->setViewport( tempRect ); } else { // Activate stereo RT GFX->activateStereoTarget(-1); } // Clear the zBuffer so GUI doesn't hose object rendering accidentally GFX->clear( GFXClearZBuffer , ColorI(20,20,20), 1.0f, 0 ); //GFX->clear( GFXClearTarget, ColorI(255,0,0), 1.0f, 0); GFX->setFrustum( frustum ); if(mLastCameraQuery.ortho) { mOrthoWidth = frustum.getWidth(); mOrthoHeight = frustum.getHeight(); } // We're going to be displaying this render at size of this control in // pixels - let the scene know so that it can calculate e.g. reflections // correctly for that final display result. gClientSceneGraph->setDisplayTargetResolution(renderSize); // Set the GFX world matrix to the world-to-camera transform, but don't // change the cameraMatrix in mLastCameraQuery. This is because // mLastCameraQuery.cameraMatrix is supposed to contain the camera-to-world // transform. In-place invert would save a copy but mess up any GUIs that // depend on that value. MatrixF worldToCamera = mLastCameraQuery.cameraMatrix; worldToCamera.inverse(); GFX->setWorldMatrix( worldToCamera ); mSaveProjection = GFX->getProjectionMatrix(); mSaveModelview = GFX->getWorldMatrix(); mSaveViewport = updateRect; mSaveWorldToScreenScale = GFX->getWorldToScreenScale(); mSaveFrustum = GFX->getFrustum(); mSaveFrustum.setTransform( mLastCameraQuery.cameraMatrix ); // Set the default non-clip projection as some // objects depend on this even in non-reflect cases. gClientSceneGraph->setNonClipProjection( mSaveProjection ); // Give the post effect manager the worldToCamera, and cameraToScreen matrices PFXMGR->setFrameMatrices( mSaveModelview, mSaveProjection ); renderWorld(updateRect); DebugDrawer::get()->render(); // Render the canvas overlay if its available if (mRenderStyle == RenderStyleStereoSideBySide && mStereoGuiTarget.getPointer()) { GFXDEBUGEVENT_SCOPE( StereoGui_Render, ColorI( 255, 0, 0 ) ); MatrixF proj(1); Frustum originalFrustum = GFX->getFrustum(); GFXTextureObject *texObject = mStereoGuiTarget->getTexture(0); const FovPort *currentFovPort = GFX->getStereoFovPort(); const MatrixF *eyeTransforms = GFX->getStereoEyeTransforms(); const Point3F *eyeOffset = GFX->getStereoEyeOffsets(); Frustum gfxFrustum = originalFrustum; for (U32 i=0; i<2; i++) { GFX->activateStereoTarget(i); MathUtils::makeFovPortFrustum(&gfxFrustum, true, gfxFrustum.getNearDist(), gfxFrustum.getFarDist(), currentFovPort[i], eyeTransforms[i]); GFX->setFrustum(gfxFrustum); MatrixF eyeWorldTrans(1); eyeWorldTrans.setPosition(Point3F(eyeOffset[i].x,eyeOffset[i].y,eyeOffset[i].z)); MatrixF eyeWorld(1); eyeWorld.mul(eyeWorldTrans); eyeWorld.inverse(); GFX->setWorldMatrix(eyeWorld); GFX->setViewMatrix(MatrixF::Identity); if (!mStereoOverlayVB.getPointer()) { mStereoOverlayVB.set(GFX, 4, GFXBufferTypeStatic); GFXVertexPCT *verts = mStereoOverlayVB.lock(0, 4); F32 texLeft = 0.0f; F32 texRight = 1.0f; F32 texTop = 1.0f; F32 texBottom = 0.0f; F32 rectRatio = gfxFrustum.getWidth() / gfxFrustum.getHeight(); F32 rectWidth = gfxFrustum.getWidth() * TS_OVERLAY_SCREEN_WIDTH; F32 rectHeight = rectWidth * rectRatio; F32 screenLeft = -rectWidth * 0.5; F32 screenRight = rectWidth * 0.5; F32 screenTop = -rectHeight * 0.5; F32 screenBottom = rectHeight * 0.5; const F32 fillConv = 0.0f; const F32 frustumDepthAdjusted = gfxFrustum.getNearDist() + 0.012; verts[0].point.set( screenLeft - fillConv, frustumDepthAdjusted, screenTop - fillConv ); verts[1].point.set( screenRight - fillConv, frustumDepthAdjusted, screenTop - fillConv ); verts[2].point.set( screenLeft - fillConv, frustumDepthAdjusted, screenBottom - fillConv ); verts[3].point.set( screenRight - fillConv, frustumDepthAdjusted, screenBottom - fillConv ); verts[0].color = verts[1].color = verts[2].color = verts[3].color = ColorI(255,255,255,255); verts[0].texCoord.set( texLeft, texTop ); verts[1].texCoord.set( texRight, texTop ); verts[2].texCoord.set( texLeft, texBottom ); verts[3].texCoord.set( texRight, texBottom ); mStereoOverlayVB.unlock(); } if (!mStereoGuiSB.getPointer()) { // DrawBitmapStretchSR GFXStateBlockDesc bitmapStretchSR; bitmapStretchSR.setCullMode(GFXCullNone); bitmapStretchSR.setZReadWrite(false, false); bitmapStretchSR.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha); bitmapStretchSR.samplersDefined = true; bitmapStretchSR.samplers[0] = GFXSamplerStateDesc::getClampLinear(); bitmapStretchSR.samplers[0].minFilter = GFXTextureFilterPoint; bitmapStretchSR.samplers[0].mipFilter = GFXTextureFilterPoint; bitmapStretchSR.samplers[0].magFilter = GFXTextureFilterPoint; mStereoGuiSB = GFX->createStateBlock(bitmapStretchSR); } GFX->setVertexBuffer(mStereoOverlayVB); GFX->setStateBlock(mStereoGuiSB); GFX->setTexture( 0, texObject ); GFX->setupGenericShaders( GFXDevice::GSModColorTexture ); GFX->drawPrimitive( GFXTriangleStrip, 0, 2 ); } } // Restore the previous matrix state before // we begin rendering the child controls. saver.restore(); // Restore the render style and any stereo parameters GFX->setActiveRenderTarget(origTarget); GFX->setCurrentRenderStyle(prevRenderStyle); GFX->setCurrentProjectionOffset(prevProjectionOffset); if(mRenderStyle == RenderStyleStereoSideBySide && gLastStereoTexture) { GFX->setClipRect(updateRect); GFX->getDrawUtil()->drawBitmapStretch(gLastStereoTexture, updateRect); } // Allow subclasses to render 2D elements. GFX->setClipRect(updateRect); renderGui( offset, updateRect ); if (shouldRenderChildControls()) { renderChildControls(offset, updateRect); } smFrameCount++; }
void SFXEmitter::_render3DVisualFeedback() { GFXTransformSaver saver; GFX->multWorld( getRenderTransform() ); GFXStateBlockDesc desc; desc.setZReadWrite( true, false ); desc.setBlend( true ); desc.setCullMode( GFXCullNone ); if( mRenderSB == NULL ) mRenderSB = GFX->createStateBlock( desc ); GFX->setStateBlock( mRenderSB ); // Render the max range sphere. if( smRenderColorRangeSphere.alpha > 0 ) GFX->getDrawUtil()->drawSphere( desc, mDescription.mMaxDistance, Point3F( 0.f, 0.f, 0.f ), smRenderColorRangeSphere ); //TODO: some point size support in GFX would be nice // Prepare primitive list. Make sure we stay within limits. F32 radialIncrements = smRenderRadialIncrements; F32 sweepIncrements = smRenderSweepIncrements; F32 pointDistance = smRenderPointDistance; F32 numPoints; while( 1 ) { numPoints = mCeil( 360.f / radialIncrements ) * mCeil( 360.f / sweepIncrements ) * ( mDescription.mMaxDistance / pointDistance ); if( numPoints < 65536 ) break; radialIncrements *= 1.1f; sweepIncrements *= 1.1f; pointDistance *= 1.5; } PrimBuild::begin( GFXPointList, numPoints ); // Render inner cone. _renderCone( radialIncrements, sweepIncrements, pointDistance, mDescription.mConeInsideAngle, 0.f, mDescription.mVolume, mDescription.mVolume, smRenderColorInnerCone ); // Outer Cone and Outside volume only get rendered if mConeOutsideVolume > 0 if( mDescription.mConeOutsideVolume > 0.f ) { const F32 outsideVolume = mDescription.mVolume * mDescription.mConeOutsideVolume; // Render outer cone. _renderCone( radialIncrements, sweepIncrements, pointDistance, mDescription.mConeOutsideAngle, mDescription.mConeInsideAngle, outsideVolume, mDescription.mVolume, smRenderColorOuterCone ); // Render outside volume. _renderCone( radialIncrements, sweepIncrements, pointDistance, 360.f, mDescription.mConeOutsideAngle, outsideVolume, outsideVolume, smRenderColorOutsideVolume ); } // Commit primitive list. PrimBuild::end(); }
void ShadowMaterialHook::init( BaseMatInstance *inMat ) { if( !inMat->isValid() ) return; // Tweak the feature data to include just what we need. FeatureSet features; features.addFeature( MFT_VertTransform ); features.addFeature( MFT_DiffuseMap ); features.addFeature( MFT_TexAnim ); features.addFeature( MFT_AlphaTest ); features.addFeature( MFT_Visibility ); // Actually we want to include features from the inMat // if they operate on the preTransform verts so things // like wind/deformation effects will also affect the shadow. const FeatureSet &inFeatures = inMat->getFeatures(); for ( U32 i = 0; i < inFeatures.getCount(); i++ ) { const FeatureType& ft = inFeatures.getAt(i); if ( ft.getGroup() == MFG_PreTransform ) features.addFeature( ft ); } // Do instancing in shadows if we can. if ( inFeatures.hasFeature( MFT_UseInstancing ) ) features.addFeature( MFT_UseInstancing ); Material *shadowMat = (Material*)inMat->getMaterial(); if ( dynamic_cast<CustomMaterial*>( shadowMat ) ) { // This is a custom material... who knows what it really does, but // if it wasn't already filtered out of the shadow render then just // give it some default depth out material. shadowMat = MATMGR->getMaterialDefinitionByName( "AL_DefaultShadowMaterial" ); } // By default we want to disable some states // that the material might enable for us. GFXStateBlockDesc forced; forced.setBlend( false ); forced.setAlphaTest( false ); // We should force on zwrite as the prepass // will disable it by default. forced.setZReadWrite( true, true ); // TODO: Should we render backfaces for // shadows or does the ESM take care of // all our acne issues? //forced.setCullMode( GFXCullCW ); // Vector, and spotlights use the same shadow material. BaseMatInstance *newMat = new ShadowMatInstance( shadowMat ); newMat->setUserObject( inMat->getUserObject() ); newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures ); newMat->addStateBlockDesc( forced ); if( !newMat->init( features, inMat->getVertexFormat() ) ) { SAFE_DELETE( newMat ); newMat = MATMGR->createWarningMatInstance(); } mShadowMat[ShadowType_Spot] = newMat; newMat = new ShadowMatInstance( shadowMat ); newMat->setUserObject( inMat->getUserObject() ); newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures ); forced.setCullMode( GFXCullCW ); newMat->addStateBlockDesc( forced ); forced.cullDefined = false; newMat->addShaderMacro( "CUBE_SHADOW_MAP", "" ); newMat->init( features, inMat->getVertexFormat() ); mShadowMat[ShadowType_CubeMap] = newMat; // A dual paraboloid shadow rendered in a single draw call. features.addFeature( MFT_ParaboloidVertTransform ); features.addFeature( MFT_IsSinglePassParaboloid ); features.removeFeature( MFT_VertTransform ); newMat = new ShadowMatInstance( shadowMat ); newMat->setUserObject( inMat->getUserObject() ); GFXStateBlockDesc noCull( forced ); noCull.setCullMode( GFXCullNone ); newMat->addStateBlockDesc( noCull ); newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures ); newMat->init( features, inMat->getVertexFormat() ); mShadowMat[ShadowType_DualParaboloidSinglePass] = newMat; // Regular dual paraboloid shadow. features.addFeature( MFT_ParaboloidVertTransform ); features.removeFeature( MFT_IsSinglePassParaboloid ); features.removeFeature( MFT_VertTransform ); newMat = new ShadowMatInstance( shadowMat ); newMat->setUserObject( inMat->getUserObject() ); newMat->addStateBlockDesc( forced ); newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures ); newMat->init( features, inMat->getVertexFormat() ); mShadowMat[ShadowType_DualParaboloid] = newMat; /* // A single paraboloid shadow. newMat = new ShadowMatInstance( startMatInstance ); GFXStateBlockDesc noCull; noCull.setCullMode( GFXCullNone ); newMat->addStateBlockDesc( noCull ); newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures ); newMat->init( features, globalFeatures, inMat->getVertexFormat() ); mShadowMat[ShadowType_DualParaboloidSinglePass] = newMat; */ }
void GuiGraphCtrl::onRender(Point2I offset, const RectI &updateRect) { if (mBlendSB.isNull()) { GFXStateBlockDesc desc; desc.setBlend(true, GFXBlendSrcColor, GFXBlendInvSrcColor); mBlendSB = GFX->createStateBlock(desc); desc.setBlend(false, GFXBlendOne, GFXBlendZero); mSolidSB = GFX->createStateBlock(desc); } GFX->setStateBlock( mBlendSB ); GFX->getDrawUtil()->drawRectFill( updateRect, mProfile->mFillColor ); GFX->setStateBlock( mSolidSB ); const Point2I globalPos = getGlobalBounds().point; const F32 midPointY = F32( globalPos.y ) + F32( getExtent().y ) * mCenterY; for( S32 k = 0; k < MaxPlots; ++ k ) { // Check if there is an autoplot and the proper amount of time has passed, if so add datum. if( mAutoPlot[ k ] && mAutoPlotDelay[ k ] < (Sim::getCurrentTime() - mAutoPlotLastDisplay[ k ] ) ) { mAutoPlotLastDisplay[ k ] = Sim::getCurrentTime(); addDatum( k, Con::getFloatVariable( mAutoPlot[ k ] ) ); } // Nothing to graph if( mGraphData[ k ].size() == 0 ) continue; // Adjust scale to max value + 5% so we can see high values F32 Scale = F32( getExtent().y ) / F32( mGraphMax[ k ] * 1.05 ); const S32 numSamples = mGraphData[ k ].size(); switch( mGraphType[ k ] ) { case Bar: { F32 prevOffset = 0; for( S32 sample = 0; sample < numSamples; ++ sample ) { PrimBuild::begin( GFXTriangleFan, 4 ); PrimBuild::color( mGraphColor[ k ] ); F32 offset = F32( getExtent().x ) / F32( MaxDataPoints ) * F32( sample + 1 ); PrimBuild::vertex2f( globalPos.x + prevOffset, midPointY - ( getDatum( k, sample ) * Scale ) ); PrimBuild::vertex2f( globalPos.x + offset, midPointY - ( getDatum( k, sample ) * Scale ) ); PrimBuild::vertex2f( globalPos.x + offset, midPointY ); PrimBuild::vertex2f( globalPos.x + prevOffset, midPointY ); prevOffset = offset; PrimBuild::end(); } break; } case Filled: { PrimBuild::begin( GFXTriangleStrip, numSamples * 2 ); // Max size correct? -pw PrimBuild::color( mGraphColor[ k ] ); for( S32 sample = 0; sample < numSamples; ++ sample ) { F32 offset = F32( getExtent().x ) / F32( MaxDataPoints - 1 ) * F32( sample ); PrimBuild::vertex2f( globalPos.x + offset, midPointY ); PrimBuild::vertex2f( globalPos.x + offset, midPointY - ( getDatum( k, sample ) * Scale ) ); } PrimBuild::end(); break; } case Point: case Polyline: { if( mGraphType[ k ] == Point ) PrimBuild::begin( GFXPointList, numSamples ); // Max size correct? -pw else PrimBuild::begin( GFXLineStrip, numSamples ); PrimBuild::color( mGraphColor[ k ] ); for( S32 sample = 0; sample < numSamples; ++ sample ) { F32 offset = F32( getExtent().x ) / F32( MaxDataPoints - 1 ) * F32( sample ); PrimBuild::vertex2f( globalPos.x + offset, midPointY - ( getDatum( k, sample ) * Scale ) ); } PrimBuild::end(); break; } } } if( mProfile->mBorder ) { RectI rect( offset.x, offset.y, getWidth(), getHeight() ); GFX->getDrawUtil()->drawRect( rect, mProfile->mBorderColor ); } renderChildControls( offset, updateRect ); }