/// <summary> /// Render /// </summary> /// <param name="setMat">Set matrix</param> /// <param name="techniqueName">Technique name</param> /// <param name="renderDelegate">Render delegate</param> public void RenderCave(Material setMat, //auto: List<Vector3> setLightPositions, BaseGame.RenderDelegate renderDelegate) { // And set all the other parameters detailGroundDiffuseTexture.SetValue(groundDiffuseTexture.XnaTexture); detailGroundNormalTexture.SetValue(groundNormalTexture.XnaTexture); detailGroundHeightTexture.SetValue(groundHeightTexture.XnaTexture); detailWallDiffuseTexture.SetValue(wallDiffuseTexture.XnaTexture); detailWallNormalTexture.SetValue(wallNormalTexture.XnaTexture); detailWallHeightTexture.SetValue(wallHeightTexture.XnaTexture); // Set all the basic parameters. SetParameters(setMat); // Set all light positions that are close to us. if (LightManager.closestLightsForRendering.Count != 6) throw new InvalidOperationException( "You must always set exactly " + LightManager.NumberOfLights + " lights for the shader!"); lightPositions.SetValue(LightManager.closestLightsForRendering.ToArray()); // Start effect (current technique should be set) xnaEffect.Begin(SaveStateMode.None); // Start first pass xnaEffect.CurrentTechnique.Passes[0].Begin(); // Render renderDelegate(); // End pass and shader xnaEffect.CurrentTechnique.Passes[0].End(); xnaEffect.End(); }
/// <summary> /// Create plane renderer /// </summary> /// <param name="setPos">Set position</param> /// <param name="setPlane">Set plane</param> /// <param name="setMaterial">Set material</param> /// <param name="setSize">Set size</param> public PlaneRenderer(Vector3 setPos, Plane setPlane, Material setMaterial, float setSize) { pos = setPos; plane = setPlane; material = setMaterial; size = setSize; }
/// <summary> /// Set parameters, this overload sets all material parameters too. /// </summary> public virtual void SetParametersOptimized(Material setMat) { // No need to set world matrix, will be done later in mesh rendering // in the MeshRenderManager. All the rest is set with help of the // SetParametersOptimizedGeneral above. // Only update ambient, diffuse, specular and the textures, the rest // will not change for a material change in MeshRenderManager. ambientColor.SetValue(setMat.ambientColor.ToVector4()); diffuseColor.SetValue(setMat.diffuseColor.ToVector4()); specularColor.SetValue(setMat.specularColor.ToVector4()); if (setMat.diffuseTexture != null) diffuseTexture.SetValue(setMat.diffuseTexture.XnaTexture); if (setMat.normalTexture != null) normalTexture.SetValue(setMat.normalTexture.XnaTexture); }
/// <summary> /// Set parameters, this overload sets all material parameters too. /// </summary> public virtual void SetParameters(Material setMat) { if (worldViewProj != null) worldViewProj.SetValue(BaseGame.WorldViewProjectionMatrix); if (viewProj != null) viewProj.SetValue(BaseGame.ViewProjectionMatrix); if (world != null) world.SetValue(BaseGame.WorldMatrix); if (viewInverse != null) viewInverse.SetValue(BaseGame.InverseViewMatrix); if (cameraPos != null) cameraPos.SetValue(BaseGame.CameraPos); //obs: if (lightDir != null) //obs: lightDir.SetValue(BaseGame.LightDirection); // Set all material properties if (setMat != null) { AmbientColor = setMat.ambientColor; DiffuseColor = setMat.diffuseColor; SpecularColor = setMat.specularColor; SpecularPower = setMat.specularPower; DiffuseTexture = setMat.diffuseTexture; NormalTexture = setMat.normalTexture; SpecularTexture = setMat.specularTexture; Time = BaseGame.TotalTime; } // if (setMat) }
/// <summary> /// Render single pass shader, little faster and simpler than /// Render and it just uses the current technique and renderes only /// the first pass (most shaders have only 1 pass anyway). /// Used for MeshRenderManager! /// </summary> /// <param name="renderDelegate">Render delegate</param> public void RenderSinglePassShader( Material setMat, //always use the LightManager! List<Vector3> setLightPositions, BaseGame.RenderDelegate renderDelegate) { SetParameters(setMat); // Set all light positions that are close to us. //NOTE: We are only using 6 lights for the cave itself, all the // static and animated models are just using 3 lights (faster). if (LightManager.closestLightsForRendering.Count < 3) throw new InvalidOperationException( "You must always have at least 3 lights for the shader!"); if (lightPositions != null) lightPositions.SetValue( LightManager.closestLightsForRendering.GetRange(0, 3).ToArray()); // Start effect (current technique should be set) xnaEffect.Begin(SaveStateMode.None); // Start first pass xnaEffect.CurrentTechnique.Passes[0].Begin(); // Render renderDelegate(); // End pass and shader xnaEffect.CurrentTechnique.Passes[0].End(); xnaEffect.End(); }
/// <summary> /// Render /// </summary> /// <param name="setMat">Set matrix</param> /// <param name="techniqueName">Technique name</param> /// <param name="renderDelegate">Render delegate</param> public void RenderNoLight(Material setMat, string techniqueName, BaseGame.RenderDelegate renderDelegate) { SetParameters(setMat); /*will become important later in the book. // Can we do the requested technique?0 // For graphic cards not supporting ps2.0, fall back to ps1.1 if (BaseGame.CanUsePS20 == false && techniqueName.EndsWith("20")) // Use same technique without the 20 ending! techniqueName = techniqueName.Substring(0, techniqueName.Length - 2); */ // Start shader xnaEffect.CurrentTechnique = xnaEffect.Techniques[techniqueName]; xnaEffect.Begin(SaveStateMode.None); // Render all passes (usually just one) //foreach (EffectPass pass in effect.CurrentTechnique.Passes) for (int num = 0; num < xnaEffect.CurrentTechnique.Passes.Count; num++) { EffectPass pass = xnaEffect.CurrentTechnique.Passes[num]; pass.Begin(); renderDelegate(); pass.End(); } // foreach (pass) // End shader xnaEffect.End(); }
/*not used anymore, works fine, but we had problems at the GDC exporting * shader material data in 3DS Max 9 (always crashes the exporter). * Instead the AutoAssignMaterial method below is used. /// <summary> /// Load material information from a collada file /// </summary> /// <param name="colladaFile">Collada file xml node</param> private void LoadMaterial(XmlNode colladaFile) { // First get all textures, if there are none, ignore and quit. XmlNode texturesNode = XmlHelper.GetChildNode(colladaFile, "library_images"); if (texturesNode == null) return; // Get all used texture images Dictionary<string, Texture> textures = new Dictionary<string, Texture>(); foreach (XmlNode textureNode in texturesNode) { if (textureNode.Name == "image") { string filename = XmlHelper.GetChildNode(textureNode, "init_from").InnerText; textures.Add( XmlHelper.GetXmlAttribute(textureNode, "id"), new Texture(StringHelper.ExtractFilename(filename, true))); } // if (texture.name) else throw new InvalidOperationException( "Unknown Node " + textureNode.Name + " found in library_images"); } // foreach (texture) // Load all effects to find out the used effect in our material XmlNode effectsNode = XmlHelper.GetChildNode(colladaFile, "library_effects"); if (effectsNode == null) throw new InvalidOperationException( "library_effects node not found while loading Collada file " +name); Dictionary<string, string> effectIds = new Dictionary<string, string>(); foreach (XmlNode effectNode in effectsNode) { XmlNode fileNode = XmlHelper.GetChildNode(effectNode, "import"); if (fileNode == null) { // Use "include" node instead, this one is used when we got valid // techniques selected in the material (was sometimes used collada // 1.4 and different versions of collada exporters than ColladaMax). fileNode = XmlHelper.GetChildNode(effectNode, "include"); // Still null? if (fileNode == null) throw new InvalidOperationException( "Import or include node not found in effect node, file: " +name); } // if (filenode) effectIds.Add( XmlHelper.GetXmlAttribute(effectNode, "id"), XmlHelper.GetXmlAttribute(fileNode, "url")); } // foreach (effect) // And finally get all material nodes, but we only support one material // here, we will use the first one that uses shaders and ignore the rest. XmlNode materialsNode = XmlHelper.GetChildNode(colladaFile, "library_materials"); if (materialsNode == null) throw new InvalidOperationException( "library_materials node not found while loading Collada file "+name); foreach (XmlNode materialNode in materialsNode) { if (materialNode.Name == "material") { Material newMaterial = new Material(materialNode, textures, effectIds); if (material == null || newMaterial.shader != null) material = newMaterial; } // if (materialNode.name) else throw new InvalidOperationException("Unknown Node " + materialNode.Name + " found in library_materials"); } // foreach (material) } // LoadMaterial(colladaFile, TextureIDDictionary, MaterialIDDictionary)' */ /// <summary> /// Auto assign material /// </summary> protected void AutoAssignMaterial() { // Just load the material from the name of this model material = new Material( name, name + "Normal", name + "Specular"); // Custom material stuff for Cave (detail maps and different shader) // is handled in the CavePointNormalMapping class. // But make sure to use black for ambient, very bright yellow for // diffuse and white for specular. if (isCave) { material.ambientColor = Color.Black; material.diffuseColor = new Color(255, 255, 240); material.specularColor = Color.White; material.specularPower = 22; } // if (name) else if (name.Contains("Goblin") || name.Contains("Orge")) { // Use a higher specular for the monsters. material.specularPower = 16; material.specularColor = new Color(180, 180, 180); // Increase ambient a little (better visibility of monsters) material.ambientColor = new Color(80, 80, 80); } // else if }
/// <summary> /// Update parameters /// </summary> public override void SetParameters(Material setMat) { // Can't set parameters if loading failed! if (xnaEffect == null) return; /*already set, don't change! shadowNearPlane = 1.0f; shadowFarPlane = 28; virtualLightDistance = 24; virtualVisibleRange = 23.5f; */ //if (BaseGame.CanUsePS20) //{ compareDepthBias = 0.0025f;// 0.0075f;//0.00025f; shadowMapDepthBiasValue = 0.0025f;// 0.0075f;//0.00025f; /*not supported anyway!} // if (BaseGame.CanUsePS20) else { // Ps 1.1 isn't as percise! compareDepthBias = 0.0025f; shadowMapDepthBiasValue = 0.002f; } // else */ base.SetParameters(setMat); // Set all extra parameters for this shader depthBias.SetValue(compareDepthBias); shadowMapDepthBias.SetValue(shadowMapDepthBiasValue); shadowMapTexelSize.SetValue( new Vector2(texelWidth, texelHeight)); nearPlane.SetValue(shadowNearPlane); farPlane.SetValue(shadowFarPlane); }