private void VertexPrimitiveCombo_SelectedIndexChanged(object sender, EventArgs e) { m_Surface.Data.Clear(); VertexPrimitive vertexPrimitive = (VertexPrimitive)VertexPrimitiveCombo.SelectedIndex; m_Surface.VertexPrimitive = vertexPrimitive; m_Surface.UseIndices = false; Random rand = new Random(); string descriptionText = string.Empty; switch (vertexPrimitive) { case VertexPrimitive.Points: { descriptionText = "Each vertex represents a 3d point"; m_Surface.FrameMode = SurfaceFrameMode.Dots; for (int i = 0; i < 10000; i++) { m_Surface.Data.AddValue(rand.Next(100), rand.Next(100), rand.Next(100)); } } break; case VertexPrimitive.Lines: { descriptionText = "Each consecutive pair of vertices represents a line segment"; m_Surface.FrameMode = SurfaceFrameMode.Dots; for (int i = 0; i < 200; i++) { m_Surface.Data.AddValue(rand.Next(100), rand.Next(100), rand.Next(100)); m_Surface.Data.AddValue(rand.Next(100), rand.Next(100), rand.Next(100)); } } break; case VertexPrimitive.LineLoop: case VertexPrimitive.LineStrip: { descriptionText = "Adjacent vertices are connected with a line segment"; for (int i = 0; i < 5; i++) { m_Surface.Data.AddValue(rand.Next(100), rand.Next(100), rand.Next(100)); } } break; case VertexPrimitive.Triangles: { descriptionText = "Each three consequtive vertices are considered a triangle"; m_Surface.FrameMode = SurfaceFrameMode.Mesh; NVector3DD top = new NVector3DD(0.5, 1, 0.5); NVector3DD baseA = new NVector3DD(0, 0, 0); NVector3DD baseB = new NVector3DD(1, 0, 0); NVector3DD baseC = new NVector3DD(1, 0, 1); NVector3DD baseD = new NVector3DD(0, 0, 1); m_Surface.Data.AddValue(top); m_Surface.Data.AddValue(baseA); m_Surface.Data.AddValue(baseB); m_Surface.Data.AddValue(top); m_Surface.Data.AddValue(baseB); m_Surface.Data.AddValue(baseC); m_Surface.Data.AddValue(top); m_Surface.Data.AddValue(baseC); m_Surface.Data.AddValue(baseD); m_Surface.Data.AddValue(top); m_Surface.Data.AddValue(baseD); m_Surface.Data.AddValue(baseA); } break; case VertexPrimitive.TriangleStrip: { descriptionText = "A series of connected triangles that share common vertices"; m_Surface.FrameMode = SurfaceFrameMode.Mesh; NVector3DD A = new NVector3DD(0, 0, 0); NVector3DD B = new NVector3DD(1, 0, 0); NVector3DD C = new NVector3DD(0, 1, 1); NVector3DD D = new NVector3DD(1, 1, 1); m_Surface.Data.AddValue(A); m_Surface.Data.AddValue(B); m_Surface.Data.AddValue(C); m_Surface.Data.AddValue(D); } break; case VertexPrimitive.TriangleFan: { descriptionText = "A series of connected triangles that share a common vertex"; m_Surface.FrameMode = SurfaceFrameMode.Mesh; m_Surface.Data.AddValue(0, 100, 0); int steps = 10; for (int i = 0; i < 3000; i++) { double angle = i * 2 * Math.PI / steps; m_Surface.Data.AddValue(Math.Cos(angle) * 100, 0, Math.Sin(angle) * 100); } } break; case VertexPrimitive.Quads: { descriptionText = "Each for consecutive vertices form a quad"; m_Surface.FrameMode = SurfaceFrameMode.Mesh; NVector3DD A = new NVector3DD(0, 0, 0); NVector3DD B = new NVector3DD(1, 0, 0); NVector3DD C = new NVector3DD(0, 1, 1); NVector3DD D = new NVector3DD(1, 1, 1); m_Surface.Data.AddValue(A); m_Surface.Data.AddValue(B); m_Surface.Data.AddValue(D); m_Surface.Data.AddValue(C); } break; case VertexPrimitive.QuadStrip: { descriptionText = "A series of connected quads that share common vertices"; m_Surface.FrameMode = SurfaceFrameMode.Mesh; NVector3DD A = new NVector3DD(0, 0, 0); NVector3DD B = new NVector3DD(1, 0, 0); NVector3DD C = new NVector3DD(0, 1, 1); NVector3DD D = new NVector3DD(1, 1, 1); NVector3DD E = new NVector3DD(0, 2, 2); NVector3DD F = new NVector3DD(1, 2, 2); m_Surface.Data.AddValue(A); m_Surface.Data.AddValue(B); m_Surface.Data.AddValue(C); m_Surface.Data.AddValue(D); m_Surface.Data.AddValue(E); m_Surface.Data.AddValue(F); } break; } nChartControl1.Labels[0].Text = "Vertex Surface<br/><font size='10pt'>" + descriptionText + "</font>"; nChartControl1.Refresh(); }
/// <summary> /// Generates the shadow map to be used when rendering this light. /// </summary> /// <remarks>If this instance is not to cast shadows the shadow map is cleared.</remarks> /// <param name="renderSystem">The render system to render with.</param> /// <param name="shadowMap">The shadow map to render on</param> protected virtual void GenerateShadowMap(DeferredRenderSystem renderSystem, RenderTarget2D shadowMap) { RenderTarget2D intermediateShadowMap = renderSystem.RenderTargets.GetTemporaryRenderTarget(SurfaceFormat.Color); // Intermediate map used for selective sampling RectangleF lightDrawBounds = this.GetWorldDrawBounds(); renderSystem.GraphicsDevice.SetRenderTarget(shadowMap); renderSystem.ClearCurrentRenderTarget(Color.White); // Clear the core shadow map // Only render the shadows if we are to cast them if (this.CastsShadows) { // Render the shadow caused by each object within the lights range List <SpriteBase> objectList = this.World.GetSpriteObjectsInArea(lightDrawBounds).Where(currObj => (currObj.RenderOptions & SpriteRenderOptions.CastsShadows) != 0).OrderBy(s => s.LayerDepth).ToList(); if (objectList.Count > 0) { int lastLayerDepth = 0; int lastLayerDepthIndex = 0; bool renderedShadow = false; // This is used so that we don't bother occluding objects if we didn't even render anything lastLayerDepth = (int)objectList[0].LayerDepth; for (int objectIndex = 0; objectIndex < objectList.Count; objectIndex++) { SpriteBase currObj = objectList[objectIndex]; RectangleF spriteWorldBounds = currObj.SpriteWorldBounds; // If the object we found doesn't cast shadows (or we're inside it), skip it if (spriteWorldBounds.Contains(base.Position)) { continue; } this.shadowMapShader.ConfigureShader(renderSystem); // Configure the shader this.shadowMapShader.GetParameter("viewProjection").SetValue(renderSystem.GameCamera.GetViewProjectionMatrix(renderSystem)); this.shadowMapShader.GetParameter("cameraPosition").SetValue(renderSystem.GameCamera.PixelPosition); // If we switched light planes remove occlusion from all previous objects if (lastLayerDepth != (int)currObj.LayerDepth) { // Only occlude if we actually rendered something if (renderedShadow) { // Loop through all the objects between the last layer index and the current index for (int clearObjIndex = lastLayerDepthIndex; clearObjIndex < objectIndex; clearObjIndex++) { this.ProcessSpriteDepthTransition(renderSystem, objectList[clearObjIndex]); } } // Save the last values lastLayerDepth = (int)currObj.LayerDepth; lastLayerDepthIndex = objectIndex; renderedShadow = false; // Reset this } // Create the shadow map caused by the current sprite this.shadowMapShader.ApplyPass(0); // Construct the vertex primitive to mask with Vector2[] extrema; if (currObj.SpriteWorldShape != null) { extrema = currObj.SpriteWorldShape.GetRelativeExtrema(base.Position); // Get the extrema that cause the shadow } else { extrema = spriteWorldBounds.GetRelativeExtrema(base.Position); // Get the extrema that cause the shadow } Vector2 widthVector = Vector2.Normalize(extrema[0] - base.Position); // Get the vector to the first extrema Vector2 heightVector = Vector2.Normalize(extrema[1] - base.Position); // Get the vector to the second extrema VertexPrimitive shadowArea = new VertexPrimitive(PrimitiveType.TriangleStrip, 4); shadowArea.Add(extrema[0]); shadowArea.Add(extrema[1]); // Let's extend the shadow vector until it hits the edge of the draw bounds shadowArea.Add(lightDrawBounds.CastInternalRay(extrema[0], widthVector)); shadowArea.Add(lightDrawBounds.CastInternalRay(extrema[1], heightVector)); // Let's get the remaining verts that might exist to finish up the rect List <Vector2> interiorVerts = lightDrawBounds.GetInteriorVertices(base.Position, widthVector, heightVector); shadowArea.Add(interiorVerts); // Add the interior verts (if any exist) renderSystem.DirectScreenPaint(shadowArea); // Render the shadow renderedShadow = true; // We just rendered a shadow; keep track of that } // Loop through all the objects between the last layer index and the current index if (renderedShadow) { // Remove the shadows over the LAST shadow plane for (int clearObjIndex = lastLayerDepthIndex; clearObjIndex < objectList.Count; clearObjIndex++) { this.ProcessSpriteDepthTransition(renderSystem, objectList[clearObjIndex]); } // Blur the shadow map if enabled if (!float.IsPositiveInfinity(this.minShadowBlurDistance)) { renderSystem.GraphicsDevice.SetRenderTarget(intermediateShadowMap); // We need to render to a temp target // Configure the shader this.shadowMapShader.ConfigureShader(renderSystem, 1); // Set parameters this.shadowMapShader.GetParameter("viewProjection").SetValue(renderSystem.GameCamera.GetViewProjectionMatrix(renderSystem)); this.shadowMapShader.GetParameter("cameraPosition").SetValue(renderSystem.GameCamera.PixelPosition); this.shadowMapShader.GetParameter("lightPosition").SetValue(base.PixelPosition); this.shadowMapShader.GetParameter("maxBlurDistance").SetValue(this.World.GetPixelFromWorld(this.maxShadowBlurDistance)); this.shadowMapShader.GetParameter("minBlurDistance").SetValue(this.World.GetPixelFromWorld(this.maxShadowBlurDistance)); this.shadowMapShader.GetParameter("shadowMap").SetValue(shadowMap); this.shadowMapShader.ApplyPass(0); renderSystem.DirectScreenPaint(lightDrawBounds); // Render the shadow renderSystem.GraphicsDevice.SetRenderTarget(shadowMap); // Set the shadow map for final render // Update shadow map this.shadowMapShader.GetParameter("shadowMap").SetValue(intermediateShadowMap); this.shadowMapShader.ApplyPass(0); renderSystem.DirectScreenPaint(lightDrawBounds); // Render } } } } renderSystem.SetRenderTargets(RenderTargetTypes.None, 0); // Resolve the render target renderSystem.RenderTargets.ReleaseTemporaryRenderTarget(intermediateShadowMap); }