/// <summary> /// Update per frame data /// </summary> /// <param name="world">World matrix</param> /// <param name="context">Context</param> public override void UpdatePerFrame( Matrix world, DrawContextShadows context) { var viewProjection = context.ShadowMap.FromLightViewProjectionArray; if (viewProjection != null && viewProjection.Length > 0) { if (viewProjection.Length != MaxCascades) { throw new EngineException($"The matrix array must have a length of {MaxCascades}"); } var m = new Matrix[viewProjection.Length]; for (int i = 0; i < viewProjection.Length; i++) { m[i] = world * viewProjection[i]; } this.WorldViewProjectionArray = m; } else { this.WorldViewProjectionArray = null; } }
/// <summary> /// Draws the gardener shadows /// </summary> /// <param name="context">Context</param> public override void DrawShadows(DrawContextShadows context) { if (this.visibleNodes.Any()) { var graphics = this.Game.Graphics; graphics.SetBlendDefaultAlpha(); foreach (var item in this.visibleNodes) { this.DrawShadowsNode(context, item); } } }
/// <summary> /// Sets thecnique for vegetation drawing in shadow mapping /// </summary> /// <param name="context">Drawing context</param> /// <param name="channel">Channel</param> /// <returns>Returns the selected technique</returns> private EngineEffectTechnique SetTechniqueVegetationShadowMap(DrawContextShadows context, int channel) { var channelData = this.foliageMapChannels[channel]; var effect = DrawerPool.EffectShadowFoliage; #region Per frame update effect.UpdatePerFrame( context.ViewProjection, context.EyePosition, this.WindDirection, this.WindStrength * channelData.WindEffect, this.windTime * channelData.WindEffect, channelData.Delta, this.textureRandom); #endregion #region Per object update effect.UpdatePerObject( channelData.StartRadius, channelData.EndRadius, channelData.TextureCount, channelData.Textures); #endregion if (channelData.Count == 1) { return(effect.ShadowMapFoliage4); } if (channelData.Count == 2) { return(effect.ShadowMapFoliage8); } if (channelData.Count == 4) { return(effect.ShadowMapFoliage16); } else { return(null); } }
/// <summary> /// Draws the node shadows /// </summary> /// <param name="context">Context</param> /// <param name="item">Node</param> private void DrawShadowsNode(DrawContextShadows context, QuadTreeNode item) { var buffers = this.foliageBuffers.FindAll(b => b.CurrentPatch?.CurrentNode == item); if (buffers.Count > 0) { foreach (var buffer in buffers) { var vegetationTechnique = this.SetTechniqueVegetationShadowMap(context, buffer.CurrentPatch.Channel); if (vegetationTechnique != null) { this.BufferManager.SetInputAssembler( vegetationTechnique, buffer.VertexBuffer.Slot, Topology.PointList); buffer.DrawFoliageShadows(vegetationTechnique); } } } }
/// <summary> /// Draw shadows /// </summary> /// <param name="context"></param> public override void DrawShadows(DrawContextShadows context) { if (this.DrawingData == null) { return; } var effect = context.ShadowMap.GetEffect(); if (effect == null) { return; } int count = 0; foreach (string meshName in this.DrawingData.Meshes.Keys) { count += DrawMeshShadow(context, effect, meshName); } }
/// <summary> /// Draw shadows /// </summary> /// <param name="context">Context</param> public override void DrawShadows(DrawContextShadows context) { if (this.visibleNodes.Any()) { var graphics = this.Game.Graphics; var sceneryEffect = context.ShadowMap.GetEffect(); if (sceneryEffect != null) { sceneryEffect.UpdatePerFrame(Matrix.Identity, context); graphics.SetBlendDefault(); foreach (var node in visibleNodes) { this.patchDictionary[node.Id].Current = node; this.patchDictionary[node.Id].DrawSceneryShadows(sceneryEffect, this.BufferManager); } } } }
/// <summary> /// Draws a mesh shadow /// </summary> /// <param name="context">Context</param> /// <param name="effect">Effect</param> /// <param name="meshName">Mesh name</param> /// <returns>Returns the number of drawn triangles</returns> private int DrawMeshShadow(DrawContextShadows context, IShadowMapDrawer effect, string meshName) { int count = 0; var graphics = this.Game.Graphics; var meshDict = this.DrawingData.Meshes[meshName]; var localTransform = this.GetTransformByName(meshName); effect.UpdatePerFrame(localTransform, context); foreach (string materialName in meshDict.Keys) { var mesh = meshDict[materialName]; var material = this.DrawingData.Materials[materialName]; effect.UpdatePerObject(this.AnimationOffset, material, this.TextureIndex); this.BufferManager.SetIndexBuffer(mesh.IndexBuffer.Slot); var technique = effect.GetTechnique(mesh.VertextType, false, material.Material.IsTransparent); this.BufferManager.SetInputAssembler(technique, mesh.VertexBuffer.Slot, mesh.Topology); count += mesh.IndexBuffer.Count > 0 ? mesh.IndexBuffer.Count / 3 : mesh.VertexBuffer.Count / 3; for (int p = 0; p < technique.PassCount; p++) { graphics.EffectPassApply(technique, p, 0); mesh.Draw(graphics); } } return(count); }
/// <summary> /// Draw shadows /// </summary> /// <param name="context">Context</param> public virtual void DrawShadows(DrawContextShadows context) { }
/// <summary> /// Update per frame data /// </summary> /// <param name="world">World matrix</param> /// <param name="context">Context</param> public abstract void UpdatePerFrame( Matrix world, DrawContextShadows context);
/// <summary> /// Shadow Drawing /// </summary> /// <param name="context">Context</param> public override void DrawShadows(DrawContextShadows context) { if (this.hasDataToWrite) { this.BufferManager.WriteInstancingData(this.instancingData); } if (this.VisibleCount <= 0) { return; } var effect = context.ShadowMap.GetEffect(); if (effect == null) { return; } int count = 0; int instanceCount = 0; effect.UpdatePerFrame(Matrix.Identity, context); int maxCount = this.GetMaxCount(); //Render by level of detail for (int l = 1; l < (int)LevelOfDetail.Minimum + 1; l *= 2) { if (maxCount <= 0) { break; } LevelOfDetail lod = (LevelOfDetail)l; //Get instances in this LOD var lodInstances = Array.FindAll(this.instancesTmp, i => i != null && i.LevelOfDetail == lod); if (lodInstances.Length <= 0) { continue; } var drawingData = this.GetDrawingData(lod); if (drawingData == null) { continue; } var index = Array.IndexOf(this.instancesTmp, lodInstances[0]); var length = Math.Min(maxCount, lodInstances.Length); if (length <= 0) { continue; } maxCount -= length; instanceCount += length; foreach (string meshName in drawingData.Meshes.Keys) { count += this.DrawMeshShadow(effect, drawingData, meshName, index, length); count *= instanceCount; } } }
/// <summary> /// Update per frame data /// </summary> /// <param name="world">World matrix</param> /// <param name="context">Context</param> public override void UpdatePerFrame( Matrix world, DrawContextShadows context) { this.WorldViewProjection = world * context.ShadowMap.FromLightViewProjectionArray[0]; }