123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- using System;
- using nkast.Aether.Shaders;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework.Content;
- namespace Samples.Deferred
- {
- public class DeferredRendering
- {
- GraphicsDevice _graphicsDevice;
- private QuadRenderComponent quadRenderer;
- public RenderTarget2D colorRT; // color and specular intensity
- public RenderTarget2D normalRT; // normals + specular power
- public RenderTarget2D depthRT; // depth
- public RenderTarget2D lightRT; // lighting
- public DeferredBasicEffect basicEffect;
- private DeferredClearGBufferEffect clearBufferEffect;
- private DeferredPointLightEffect pointLightEffect;
- private DeferredSpotLightEffect spotLightEffect;
- private DeferredCombineEffect combineEffect;
- private Model sphereModel; //point ligt volume
- private Vector2 halfPixel;
-
- public DeferredRendering(GraphicsDevice graphicsDevice, ContentManager content)
- {
- _graphicsDevice = graphicsDevice;
- quadRenderer = new QuadRenderComponent(graphicsDevice);
- halfPixel = new Vector2()
- {
- X = 0.5f / (float)graphicsDevice.PresentationParameters.BackBufferWidth,
- Y = 0.5f / (float)graphicsDevice.PresentationParameters.BackBufferHeight
- };
- int backbufferWidth = graphicsDevice.PresentationParameters.BackBufferWidth;
- int backbufferHeight = graphicsDevice.PresentationParameters.BackBufferHeight;
- colorRT = new RenderTarget2D(graphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Color, DepthFormat.Depth24);
- normalRT = new RenderTarget2D(graphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Color, DepthFormat.None);
- depthRT = new RenderTarget2D(graphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Single, DepthFormat.None);
- lightRT = new RenderTarget2D(graphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Color, DepthFormat.None);
- basicEffect = new DeferredBasicEffect(graphicsDevice);
- clearBufferEffect = new DeferredClearGBufferEffect(graphicsDevice);
- combineEffect = new DeferredCombineEffect(graphicsDevice);
- pointLightEffect = new DeferredPointLightEffect(graphicsDevice);
- spotLightEffect = new DeferredSpotLightEffect(graphicsDevice);
- sphereModel = content.Load<Model>(@"sphere");
- }
-
- internal void DrawRTs(SpriteBatch spriteBatch)
- {
- float height = this._graphicsDevice.Viewport.Height / 8;
- float scale = height/colorRT.Height;
- Vector2 pos = new Vector2(0, height);
- Vector2 off = new Vector2(0, this._graphicsDevice.Viewport.Height - height*4);
- spriteBatch.Draw(colorRT, pos * 0 + off, null, Color.White, 0f, Vector2.Zero, scale, SpriteEffects.None, 0);
- spriteBatch.Draw(normalRT,pos * 1 + off, null, Color.White, 0f, Vector2.Zero, scale, SpriteEffects.None, 0);
- spriteBatch.Draw(depthRT, pos * 2 + off, null, Color.White, 0f, Vector2.Zero, scale, SpriteEffects.None, 0);
- spriteBatch.Draw(lightRT, pos * 3 + off, null, Color.White, 0f, Vector2.Zero, scale, SpriteEffects.None, 0);
- }
- internal void SetGBuffer()
- {
- _graphicsDevice.SetRenderTargets(colorRT, normalRT, depthRT);
- }
- internal void ClearGBuffer()
- {
- _graphicsDevice.Clear(Color.Black);
- clearBufferEffect.CurrentTechnique.Passes[0].Apply();
- quadRenderer.Render(Vector2.One * -1, Vector2.One);
- }
- internal void ResolveGBuffer()
- {
- _graphicsDevice.SetRenderTargets(null);
- }
- internal void Combine()
- {
- _graphicsDevice.BlendState = BlendState.Opaque;
- _graphicsDevice.DepthStencilState = DepthStencilState.None;
- _graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
- _graphicsDevice.SetRenderTarget(null);
- _graphicsDevice.Clear(Color.Black);
- //Combine everything
- combineEffect.ColorMap = colorRT;
- combineEffect.LightMap = lightRT;
- combineEffect.HalfPixel = halfPixel;
- combineEffect.CurrentTechnique.Passes[0].Apply();
- quadRenderer.Render(Vector2.One * -1, Vector2.One);
- }
- public void DrawPointLight(Vector3 lightPosition, Color color, float lightRadius, float lightIntensity, Matrix view, Matrix projection, Vector3 cameraPosition)
- {
- //set the G-Buffer parameters
- pointLightEffect.ColorMap = colorRT;
- pointLightEffect.NormalMap = normalRT;
- pointLightEffect.DepthMap = depthRT;
- //compute the light world matrix
- //scale according to light radius, and translate it to light position
- Matrix sphereWorldMatrix = Matrix.CreateScale(lightRadius) * Matrix.CreateTranslation(lightPosition);
- pointLightEffect.World = sphereWorldMatrix;
- pointLightEffect.View = view;
- pointLightEffect.Projection = projection;
- //light position
- pointLightEffect.LightPosition = lightPosition;
- //set the color, radius and Intensity
- pointLightEffect.Color = color.ToVector3();
- pointLightEffect.LightRadius = lightRadius;
- pointLightEffect.LightIntensity = lightIntensity;
- //parameters for specular computations
- pointLightEffect.CameraPosition = cameraPosition;
- pointLightEffect.InvertViewProjection = Matrix.Invert(view * projection);
- //size of a halfpixel, for texture coordinates alignment
- pointLightEffect.HalfPixel = halfPixel;
- _graphicsDevice.RasterizerState = RasterizerState.CullNone;
- _graphicsDevice.DepthStencilState = DepthStencilState.None;
- _graphicsDevice.BlendState = BlendState.AlphaBlend;
- pointLightEffect.CurrentTechnique.Passes[0].Apply();
- foreach (ModelMesh mesh in sphereModel.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;
- _graphicsDevice.BlendState = BlendState.Opaque;
- }
- public void DrawSpotLight(Vector3 lightPosition, Color color, float lightRadius, float lightIntensity,
- Vector3 lightDirection, float innerAngle, float outerAngle, Matrix view, Matrix projection, Vector3 cameraPosition)
- {
- //set the G-Buffer parameters
- spotLightEffect.ColorMap = colorRT;
- spotLightEffect.NormalMap = normalRT;
- spotLightEffect.DepthMap = depthRT;
- //compute the light world matrix
- //scale according to light radius, and translate it to light position
- Matrix sphereWorldMatrix = Matrix.CreateScale(lightRadius) * Matrix.CreateTranslation(lightPosition);
- spotLightEffect.World = sphereWorldMatrix;
- spotLightEffect.View = view;
- spotLightEffect.Projection = projection;
- //light position
- spotLightEffect.LightPosition = lightPosition;
- //light direction
- spotLightEffect.LightDirection = lightDirection;
- //spot light
- if (innerAngle == outerAngle) innerAngle -= innerAngle / 360f;
- spotLightEffect.InnerAngleCos = (float)Math.Cos(innerAngle);
- spotLightEffect.OuterAngleCos = (float)Math.Cos(outerAngle);
- //set the color, radius and Intensity
- spotLightEffect.Color = color.ToVector3();
- spotLightEffect.LightRadius = lightRadius;
- spotLightEffect.LightIntensity = lightIntensity;
- //parameters for specular computations
- spotLightEffect.CameraPosition = cameraPosition;
- spotLightEffect.InvertViewProjection = Matrix.Invert(view * projection);
- //size of a halfpixel, for texture coordinates alignment
- spotLightEffect.HalfPixel = halfPixel;
- _graphicsDevice.RasterizerState = RasterizerState.CullNone;
- _graphicsDevice.DepthStencilState = DepthStencilState.None;
- _graphicsDevice.BlendState = BlendState.AlphaBlend;
- spotLightEffect.CurrentTechnique.Passes[0].Apply();
- foreach (ModelMesh mesh in sphereModel.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;
- _graphicsDevice.BlendState = BlendState.Opaque;
- }
- }
- }
|