private void _initBlendMaps(Axiom.Components.Terrain.Terrain terrain) { var blendMap0 = terrain.GetLayerBlendMap(1); var blendMap1 = terrain.GetLayerBlendMap(2); Real minHeight0 = 70; Real fadeDist0 = 40; Real minHeight1 = 70; Real fadeDist1 = 15; var pBlend1 = blendMap1.BlendPointer; var blendIdx = 0; for (var y = 0; y < terrain.LayerBlendMapSize; y++) { for (var x = 0; x < terrain.LayerBlendMapSize; x++) { Real tx = 0; Real ty = 0; blendMap0.ConvertImageToTerrainSpace(x, y, ref tx, ref ty); Real height = terrain.GetHeightAtTerrainPosition(tx, ty); Real val = (height - minHeight0) / fadeDist0; val = Utility.Clamp(val, 0, 1); val = (height - minHeight1) / fadeDist1; val = Utility.Clamp(val, 0, 1); pBlend1[blendIdx++] = val; } } blendMap0.Dirty(); blendMap1.Dirty(); blendMap0.Update(); blendMap1.Update(); }
/// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="y"></param> public TerrainSlot(long x, long y) { X = x; Y = y; Instance = null; Def = new TerrainSlotDefinition(); }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <returns></returns> protected override HighLevelGpuProgram CreateFragmentProgram( SM2Profile prof, Terrain terrain, TechniqueType tt ) { HighLevelGpuProgramManager mgr = HighLevelGpuProgramManager.Instance; string progName = GetFragmentProgramName( prof, terrain, tt ); var ret = (HighLevelGpuProgram)mgr.GetByName( progName ); if ( ret == null ) { ret = mgr.CreateProgram( progName, ResourceGroupManager.DefaultResourceGroupName, "cg", GpuProgramType.Fragment ); } else { ret.Unload(); } if ( prof.IsLayerNormalMappingEnabled || prof.IsLayerParallaxMappingEnabled ) { //ret.SetParam( "profiles", "ps_2_x fp40" ); ret.Properties[ "profiles" ] = "ps_2_x fp40"; } else { //ret.SetParam( "profiles", "ps_2_0 fp30" ); ret.Properties[ "profiles" ] = "ps_2_0 fp30"; } //ret.SetParam( "entry_point", "main_fp" ); ret.Properties[ "entry_point" ] = "main_fp"; return ret; }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="gpuparams"></param> public virtual void UpdateFpParams( SM2Profile prof, Terrain terrain, TechniqueType tt, GpuProgramParameters gpuparams ) { gpuparams.IgnoreMissingParameters = true; // TODO - parameterise this? var scaleBiasSpecular = new Vector4( 0.03f, -0.04f, 32, 1 ); gpuparams.SetNamedConstant( "scaleBiasSpecular", scaleBiasSpecular ); }
/// <summary> /// / /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="prog"></param> public virtual void DefaultFpParams( SM2Profile prof, Terrain terrain, TechniqueType tt, HighLevelGpuProgram prog ) { GpuProgramParameters gparams = prog.DefaultParameters; gparams.IgnoreMissingParameters = true; #if true gparams.SetNamedAutoConstant( "ambient", GpuProgramParameters.AutoConstantType.AmbientLightColor, 0 ); gparams.SetNamedAutoConstant( "lightPosObjSpace", GpuProgramParameters.AutoConstantType.LightPositionObjectSpace, 0 ); gparams.SetNamedAutoConstant( "lightDiffuseColor", GpuProgramParameters.AutoConstantType.LightDiffuseColor, 0 ); gparams.SetNamedAutoConstant( "lightSpecularColor", GpuProgramParameters.AutoConstantType.LightSpecularColor, 0 ); gparams.SetNamedAutoConstant( "eyePosObjSpace", GpuProgramParameters.AutoConstantType.CameraPositionObjectSpace, 0 ); #warning missing auto constant type "FogColor" //gparams.SetNamedAutoConstant("fogColor", GpuProgramParameters.AutoConstantType.FogParams, 0); #endif }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="source"></param> protected abstract void GenerateVpFooter( SM2Profile prof, Terrain terrain, TechniqueType tt, ref string source );
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="source"></param> protected virtual void GenerateFragmetProgramSource( SM2Profile prof, Terrain terrain, TechniqueType tt, ref string source ) { GenerateFpHeader( prof, terrain, tt, ref source ); if ( tt != TechniqueType.LowLod ) { uint maxLayers = prof.GetMaxLayers( terrain ); uint numLayers = Utility.Min( maxLayers, (uint)terrain.LayerCount ); for ( uint i = 0; i < numLayers; ++i ) { GenerateFpLayer( prof, terrain, tt, i, ref source ); } } GenerateFpFooter( prof, terrain, tt, ref source ); }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <returns></returns> protected virtual string GetFragmentProgramName( SM2Profile prof, Terrain terrain, TechniqueType tt ) { string progName = terrain.MaterialName + "/sm2/fp"; switch ( tt ) { case TechniqueType.HighLod: progName += "/hlod"; break; case TechniqueType.LowLod: progName += "/llod"; break; case TechniqueType.RenderCompositeMap: progName += "/comp"; break; } return progName; }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <returns></returns> public virtual HighLevelGpuProgram GenerateFragmentProgram( SM2Profile prof, Terrain terrain, TechniqueType tt ) { HighLevelGpuProgram ret = CreateFragmentProgram( prof, terrain, tt ); string sourceStr = string.Empty; GenerateFragmetProgramSource( prof, terrain, tt, ref sourceStr ); ret.Source = sourceStr; DefaultFpParams( prof, terrain, tt, ret ); #if AXIOM_DEBUG_MODE LogManager.Instance.Write(LogMessageLevel.Trivial, false, "*** Terrain Fragment Program: " + ret.Name + " ***\n" + ret.Source + "\n*** ***"); #endif return ret; }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <returns></returns> protected override HighLevelGpuProgram CreateVertexProgram( SM2Profile prof, Terrain terrain, TechniqueType tt ) { HighLevelGpuProgramManager mgr = HighLevelGpuProgramManager.Instance; string progName = GetVertexProgramName( prof, terrain, tt ); switch ( tt ) { case TechniqueType.HighLod: progName += "/hlod"; break; case TechniqueType.LowLod: progName += "/llod"; break; case TechniqueType.RenderCompositeMap: progName += "/comp"; break; } var ret = (HighLevelGpuProgram)mgr.GetByName( progName ); if ( ret == null ) { ret = mgr.CreateProgram( progName, ResourceGroupManager.DefaultResourceGroupName, "glsl", GpuProgramType.Vertex ); } else { ret.Unload(); } return ret; }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <returns></returns> protected override HighLevelGpuProgram CreateFragmentProgram( SM2Profile prof, Terrain terrain, TechniqueType tt ) { HighLevelGpuProgramManager mgr = HighLevelGpuProgramManager.Instance; string progName = GetFragmentProgramName( prof, terrain, tt ); var ret = (HighLevelGpuProgram)mgr.GetByName( progName ); if ( ret == null ) { ret = mgr.CreateProgram( progName, ResourceGroupManager.DefaultResourceGroupName, "hlsl", GpuProgramType.Fragment ); } else { ret.Unload(); } #warning very high shader version //ret.SetParam( "target", "ps_3_0" ); //ret.SetParam( "entry_point", "main_fp" ); ret.Properties[ "target" ] = "ps_3_0"; ret.Properties[ "entry_point" ] = "main_fp"; return ret; }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="source"></param> protected override void GenerateFpFooter( SM2Profile prof, Terrain terrain, TechniqueType tt, ref string source ) { if ( tt == TechniqueType.LowLod ) { source += " outputCol.rgb = diffuse;\n"; } else { if ( terrain.IsGlobalColorMapEnabled && prof.IsGlobalColorMapEnabled ) { // sample colour map and apply to diffuse source += " diffuse *= tex2D(globalColorMap, uv).rgb;\n"; } if ( prof.IsLightMapEnabled ) { // sample lightmap source += " shadow = tex2D(lightMap, uv).r;\n"; } // diffuse lighting source += " outputCol.rgb += ambient * diffuse + litRes.y * lightDiffuseColor * diffuse * shadow;\n"; // specular default if ( !prof.IsLayerSpecularMappingEnabled ) { source += " specular = 1.0;\n"; } if ( tt == TechniqueType.RenderCompositeMap ) { // Raw specular is embedded in composite map alpha source += " outputCol.a = specular * shadow;\n"; } else { // Apply specular source += " outputCol.rgb += litRes.z * lightSpecularColor * specular * shadow;\n"; if ( prof.Parent.DebugLevel != 0 ) { source += " outputCol.rg += lodInfo.xy;\n"; } } } // Final return source += " return outputCol;\n" + "}\n"; }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="source"></param> protected override void GenerateVpFooter( SM2Profile prof, Terrain terrain, TechniqueType tt, ref string source ) { source += " oPos = mul(viewProjMatrix, worldPos);\n" + " oUV = uv.xy;\n" + "}\n"; }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="layer"></param> /// <param name="source"></param> protected override void GenerateFpLayer( SM2Profile prof, Terrain terrain, TechniqueType tt, uint layer, ref string source ) { uint uvIdx = layer/2; string uvChannels = layer%2 != 0 ? ".zw" : ".xy"; uint blendIdx = ( layer - 1 )/4; // generate UV source += " float2 uv" + layer + " = layerUV" + uvIdx + uvChannels + ";\n"; // calculate lighting here if normal mapping if ( prof.IsLayerNormalMappingEnabled ) { if ( prof.IsLayerParallaxMappingEnabled && tt != TechniqueType.RenderCompositeMap ) { // modify UV - note we have to sample an extra time source += " displacement = tex2D(normtex" + layer + ", uv" + layer + ").a\n" + " * scaleBiasSpecular.x + scaleBiasSpecular.y;\n"; source += " uv" + layer + " += TSeyeDir.xy * displacement;\n"; } // access TS normal map source += " TSnormal = expand(tex2D(normtex" + layer + ", uv" + layer + ")).rgb;\n"; source += " TShalfAngle = normalize(TSlightDir + TSeyeDir);\n"; source += " litResLayer = lit(dot(TSlightDir, TSnormal), dot(TShalfAngle, TSnormal), scaleBiasSpecular.z);\n"; if ( layer == 0 ) { source += " litRes = litResLayer;\n"; } else { source += " litRes = lerp(litRes, litResLayer, blendTexVal" + blendIdx + "." + GetChannel( layer - 1 ) + ");\n"; } } // sample diffuse texture source += " float4 diffuseSpecTex" + layer + " = tex2D(difftex" + layer + ", uv" + layer + ");\n"; // apply to common if ( layer == 0 ) { source += " diffuse = diffuseSpecTex0.rgb;\n"; if ( prof.IsLayerSpecularMappingEnabled ) { source += " specular = diffuseSpecTex0.a;\n"; } } else { source += " diffuse = lerp(diffuse, diffuseSpecTex" + layer + ".rgb, blendTexVal" + blendIdx + "." + GetChannel( layer - 1 ) + ");\n"; if ( prof.IsLayerSpecularMappingEnabled ) { source += " specular = lerp(specular, diffuseSpecTex" + layer + ".a, blendTexVal" + blendIdx + "." + GetChannel( layer - 1 ) + ");\n"; } } }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="layer"></param> /// <param name="source"></param> protected override void GenerateVpLayer( SM2Profile prof, Terrain terrain, TechniqueType tt, uint layer, ref string source ) { // nothing to do }
public void DoTerrainModify(Axiom.Components.Terrain.Terrain terrain, Vector3 centrepos, Real timeElapsed) { var tsPos = Vector3.Zero; terrain.GetTerrainPosition(centrepos, ref tsPos); #if !(WINDOWS_PHONE || XBOX || XBOX360 || ANDROID || IOS) if (Keyboard.IsKeyDown(SIS.KeyCode.Key_EQUALS) || Keyboard.IsKeyDown(SIS.KeyCode.Key_ADD) || Keyboard.IsKeyDown(SIS.KeyCode.Key_MINUS) || Keyboard.IsKeyDown(SIS.KeyCode.Key_SUBTRACT)) { switch (this.mode) { case Mode.EditHeight: { // we need point coords Real terrainSize = (terrain.Size - 1); var startx = (long)((tsPos.x - this.brushSizeTerrainSpace) * terrainSize); var starty = (long)((tsPos.y - this.brushSizeTerrainSpace) * terrainSize); var endx = (long)((tsPos.x + this.brushSizeTerrainSpace) * terrainSize); var endy = (long)((tsPos.y + this.brushSizeTerrainSpace) * terrainSize); startx = Utility.Max(startx, 0L); starty = Utility.Max(starty, 0L); endx = Utility.Min(endx, (long)terrainSize); endy = Utility.Min(endy, (long)terrainSize); for (long y = starty; y <= endy; ++y) { for (long x = startx; x <= endx; ++x) { Real tsXdist = (x / terrainSize) - tsPos.x; Real tsYdist = (y / terrainSize) - tsPos.y; Real weight = Utility.Min((Real)1.0, Utility.Sqrt(tsYdist * tsYdist + tsXdist * tsXdist) / (Real)(0.5 * this.brushSizeTerrainSpace)); weight = 1.0 - (weight * weight); var addedHeight = weight * 250.0 * timeElapsed; float newheight; if (Keyboard.IsKeyDown(SIS.KeyCode.Key_EQUALS) || Keyboard.IsKeyDown(SIS.KeyCode.Key_ADD)) { newheight = terrain.GetHeightAtPoint(x, y) + addedHeight; } else { newheight = terrain.GetHeightAtPoint(x, y) - addedHeight; } terrain.SetHeightAtPoint(x, y, newheight); } } if (this.heightUpdateCountDown == 0) { this.heightUpdateCountDown = this.heightUpdateRate; } } break; case Mode.EditBlend: { var layer = terrain.GetLayerBlendMap(this.layerEdit); // we need image coords Real imgSize = terrain.LayerBlendMapSize; var startx = (long)((tsPos.x - this.brushSizeTerrainSpace) * imgSize); var starty = (long)((tsPos.y - this.brushSizeTerrainSpace) * imgSize); var endx = (long)((tsPos.x + this.brushSizeTerrainSpace) * imgSize); var endy = (long)((tsPos.y + this.brushSizeTerrainSpace) * imgSize); startx = Utility.Max(startx, 0L); starty = Utility.Max(starty, 0L); endx = Utility.Min(endx, (long)imgSize); endy = Utility.Min(endy, (long)imgSize); for (var y = (int)starty; y <= endy; ++y) { for (var x = (int)startx; x <= endx; ++x) { Real tsXdist = (x / imgSize) - tsPos.x; Real tsYdist = (y / imgSize) - tsPos.y; Real weight = Utility.Min((Real)1.0, Utility.Sqrt(tsYdist * tsYdist + tsXdist * tsXdist) / (Real)(0.5 * this.brushSizeTerrainSpace)); weight = 1.0 - (weight * weight); float paint = weight * timeElapsed; var imgY = (int)(imgSize - y); float val; if (Keyboard.IsKeyDown(SIS.KeyCode.Key_EQUALS) || Keyboard.IsKeyDown(SIS.KeyCode.Key_ADD)) { val = layer.GetBlendValue(x, imgY) + paint; } else { val = layer.GetBlendValue(x, imgY) - paint; } val = Utility.Clamp(val, 1.0f, 0.0f); layer.SetBlendValue(x, imgY, val); } } layer.Update(); } break; case Mode.Normal: case Mode.Count: default: break; } ; } #endif }
/// <summary> /// /// </summary> /// <param name="terrain"></param> public override void RequestOption( Terrain terrain ) { terrain.IsMorphRequired = true; terrain.NormalMapRequired = true; terrain.SetLightMapRequired( this.mLightMapEnabled, true ); terrain.CompositeMapRequired = this.mCompositeMapEnabled; }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <returns></returns> protected override HighLevelGpuProgram CreateFragmentProgram( SM2Profile prof, Terrain terrain, TechniqueType tt ) { HighLevelGpuProgramManager mgr = HighLevelGpuProgramManager.Instance; string progName = GetVertexProgramName( prof, terrain, tt ); var ret = (HighLevelGpuProgram)mgr.GetByName( progName ); if ( ret == null ) { ret = mgr.CreateProgram( progName, ResourceGroupManager.DefaultResourceGroupName, "glsl", GpuProgramType.Fragment ); } else { ret.Unload(); } return ret; }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="mat"></param> /// <param name="terrain"></param> /// <param name="compositeMap"></param> public virtual void UpdateParams( SM2Profile prof, Material mat, Terrain terrain, bool compositeMap ) { Pass p = mat.GetTechnique( 0 ).GetPass( 0 ); if ( compositeMap ) { UpdateVpParams( prof, terrain, TechniqueType.RenderCompositeMap, p.VertexProgramParameters ); UpdateFpParams( prof, terrain, TechniqueType.RenderCompositeMap, p.FragmentProgramParameters ); } else { //high lod UpdateVpParams( prof, terrain, TechniqueType.HighLod, p.VertexProgramParameters ); UpdateFpParams( prof, terrain, TechniqueType.HighLod, p.FragmentProgramParameters ); //low lod p = mat.GetTechnique( 1 ).GetPass( 0 ); UpdateVpParams( prof, terrain, TechniqueType.LowLod, p.VertexProgramParameters ); UpdateFpParams( prof, terrain, TechniqueType.LowLod, p.FragmentProgramParameters ); } }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="source"></param> protected override void GenerateVpFooter( SM2Profile prof, Terrain terrain, TechniqueType tt, ref string source ) { //not implemted yet }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <returns></returns> protected abstract HighLevelGpuProgram CreateFragmentProgram( SM2Profile prof, Terrain terrain, TechniqueType tt );
/// <summary> /// /// </summary> /// <param name="mat"></param> /// <param name="terrain"></param> /// <param name="tt"></param> protected void AddTechnique( Material mat, Terrain terrain, TechniqueType tt ) { string ttStr = string.Empty; switch ( tt ) { case TechniqueType.HighLod: ttStr += "hl"; break; case TechniqueType.LowLod: ttStr += "ll"; break; case TechniqueType.RenderCompositeMap: ttStr += "rc"; break; } LogManager.Instance.Write( "AddTechique:" + ttStr, null ); Technique tech = mat.CreateTechnique(); //only supporting one pass Pass pass = tech.CreatePass(); GpuProgramManager gmgr = GpuProgramManager.Instance; HighLevelGpuProgramManager hmgr = HighLevelGpuProgramManager.Instance; if ( this.mShaderGen == null ) { bool check2x = this.mLayerNormalMappingEnabled || this.mLayerParallaxMappingEnabled; /* if (hmgr.IsLanguageSupported("cg") && (check2x && (gmgr.IsSyntaxSupported("fp40") || gmgr.IsSyntaxSupported("ps_2_x"))) || (gmgr.IsSyntaxSupported("ps_2_0"))) mShaderGen = new ShaderHelperCG(); else*/ if ( hmgr.IsLanguageSupported( "hlsl" ) ) { this.mShaderGen = new ShaderHelperHLSL(); } else if ( hmgr.IsLanguageSupported( "glsl" ) ) { this.mShaderGen = new ShaderHelperGLSL(); } else { //TODO } } HighLevelGpuProgram vprog = this.mShaderGen.GenerateVertexProgram( this, terrain, tt ); HighLevelGpuProgram fprog = this.mShaderGen.GenerateFragmentProgram( this, terrain, tt ); pass.SetVertexProgram( vprog.Name ); pass.SetFragmentProgram( fprog.Name ); if ( tt == TechniqueType.HighLod || tt == TechniqueType.RenderCompositeMap ) { //global normal map TextureUnitState tu = pass.CreateTextureUnitState(); tu.SetTextureName( terrain.TerrainNormalMap.Name ); tu.SetTextureAddressingMode( TextureAddressing.Clamp ); //global color map if ( terrain.IsGlobalColorMapEnabled && IsGlobalColorMapEnabled ) { tu = pass.CreateTextureUnitState( terrain.GlobalColorMap.Name ); tu.SetTextureAddressingMode( TextureAddressing.Clamp ); } //light map if ( IsLightMapEnabled ) { tu = pass.CreateTextureUnitState( terrain.LightMap.Name ); tu.SetTextureAddressingMode( TextureAddressing.Clamp ); } //blend maps uint maxLayers = GetMaxLayers( terrain ); uint numBlendTextures = Utility.Min( terrain.GetBlendTextureCount( (byte)maxLayers ), terrain.GetBlendTextureCount() ); uint numLayers = Utility.Min( maxLayers, (uint)terrain.LayerCount ); for ( uint i = 0; i < numBlendTextures; ++i ) { tu = pass.CreateTextureUnitState( terrain.GetBlendTextureName( (byte)i ) ); tu.SetTextureAddressingMode( TextureAddressing.Clamp ); } //layer textures for ( uint i = 0; i < numLayers; ++i ) { //diffuse / specular string name = terrain.GetLayerTextureName( (byte)i, 0 ); tu = pass.CreateTextureUnitState( terrain.GetLayerTextureName( (byte)i, 0 ) ); //normal / height tu = pass.CreateTextureUnitState( terrain.GetLayerTextureName( (byte)i, 1 ) ); } } //end if else if ( this.mCompositeMapEnabled ) { // LOW_LOD textures // composite map TextureUnitState tu = pass.CreateTextureUnitState(); tu.SetTextureName( terrain.CompositeMap.Name ); tu.SetTextureAddressingMode( TextureAddressing.Clamp ); // That's it! } }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="source"></param> protected abstract void GenerateFpLayer( SM2Profile prof, Terrain terrain, TechniqueType tt, uint layer, ref string source );
/// <summary> /// /// </summary> /// <param name="terrain"></param> /// <returns></returns> public override Material Generate( Terrain terrain ) { // re-use old material if exists Material mat = terrain._Material; if ( mat == null ) { MaterialManager matMgr = MaterialManager.Instance; // it's important that the names are deterministic for a given terrain, so // use the terrain pointer as an ID+ string matName = terrain.MaterialName; mat = (Material)matMgr.GetByName( matName ); if ( mat == null ) { mat = (Material)matMgr.Create( matName, ResourceGroupManager.DefaultResourceGroupName ); } } // clear everything mat.RemoveAllTechniques(); AddTechnique( mat, terrain, TechniqueType.HighLod ); //LOD if ( this.mCompositeMapEnabled ) { AddTechnique( mat, terrain, TechniqueType.LowLod ); var lodValues = new LodValueList(); lodValues.Add( 3000 ); //TerrainGlobalOptions.CompositeMapDistance); mat.SetLodLevels( lodValues ); Technique lowLodTechnique = mat.GetTechnique( 1 ); lowLodTechnique.LodIndex = 1; } UpdateParams( mat, terrain ); //mat.Compile(true); return mat; }
/// <summary> /// / /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="prog"></param> public virtual void DefaultVpParams( SM2Profile prof, Terrain terrain, TechniqueType tt, HighLevelGpuProgram prog ) { GpuProgramParameters gparams = prog.DefaultParameters; gparams.IgnoreMissingParameters = true; gparams.SetNamedAutoConstant( "worldMatrix", GpuProgramParameters.AutoConstantType.WorldMatrix, 0 ); gparams.SetNamedAutoConstant( "viewProjMatrix", GpuProgramParameters.AutoConstantType.ViewProjMatrix, 0 ); gparams.SetNamedAutoConstant( "lodMorph", GpuProgramParameters.AutoConstantType.Custom, Terrain.LOD_MORPH_CUSTOM_PARAM ); gparams.SetNamedAutoConstant( "fogParams", GpuProgramParameters.AutoConstantType.FogParams, 0 ); }
/// <summary> /// /// </summary> /// <param name="terrain"></param> /// <returns></returns> public override Material GenerateForCompositeMap( Terrain terrain ) { // re-use old material if exists Material mat = terrain._CompositeMapMaterial; if ( mat == null ) { MaterialManager matMgr = MaterialManager.Instance; // it's important that the names are deterministic for a given terrain, so // use the terrain pointer as an ID string matName = terrain.MaterialName + "/comp"; mat = (Material)matMgr.GetByName( matName ); if ( mat == null ) { mat = (Material)matMgr.Create( matName, ResourceGroupManager.DefaultResourceGroupName ); } } // clear everything mat.RemoveAllTechniques(); AddTechnique( mat, terrain, TechniqueType.RenderCompositeMap ); mat.Compile( true ); UpdateParamsForCompositeMap( mat, terrain ); return mat; }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="gpuparams"></param> public virtual void UpdateVpParams( SM2Profile prof, Terrain terrain, TechniqueType tt, GpuProgramParameters gpuparams ) { gpuparams.IgnoreMissingParameters = true; uint maxLayers = prof.GetMaxLayers( terrain ); uint numLayers = Utility.Min( maxLayers, (uint)terrain.LayerCount ); uint numUVMul = numLayers/4; if ( numUVMul%4 == 0 ) { ++numUVMul; } for ( uint i = 0; i < numUVMul; ++i ) { var uvMul = new Vector4( terrain.GetLayerUVMultiplier( (byte)( i*4 ) ), terrain.GetLayerUVMultiplier( (byte)( i*4 + 1 ) ), terrain.GetLayerUVMultiplier( (byte)( i*4 + 2 ) ), terrain.GetLayerUVMultiplier( (byte)( i*4 + 3 ) ) ); #if true gpuparams.SetNamedConstant( "uvMul" + i.ToString(), uvMul ); #endif } }
public override byte GetMaxLayers( Terrain terrain ) { // count the texture units free byte freeTextureUnits = 16; // lightmap --freeTextureUnits; // normalmap --freeTextureUnits; // colourmap if ( terrain.IsGlobalColorMapEnabled ) { --freeTextureUnits; } // TODO shadowmaps // each layer needs 2.25 units (1xdiffusespec, 1xnormalheight, 0.25xblend) return (byte)( freeTextureUnits/2.25f ); }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <returns></returns> protected override HighLevelGpuProgram CreateVertexProgram( SM2Profile prof, Terrain terrain, TechniqueType tt ) { HighLevelGpuProgramManager mgr = HighLevelGpuProgramManager.Instance; string progName = GetVertexProgramName( prof, terrain, tt ); var ret = (HighLevelGpuProgram)mgr.GetByName( progName ); if ( ret == null ) { ret = mgr.CreateProgram( progName, ResourceGroupManager.DefaultResourceGroupName, "cg", GpuProgramType.Vertex ); } else { ret.Unload(); } //ret.SetParam( "profiles", "vs_2_0 arbvp1" ); //ret.SetParam( "entry_point", "main_vp" ); ret.Properties[ "profiles" ] = "vs_2_0 arbvp1"; ret.Properties[ "entry_point" ] = "main_vp"; return ret; }
/// <summary> /// /// </summary> /// <param name="mat"></param> /// <param name="terrain"></param> public override void UpdateParams( Material mat, Terrain terrain ) { this.mShaderGen.UpdateParams( this, mat, terrain, false ); }
/// <summary> /// /// </summary> /// <param name="prof"></param> /// <param name="terrain"></param> /// <param name="tt"></param> /// <param name="source"></param> protected override void GenerateVpHeader( SM2Profile prof, Terrain terrain, TechniqueType tt, ref string source ) { source += "void main_vp(\n" + "float4 pos : POSITION,\n" + "float2 uv : TEXCOORD0,\n"; if ( tt != TechniqueType.RenderCompositeMap ) { source += "float2 delta : TEXCOORD1,\n"; // lodDelta, lodThreshold } source += "uniform float4x4 worldMatrix,\n" + "uniform float4x4 viewProjMatrix,\n" + "uniform float2 lodMorph,\n"; // morph amount, morph LOD target // uv multipliers uint maxLayers = prof.GetMaxLayers( terrain ); uint numLayers = Utility.Min( maxLayers, (uint)terrain.LayerCount ); uint numUVMutipliers = ( numLayers/4 ); if ( numLayers%4 != 0 ) { ++numUVMutipliers; } for ( uint i = 0; i < numUVMutipliers; ++i ) { source += "uniform float4 uvMul" + i + ", \n"; } source += "out float4 oPos : POSITION,\n" + "out float2 oUV : TEXCOORD0, \n" + "out float4 oPosObj : TEXCOORD1 \n"; // layer UV's premultiplied, packed as xy/zw uint numUVSets = numLayers/2; if ( numLayers%2 != 0 ) { ++numUVSets; } uint texCoordSet = 2; if ( tt != TechniqueType.LowLod ) { for ( uint i = 0; i < numUVSets; ++i ) { source += ", out float4 oUV" + i + " : TEXCOORD" + texCoordSet++ + "\n"; } } if ( prof.Parent.DebugLevel != 0 && tt != TechniqueType.RenderCompositeMap ) { source += ", out float2 lodInfo : TEXCOORD" + texCoordSet++ + "\n"; } source += ")\n" + "{\n" + " float4 worldPos = mul(worldMatrix, pos);\n" + " oPosObj = pos;\n"; if ( tt != TechniqueType.RenderCompositeMap ) { // determine whether to apply the LOD morph to this vertex // we store the deltas against all vertices so we only want to apply // the morph to the ones which would disappear. The target LOD which is // being morphed to is stored in lodMorph.y, and the LOD at which // the vertex should be morphed is stored in uv.w. If we subtract // the former from the latter, and arrange to only morph if the // result is negative (it will only be -1 in fact, since after that // the vertex will never be indexed), we will achieve our aim. // sign(vertexLOD - targetLOD) == -1 is to morph source += " float toMorph = -min(0, sign(delta.y - lodMorph.y));\n"; // this will either be 1 (morph) or 0 (don't morph) if ( prof.Parent.DebugLevel != 0 ) { // x == LOD level (-1 since value is target level, we want to display actual) source += "lodInfo.x = (lodMorph.y - 1) / " + terrain.NumLodLevels + ";\n"; // y == LOD morph source += "lodInfo.y = toMorph * lodMorph.x;\n"; } //morph switch ( terrain.Alignment ) { case Alignment.Align_X_Y: break; case Alignment.Align_X_Z: source += " worldPos.y += delta.x * toMorph * lodMorph.x;\n"; break; case Alignment.Align_Y_Z: break; } } // generate UVs if ( tt == TechniqueType.LowLod ) { //passtrough source += " oUV = uv;\n"; } else { for ( uint i = 0; i < numUVSets; ++i ) { uint layer = i*2; uint uvMulIdx = layer/4; source += " oUV" + i + ".xy = " + " uv.xy * uvMul" + uvMulIdx + "." + GetChannel( layer ) + ";\n"; source += " oUV" + i + ".zw = " + " uv.xy * uvMul" + uvMulIdx + "." + GetChannel( layer + 1 ) + ";\n"; } } }
/// <summary> /// /// </summary> /// <param name="mat"></param> /// <param name="terrain"></param> public override void UpdateParamsForCompositeMap( Material mat, Terrain terrain ) { this.mShaderGen.UpdateParams( this, mat, terrain, true ); }