// Drawing void Sphere::draw(GLWidget * dest) const { if (shown()) { GlErrorTool::getErrors("Sphere::draw:1", name()); GLUquadricObj * quad = gluNewQuadric(); if (texture()) { texture()->glBindTex(dest); gluQuadricTexture(quad,GL_TRUE); } glColor4fv(color().vec); if (wireframe()) { gluQuadricDrawStyle(quad, GLU_LINE); } else { gluQuadricDrawStyle(quad, GLU_FILL); } Tool::Vector v = position(); glPushMatrix(); glTranslatef(v.x, v.y, v.z); gluSphere(quad, radius_, slices_, stacks_); glPopMatrix(); if (texture()) { glBindTexture(GL_TEXTURE_2D, 0); } gluDeleteQuadric(quad); GlErrorTool::getErrors("Sphere::draw:2", name()); } }
Material::Material(Material_t tag) : tag(tag), vertexShader(this), fragmentShader(this), index0AttributeName(this) { mId = Material::MaterialIdCount++; mUuid = Math::generateUUID(); mName = ""; side() = kFrontSide; opacity() = 1.0f; transparent() = false; blending() = kNormalBlending; blendSrc() = kSrcAlphaFactor; blendDst() = kOneMinusSrcAlphaFactor; blendEquation() = kAddEquation; depthTest() = true; depthWrite() = true; polygonOffset() = false; polygonOffsetFactor() = 0; polygonOffsetUnits() = 0; // mAlphaTest = 0; overdraw() = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer visible() = true; needsUpdate() = true; // By default, bind position to attribute index 0. In WebGL, attribute 0 // should always be used to avoid potentially expensive emulation. index0AttributeName("position"); linewidth() = 1.0f; metal() = false; perPixel() = true; shading() = kNoShading; vertexColors() = kNoColors; wireframe() = false; wireframeLinewidth() = 1.0f; }
void TerrainCellMaterial::_updateDefaultAnisotropy() { // TODO: We need to split the stateblock initialization // from the shader constant lookup and pass setup in a // future version of terrain materials. // // For now use some custom code in a horrible loop to // change the anisotropy directly and fast. // const U32 maxAnisotropy = MATMGR->getDefaultAnisotropy(); Vector<TerrainCellMaterial*>::iterator iter = smAllMaterials.begin(); for ( ; iter != smAllMaterials.end(); iter++ ) { for ( U32 p=0; p < (*iter)->mPasses.size(); p++ ) { Pass &pass = (*iter)->mPasses[p]; // Start from the existing state block. GFXStateBlockDesc desc = pass.stateBlock->getDesc(); for ( U32 m=0; m < pass.materials.size(); m++ ) { const MaterialInfo *matInfo = pass.materials[m]; if ( matInfo->detailTexConst->isValid() ) { const S32 sampler = matInfo->detailTexConst->getSamplerRegister(); if ( maxAnisotropy > 1 ) { desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic; desc.samplers[sampler].maxAnisotropy = maxAnisotropy; } else desc.samplers[sampler].minFilter = GFXTextureFilterLinear; } if ( matInfo->macroTexConst->isValid() ) { const S32 sampler = matInfo->macroTexConst->getSamplerRegister(); if ( maxAnisotropy > 1 ) { desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic; desc.samplers[sampler].maxAnisotropy = maxAnisotropy; } else desc.samplers[sampler].minFilter = GFXTextureFilterLinear; } if ( matInfo->normalTexConst->isValid() ) { const S32 sampler = matInfo->normalTexConst->getSamplerRegister(); if ( maxAnisotropy > 1 ) { desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic; desc.samplers[sampler].maxAnisotropy = maxAnisotropy; } else desc.samplers[sampler].minFilter = GFXTextureFilterLinear; } } // for ( U32 m=0; m < pass.materials.size(); m++ ) // Set the updated stateblock. desc.setCullMode( GFXCullCCW ); pass.stateBlock = GFX->createStateBlock( desc ); //reflection 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 ); } // for ( U32 p=0; i < (*iter)->mPasses.size(); p++ ) } }
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; }