private void DrawSpotLight(SpotLight sl, bool renderShadows = false) { sl.lightDirection.Normalize(); //lightPosition = camera.Position + (Vector3.Right + Vector3.Down) * 10; //spotDirection = camera.Forward; //set the G-Buffer parameters spotLightEffect.Parameters["colorMap"].SetValue(colorRT); spotLightEffect.Parameters["normalMap"].SetValue(normalRT); spotLightEffect.Parameters["depthMap"].SetValue(depthRT); spotLightEffect.Parameters["transMap"].SetValue(transRT); //compute the light world matrix //scale according to light radius, and translate it to light position Matrix spotMatrix = Matrix.CreateFromQuaternion(QuaternionLookRotation(sl.lightDirection)); spotMatrix.Translation = sl.lightPosition; float spotAngleRad = MathHelper.ToRadians(sl.spotAngle); float tan = (float)Math.Tan(spotAngleRad); Matrix sphereWorldMatrix = Matrix.CreateScale(sl.lightRadius * tan, sl.lightRadius * tan, sl.lightRadius) * spotMatrix; float cosSpotAngle = (float)Math.Cos(spotAngleRad); int currentTechnique = 0; if (renderShadows) { GraphicsDevice.SetRenderTarget(null); GraphicsDevice.SetRenderTargets(shadowRTColor, shadowRTDepth); GraphicsDevice.BlendState = BlendState.Opaque; clearBufferEffect.CurrentTechnique = clearBufferEffect.Techniques[1]; clearBufferEffect.Techniques[1].Passes[0].Apply(); quadRenderer.Render(Vector2.One * -1, Vector2.One); Matrix spotProj = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(sl.spotAngle * 2), 1, 0.01f * sl.lightRadius, sl.lightRadius); Matrix spotView = Matrix.CreateLookAt(sl.lightPosition, sl.lightPosition + sl.lightDirection, Vector3.Up); //scene.DrawSceneShadow(inverseTransform, spotProj, currentModel); scene.DrawSceneShadow(spotView, spotProj, currentModel, 1); GraphicsDevice.SetRenderTarget(null); GraphicsDevice.SetRenderTarget(lightRT); GraphicsDevice.BlendState = BlendState.AlphaBlend; GraphicsDevice.DepthStencilState = DepthStencilState.None; spotLightEffect.Parameters["ShadowInvertViewProjection"].SetValue((spotView * spotProj)); //spotLightEffect.Parameters["ShadowView"].SetValue((spotView)); //spotLightEffect.Parameters["ShadowProjection"].SetValue((spotProj)); spotLightEffect.Parameters["shadowMapColor"].SetValue(shadowRTColor); spotLightEffect.Parameters["shadowMapDepth"].SetValue(shadowRTDepth); spotLightEffect.Parameters["shadowHalfPixel"].SetValue(shadowHalfPixel); currentTechnique = 1; } spotLightEffect.Parameters["World"].SetValue(sphereWorldMatrix); spotLightEffect.Parameters["View"].SetValue(camera.View); spotLightEffect.Parameters["Projection"].SetValue(camera.Projection); //light position spotLightEffect.Parameters["lightPosition"].SetValue(sl.lightPosition); //set the color, radius and Intensity spotLightEffect.Parameters["Color"].SetValue(sl.lightColor.ToVector3()); spotLightEffect.Parameters["lightRadius"].SetValue(sl.lightRadius); spotLightEffect.Parameters["lightIntensity"].SetValue(sl.lightIntensity); spotLightEffect.Parameters["spotDirection"].SetValue(sl.lightDirection); spotLightEffect.Parameters["spotLightAngleCosine"].SetValue(cosSpotAngle); spotLightEffect.Parameters["spotDecayExponent"].SetValue(10f); //parameters for specular computations spotLightEffect.Parameters["cameraPosition"].SetValue(camera.Position); spotLightEffect.Parameters["InvertViewProjection"].SetValue(Matrix.Invert(camera.View * camera.Projection)); //size of a halfpixel, for texture coordinates alignment spotLightEffect.Parameters["halfPixel"].SetValue(halfPixel); //calculate the distance between the camera and light center float cameraToCenter = Vector3.Distance(camera.Position, sl.lightPosition); //if we are inside the light volume, draw the sphere's inside face if (cameraToCenter < sl.lightRadius) { GraphicsDevice.RasterizerState = RasterizerState.CullClockwise; } else { GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; } // GraphicsDevice.DepthStencilState = DepthStencilState.None; spotLightEffect.CurrentTechnique = spotLightEffect.Techniques[currentTechnique]; spotLightEffect.Techniques[currentTechnique].Passes[0].Apply(); foreach (ModelMesh mesh in spotModel.Meshes) { foreach (ModelMeshPart meshPart in mesh.MeshParts) { GraphicsDevice.Indices = meshPart.IndexBuffer; GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer); GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount); } } GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; // GraphicsDevice.DepthStencilState = DepthStencilState.Default; }
/// <summary> /// Allows the game component to update itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> public override void Update(GameTime gameTime) { if (showStuff) { for (int i = pointList.GetLength(0) - 1; i > 0; i--) { pointList[i].Position.Y = pointList[i - 1].Position.Y; } } KeyboardState hit = new KeyboardState(); hit = Keyboard.GetState(); int previousModel = currentModel; int previousRes = currentRes; if (hit.IsKeyDown(Keys.Multiply) && previousState.IsKeyUp(Keys.Multiply) && currentModel < 6) { currentModel++; } if (hit.IsKeyDown(Keys.Divide) && previousState.IsKeyUp(Keys.Divide) && currentModel > 4) { currentModel--; } //if (hit.IsKeyDown(Keys.Add) && previousState.IsKeyUp(Keys.Add)) // n++; //if (hit.IsKeyDown(Keys.Subtract) && previousState.IsKeyUp(Keys.Subtract) && n > 0) // n--; if (hit.IsKeyDown(Keys.D1) && previousState.IsKeyUp(Keys.D1)) { currentRes = 1; LoadContent(); } if (hit.IsKeyDown(Keys.D2) && previousState.IsKeyUp(Keys.D2)) { currentRes = 2; LoadContent(); } if (hit.IsKeyDown(Keys.D3) && previousState.IsKeyUp(Keys.D3)) { currentRes = 3; LoadContent(); } if (hit.IsKeyDown(Keys.T) && previousState.IsKeyUp(Keys.T)) { showStuff = !showStuff; } if (hit.IsKeyDown(Keys.Y) && previousState.IsKeyUp(Keys.Y)) { lastRT = previewRT; } if (hit.IsKeyDown(Keys.U) && previousState.IsKeyUp(Keys.U)) { lastRT = colorRT; } if (hit.IsKeyDown(Keys.I) && previousState.IsKeyUp(Keys.I)) { lastRT = normalRT; } if (hit.IsKeyDown(Keys.O) && previousState.IsKeyUp(Keys.O)) { lastRT = lightRT; } if (hit.IsKeyDown(Keys.P) && previousState.IsKeyUp(Keys.P)) { lastRT = shadowRTColor; } //if (hit.IsKeyDown(Keys.L) && previousState.IsKeyUp(Keys.L)) //{ // lastRT = shadowRTDepth; //} if (hit.IsKeyDown(Keys.M) && previousState.IsKeyUp(Keys.M)) { lastRT = depthRT; } if (hit.IsKeyDown(Keys.LeftAlt) && hit.IsKeyDown(Keys.N) && previousState.IsKeyUp(Keys.N)) { if (spotLights.Count > 0) { spotLights.RemoveAt(spotLights.Count - 1); } } else if (hit.IsKeyDown(Keys.N) && previousState.IsKeyUp(Keys.N)) { SpotLight spot = new SpotLight() { lightPosition = camera.Position, lightColor = colors[spotLights.Count % 10], lightRadius = 500, lightIntensity = 2, lightDirection = camera.Forward, spotAngle = 15, decay = 10 }; spotLights.Add(spot); } if (hit.IsKeyDown(Keys.B) && previousState.IsKeyUp(Keys.B)) { spotLights.Clear(); } if (hit.IsKeyDown(Keys.V) && previousState.IsKeyUp(Keys.V)) { doShadows = !doShadows; } if (hit.IsKeyDown(Keys.RightShift) && previousState.IsKeyUp(Keys.RightShift)) { if (shadowRes * 2 <= 4096) { shadowRes *= 2; LoadContent(); } } if (hit.IsKeyDown(Keys.RightControl) && previousState.IsKeyUp(Keys.RightControl)) { if (shadowRes / 2 >= 128) { shadowRes /= 2; LoadContent(); } } if (hit.IsKeyDown(Keys.K) || previousRes != currentRes || previousModel != currentModel) { framesTime = 0; frameCount = 0; } if (hit.IsKeyDown(Keys.H) && previousState.IsKeyUp(Keys.H)) { vScale -= 0.01f; } if (hit.IsKeyDown(Keys.J) && previousState.IsKeyUp(Keys.J)) { vScale += 0.01f; } if (hit.IsKeyDown(Keys.G) && previousState.IsKeyUp(Keys.G)) { vScale = 0f; } previousState = hit; base.Update(gameTime); double prevDur = hpt.Duration; hpt.Stop(); double nowDur = hpt.Duration; timeSinceLastUpdate = nowDur - prevDur; }
/// <summary> /// Allows the game component to perform any initialization it needs to before starting /// to run. This is where it can query for any required services and load content. /// </summary> public override void Initialize() { // TODO: Add your initialization code here base.Initialize(); hpt.Start(); hpt.Stop(); camera = new Camera(Game); camera.CameraArc = -30; camera.CameraDistance = 50; quadRenderer = new QuadRenderComponent(Game); Game.Components.Add(camera); Game.Components.Add(quadRenderer); previousState = Keyboard.GetState(); spotLights = new List <SpotLight>(); { // graph code int n = 300; //GeneratePoints generates a random graph, implementation irrelevant pointList = new VertexPositionColor[n]; int height = 300; int minY = 0; for (int i = 0; i < n; i++) { pointList[i] = new VertexPositionColor() { Position = new Vector3(i * 10, 0, 0), Color = Color.Red } } ; //links the points into a list lineListIndices = new short[(n * 2) - 2]; for (int i = 0; i < n - 1; i++) { lineListIndices[i * 2] = (short)(i); lineListIndices[(i * 2) + 1] = (short)(i + 1); } worldMatrix = Matrix.Identity; viewMatrix = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up); projectionMatrix = Matrix.CreateOrthographicOffCenter(0, (float)GraphicsDevice.Viewport.Width, 0, (float)GraphicsDevice.Viewport.Height, 1.0f, 1000.0f); basicEffect = new BasicEffect(GraphicsDevice); basicEffect.World = worldMatrix; basicEffect.View = viewMatrix; basicEffect.Projection = projectionMatrix; basicEffect.VertexColorEnabled = true; //important for color } SpotLight spot = new SpotLight() { lightPosition = new Vector3(371, 290, -120), lightColor = Color.White, lightRadius = 500, lightIntensity = 2, lightDirection = new Vector3(-371, -290, 120), spotAngle = 15, decay = 1 }; spotLights.Add(spot); spot = new SpotLight() { lightPosition = new Vector3(-120, 290, 371), lightColor = Color.White, lightRadius = 500, lightIntensity = 2, lightDirection = new Vector3(120, -260, -371), spotAngle = 15, decay = 10 }; spotLights.Add(spot); }