public void Draw(GraphicsDevice device, BoundingBox boundingBox, Camera camera, Color color) { if (declaration == null) { declaration = VertexPositionColor.VertexDeclaration; } if (effect == null) { effect = new BasicEffect(device); } effect.DiffuseColor = color.ToVector3(); effect.View = camera.EyeTransform; effect.Projection = camera.ProjectionTransform; Vector3 size = boundingBox.Max - boundingBox.Min; effect.World = Matrix.CreateScale(size)*Matrix.CreateTranslation(boundingBox.Max - size*0.5f); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); device.DrawUserIndexedPrimitives<VertexPositionColor>( PrimitiveType.LineList, points, 0, 8, index, 0, 12); } }
public void RenderToGBuffer(Camera camera, GraphicsDevice graphicsDevice) { if (_subMeshes.Count == 0) return; // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer. Mesh.SubMesh subMesh = _subMeshes[0]; ModelMeshPart meshPart = subMesh._meshPart; graphicsDevice.SetVertexBuffers( new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0), new VertexBufferBinding(_instanceVertexBuffer, 0, 1) ); subMesh.RenderEffect.SetCurrentTechnique(3); subMesh.RenderEffect.SetMatrices(Matrix.Identity, camera.EyeTransform, camera.ProjectionTransform); //our first pass is responsible for rendering into GBuffer subMesh.RenderEffect.SetFarClip(camera.FarClip); //no individual skinned models for now if (subMesh._parent.BoneMatrixes != null) subMesh.RenderEffect.SetBones(subMesh._parent.BoneMatrixes); subMesh.RenderEffect.Apply(); graphicsDevice.Indices = meshPart.IndexBuffer; graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount, _subMeshes.Count); }
public CameraController(Viewport v, Matrix initialTransform) { camera = new Camera(); camera.Aspect = v.AspectRatio; camera.NearClip = 0.1f; camera.FarClip = 1000; camera.Viewport = v; camera.Transform = initialTransform; targetXYZ = camera.Transform.Translation; lastXYZ = targetXYZ; }
public virtual void RenderToGBuffer(Camera camera, GraphicsDevice graphicsDevice) { RenderEffect.SetCurrentTechnique(0); RenderEffect.SetMatrices(GlobalTransform, camera.EyeTransform, camera.ProjectionTransform); //our first pass is responsible for rendering into GBuffer RenderEffect.SetFarClip(camera.FarClip); if (_parent.BoneMatrixes != null) RenderEffect.SetBones(_parent.BoneMatrixes); RenderEffect.Apply(); graphicsDevice.SetVertexBuffer(_meshPart.VertexBuffer, _meshPart.VertexOffset); graphicsDevice.Indices = _meshPart.IndexBuffer; graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _meshPart.NumVertices, _meshPart.StartIndex, _meshPart.PrimitiveCount); }
//construct public MenuBackground() { viewport = Globals.graphics.GraphicsDevice.Viewport; // Create the renderer, this renderer binds to the graphics device and with the given width and height, is used to // draw everything on each frame renderer = new Renderer(Globals.graphics.GraphicsDevice, Globals.content, viewport.Width, viewport.Height); // The light and mesh container is used to store mesh and light obejcts. This is just for RENDERING. Not for DRAWING lightAndMeshContainer = new SimpleSceneGraph(); lightAndMeshContainer.SetSubMeshDelegate(delegate(Mesh.SubMesh subMesh) { renderer.SetupSubMesh(subMesh); subMesh.RenderEffect.AmbientParameter.SetValue(Vector4.Zero); }); lightAndMeshContainer.SetLightDelegate(delegate(Light l) { }); camera = new Camera(); camera.Aspect = viewport.AspectRatio; camera.NearClip = 0.1f; camera.FarClip = 1000; camera.Viewport = viewport; camera.Transform = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(170),-0.3f,0) * Matrix.CreateTranslation(2,5f,-4); Mesh m = new Mesh(); m.Model = AssetLoader.mdl_menuscene; m.Transform = Matrix.Identity; lightAndMeshContainer.AddMesh(m); Light mainlight = new Light(); mainlight.LightType = Light.Type.Spot; mainlight.Color = Color.AntiqueWhite; mainlight.Transform = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(170),-0.7f,0) * Matrix.CreateTranslation(0, 5f, -4); mainlight.SpotAngle = 50; mainlight.SpotExponent = 1; mainlight.Radius = 13; mainlight.Intensity = 2f; lightAndMeshContainer.AddLight(mainlight); }
private void BuildLightEntries(Camera camera) { _lightEntries.Clear(); for (int index = 0; index < _visibleLights.Count; index++) { LightEntry lightEntry = new LightEntry(); lightEntry.light = _visibleLights[index]; _lightEntries.Add(lightEntry); } }
/// <summary> /// Do a frustum culling test on each sub mesh, adding the visible ones to our list /// </summary> /// <param name="camera"></param> /// <param name="meshes"></param> private void CullVisibleMeshes(Camera camera, BaseSceneGraph sceneGraph) { for (int index = 0; index < _visibleMeshes.Length; index++) { _visibleMeshes[index].Clear(); } sceneGraph.GetVisibleMeshes(camera.Frustum, _visibleMeshes); }
private void DrawBlendObjects(Camera camera) { _graphicsDevice.DepthStencilState = DepthStencilState.DepthRead; _graphicsDevice.BlendState = BlendState.Additive; List<Mesh.SubMesh> meshes = _visibleMeshes[(int)MeshMetadata.ERenderQueue.Blend]; for (int index = 0; index < meshes.Count; index++) { Mesh.SubMesh visibleMesh = meshes[index]; visibleMesh.GenericRender(camera, GraphicsDevice); } //reset states, since the custom shaders could have overriden them _graphicsDevice.DepthStencilState = DepthStencilState.DepthRead; _graphicsDevice.BlendState = BlendState.Additive; _graphicsDevice.BlendFactor = Color.White; _graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; Matrix projectionTransform = camera.ProjectionTransform; Matrix eyeTransform = camera.EyeTransform; }
private void DrawOpaqueObjects(Camera camera) { List<Mesh.SubMesh> meshes = _visibleMeshes[(int)MeshMetadata.ERenderQueue.SkipGbuffer]; for (int index = 0; index < meshes.Count; index++) { Mesh.SubMesh visibleMesh = meshes[index]; visibleMesh.GenericRender(camera, GraphicsDevice); } }
public void ReconstructShading(Camera camera, GraphicsDevice graphicsDevice) { for (int index = 0; index < _instancingGroups.Count; index++) { InstancingGroup instancingGroup = _instancingGroups[index]; instancingGroup.ReconstructShading(camera, graphicsDevice); } }
private void RenderToGbuffer(Camera camera) { List<Mesh.SubMesh> meshes = _visibleMeshes[(int)MeshMetadata.ERenderQueue.Default]; for (int index = 0; index < meshes.Count; index++) { Mesh.SubMesh mesh = meshes[index]; if (!mesh.InstanceEnabled) { mesh.RenderToGBuffer(camera, GraphicsDevice); } else { InstancingGroupManager.AddInstancedSubMesh(mesh); } } InstancingGroupManager.GenerateInstanceInfo(GraphicsDevice); InstancingGroupManager.RenderToGBuffer(camera, GraphicsDevice); }
private void ReconstructShading(Camera camera) { List<Mesh.SubMesh> meshes = _visibleMeshes[(int)MeshMetadata.ERenderQueue.Default]; for (int index = 0; index < meshes.Count; index++) { Mesh.SubMesh visibleMesh = meshes[index]; if (!visibleMesh.InstanceEnabled) { visibleMesh.ReconstructShading(camera, GraphicsDevice); } } //reuse the instance groups InstancingGroupManager.ReconstructShading(camera, GraphicsDevice); }
/// <summary> /// It assumes that this shader is not the default LPP shader, and it will use ONLY the first technique /// </summary> /// <param name="camera"></param> /// <param name="graphicsDevice"></param> /// <param name="renderStatistics"></param> public void GenericRender(Camera camera, GraphicsDevice graphicsDevice) { RenderEffect.SetMatrices(GlobalTransform, camera.EyeTransform, camera.ProjectionTransform); if (_parent.BoneMatrixes != null) RenderEffect.SetBones(_parent.BoneMatrixes); RenderEffect.Apply(); graphicsDevice.SetVertexBuffer(_meshPart.VertexBuffer, _meshPart.VertexOffset); graphicsDevice.Indices = _meshPart.IndexBuffer; graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _meshPart.NumVertices, _meshPart.StartIndex, _meshPart.PrimitiveCount); }
public void ReconstructShading(Camera camera, GraphicsDevice graphicsDevice) { if (_subMeshes.Count == 0) return; // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer. Mesh.SubMesh subMesh = _subMeshes[0]; ModelMeshPart meshPart = subMesh._meshPart; graphicsDevice.SetVertexBuffers( new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0), new VertexBufferBinding(_instanceVertexBuffer, 0, 1) ); subMesh.RenderEffect.SetCurrentTechnique(4); subMesh.RenderEffect.Apply(); graphicsDevice.Indices = meshPart.IndexBuffer; graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount, _subMeshes.Count); }
/// <summary> /// Generate the shadow maps and matrixes for the visible lights. We should limit /// our shadow-casters based on number of available shadow maps (we could use some /// performance-related heuristic here too) /// </summary> /// <param name="camera"></param> /// <param name="meshes"></param> /// <param name="renderWorld"></param> private void GenerateShadows(Camera camera, BaseSceneGraph sceneGraph) { for (int index = 0; index < _lightShadowCasters.Count; index++) { LightEntry light = _lightShadowCasters[index]; //only spot if (light.light.LightType == Light.Type.Spot) { _shadowRenderer.GenerateShadowTextureSpotLight(this, sceneGraph, light.light, light.spotShadowMap); } } }
private void ReconstructZBuffer(Camera camera) { //bind effect _reconstructZBuffer.Parameters["GBufferPixelSize"].SetValue(new Vector2(0.5f / _width, 0.5f / _height)); _reconstructZBuffer.Parameters["DepthBuffer"].SetValue(_depthBuffer); _reconstructZBuffer.Parameters["FarClip"].SetValue(camera.FarClip); //our projection matrix is almost all 0s, we just need these 2 values to restoure our Z-buffer from our linear depth buffer _reconstructZBuffer.Parameters["ProjectionValues"].SetValue(new Vector2(camera.ProjectionTransform.M33, camera.ProjectionTransform.M43)); _reconstructZBuffer.CurrentTechnique.Passes[0].Apply(); //we need to always write to z-buffer //store previous state BlendState oldBlendState = GraphicsDevice.BlendState; GraphicsDevice.DepthStencilState = _depthStateReconstructZ; _quadRenderer.RenderQuad(GraphicsDevice, -Vector2.One, Vector2.One); GraphicsDevice.DepthStencilState = _depthStateDrawLights; GraphicsDevice.BlendState = oldBlendState; }
public void ReconstructShading(Camera camera, GraphicsDevice graphicsDevice) { //this pass uses the light diffuse and specular accumulation texture (already bound in the setup stage) and reconstruct the mesh's shading //our parameters were already filled in the first pass RenderEffect.SetCurrentTechnique(1); //we don't need to do this again, it was done on the previous step //_renderEffect.SetMatrices(GlobalTransform, camera.EyeTransform, camera.ProjectionTransform); // if (_parent.BoneMatrixes != null) // _renderEffect.SetBones(_parent.BoneMatrixes); RenderEffect.Apply(); graphicsDevice.SetVertexBuffer(_meshPart.VertexBuffer, _meshPart.VertexOffset); graphicsDevice.Indices = _meshPart.IndexBuffer; graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _meshPart.NumVertices, _meshPart.StartIndex, _meshPart.PrimitiveCount); }
private void RenderLights(Camera camera) { _lighting.Parameters["GBufferPixelSize"].SetValue(new Vector2(0.5f / _width, 0.5f / _height)); _lighting.Parameters["DepthBuffer"].SetValue(_depthBuffer); _lighting.Parameters["NormalBuffer"].SetValue(_normalBuffer); //just comment this line if you dont want to reconstruct the zbuffer ReconstructZBuffer(camera); _lighting.Parameters["TanAspect"].SetValue(new Vector2(camera.TanFovy * camera.Aspect, -camera.TanFovy)); for (int i = 0; i < _lightEntries.Count; i++) { LightEntry lightEntry = _lightEntries[i]; Light light = lightEntry.light; //convert light position into viewspace Vector3 viewSpaceLPos = Vector3.Transform(light.Transform.Translation, camera.EyeTransform); Vector3 viewSpaceLDir = Vector3.TransformNormal(Vector3.Normalize(light.Transform.Backward), camera.EyeTransform); _lighting.Parameters["LightPosition"].SetValue(viewSpaceLPos); _lighting.Parameters["LightDir"].SetValue(viewSpaceLDir); Vector4 lightColor = light.Color.ToVector4() * light.Intensity; lightColor.W = light.SpecularIntensity; _lighting.Parameters["LightColor"].SetValue(lightColor); float invRadiusSqr = 1.0f / (light.Radius * light.Radius); _lighting.Parameters["InvLightRadiusSqr"].SetValue(invRadiusSqr); _lighting.Parameters["FarClip"].SetValue(camera.FarClip); switch (light.LightType) { case Light.Type.Point: case Light.Type.Spot: if (light.LightType == Light.Type.Point) { //check if the light touches the near plane BoundingSphere boundingSphereExpanded = light.BoundingSphere; boundingSphereExpanded.Radius *= 1.375f; //expand it a little, because our mesh is not a perfect sphere PlaneIntersectionType planeIntersectionType; camera.Frustum.Near.Intersects(ref boundingSphereExpanded, out planeIntersectionType); if (planeIntersectionType != PlaneIntersectionType.Back) { GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; GraphicsDevice.DepthStencilState = _ccwDepthState; } else { GraphicsDevice.RasterizerState = RasterizerState.CullClockwise; GraphicsDevice.DepthStencilState = _cwDepthState; } Matrix lightMatrix = Matrix.CreateScale(light.Radius); lightMatrix.Translation = light.BoundingSphere.Center; _lighting.Parameters["WorldViewProjection"].SetValue(lightMatrix * camera.EyeProjectionTransform); _lighting.CurrentTechnique = _lighting.Techniques[1]; _lighting.CurrentTechnique.Passes[0].Apply(); _sphereRenderer.BindMesh(GraphicsDevice); _sphereRenderer.RenderMesh(GraphicsDevice); } else { //check if the light touches the far plane Plane near = camera.Frustum.Near; near.D += 3; //give some room because we dont use a perfect-fit mesh for the spot light PlaneIntersectionType planeIntersectionType = near.Intersects(light.Frustum); if (planeIntersectionType != PlaneIntersectionType.Back) { GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; GraphicsDevice.DepthStencilState = _ccwDepthState; } else { GraphicsDevice.RasterizerState = RasterizerState.CullClockwise; GraphicsDevice.DepthStencilState = _cwDepthState; } float tan = (float)Math.Tan(MathHelper.ToRadians(light.SpotAngle)); Matrix lightMatrix = Matrix.CreateScale(light.Radius * tan, light.Radius * tan, light.Radius); lightMatrix = lightMatrix * light.Transform; _lighting.Parameters["WorldViewProjection"].SetValue(lightMatrix * camera.EyeProjectionTransform); float cosSpotAngle = (float)Math.Cos(MathHelper.ToRadians(light.SpotAngle)); _lighting.Parameters["SpotAngle"].SetValue(cosSpotAngle); _lighting.Parameters["SpotExponent"].SetValue(light.SpotExponent / (1 - cosSpotAngle)); if (lightEntry.castShadows) { _lighting.CurrentTechnique = _lighting.Techniques[4]; _lighting.Parameters["MatLightViewProjSpot"].SetValue(lightEntry.spotShadowMap.LightViewProjection); _lighting.Parameters["DepthBias"].SetValue(light.ShadowDepthBias); Vector2 shadowMapPixelSize = new Vector2(0.5f / lightEntry.spotShadowMap.Texture.Width, 0.5f / lightEntry.spotShadowMap.Texture.Height); _lighting.Parameters["ShadowMapPixelSize"].SetValue(shadowMapPixelSize); _lighting.Parameters["ShadowMapSize"].SetValue(new Vector2(lightEntry.spotShadowMap.Texture.Width, lightEntry.spotShadowMap.Texture.Height)); _lighting.Parameters["ShadowMap"].SetValue(lightEntry.spotShadowMap.Texture); _lighting.Parameters["CameraTransform"].SetValue(camera.Transform); } else { _lighting.CurrentTechnique = _lighting.Techniques[3]; } _lighting.CurrentTechnique.Passes[0].Apply(); _spotRenderer.BindMesh(GraphicsDevice); _spotRenderer.RenderMesh(GraphicsDevice); } break; default: throw new ArgumentOutOfRangeException(); } } _graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; }
/// <summary> /// Render the current scene. The culling will be performed inside this method, /// because we need all meshes here to compute the shadow maps. /// </summary> /// <param name="camera">Current camera</param> /// <param name="visibleLights"></param> /// <param name="meshes">All meshes</param> /// <param name="sceneGraph"></param> /// <param name="particleSystems"></param> /// <param name="gameTime"></param> /// <param name="lights">Visible lights</param> /// <returns></returns> public RenderTarget2D RenderScene(Camera camera, BaseSceneGraph sceneGraph) { InstancingGroupManager.Reset(); sceneGraph.DoPreFrameWork(camera.Frustum); _depthDownsampledThisFrame = false; _currentCamera = camera; //compute the frustum corners for this camera ComputeFrustumCorners(camera); //this resets the free shadow maps _shadowRenderer.InitFrame(); _visibleLights.Clear(); sceneGraph.GetVisibleLights(camera.Frustum, _visibleLights); //sort lights, choose the shadow casters BuildLightEntries(camera); SelectShadowCasters(); //generate all shadow maps GenerateShadows(camera, sceneGraph); //first of all, we must bind our GBuffer and reset all states GraphicsDevice.SetRenderTargets(_gBufferBinding); GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Stencil, Color.Black, 1.0f, 0); GraphicsDevice.BlendState = BlendState.Opaque; GraphicsDevice.DepthStencilState = DepthStencilState.None; GraphicsDevice.RasterizerState = RasterizerState.CullNone; //bind the effect that outputs the default GBuffer values _clearGBuffer.CurrentTechnique.Passes[0].Apply(); //draw a full screen quad for clearing our GBuffer _quadRenderer.RenderQuad(GraphicsDevice, -Vector2.One, Vector2.One); GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; //select the visible meshes CullVisibleMeshes(camera, sceneGraph); //now, render them to the G-Buffer RenderToGbuffer(camera); //resolve our GBuffer and render the lights //clear the light buffer with black GraphicsDevice.SetRenderTargets(_lightAccumBinding); //dont be fooled by Color.Black, as its alpha is 255 (or 1.0f) GraphicsDevice.Clear(new Color(0, 0, 0, 0)); //dont use depth/stencil test...we dont have a depth buffer, anyway GraphicsDevice.DepthStencilState = DepthStencilState.None; GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; //draw using additive blending. //At first I was using BlendState.additive, but it seems to use alpha channel for modulation, //and as we use alpha channel as the specular intensity, we have to create our own blend state here GraphicsDevice.BlendState = _lightAddBlendState; RenderLights(camera); //reconstruct each object shading, using the light texture as input (and another specific parameters too) GraphicsDevice.SetRenderTarget(_outputTexture); GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Stencil | ClearOptions.Target, Color.Black, 1.0f, 0); GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.BlendState = BlendState.Opaque; GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; //reconstruct the shading, using the already culled list ReconstructShading(camera); //render objects that doesn't need the lightbuffer information, such as skyboxes, pure reflective meshes, etc DrawOpaqueObjects(camera); //draw objects with transparency DrawBlendObjects(camera); //draw SSAO texture. It's not correct to do it here, because ideally the SSAO should affect only //the ambient light, but it looks good this way //unbind our final buffer and return it GraphicsDevice.SetRenderTarget(null); return _outputTexture; }
/// <summary> /// Compute the frustum corners for a camera. /// Its used to reconstruct the pixel position using only the depth value. /// Read here for more information /// http://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/ /// </summary> /// <param name="camera"> Current rendering camera </param> private void ComputeFrustumCorners(Camera camera) { camera.Frustum.GetCorners(_cornersWorldSpace); Matrix matView = camera.EyeTransform; //this is the inverse of our camera transform Vector3.Transform(_cornersWorldSpace, ref matView, _cornersViewSpace); //put the frustum into view space for (int i = 0; i < 4; i++) //take only the 4 farthest points { _currentFrustumCorners[i] = _cornersViewSpace[i + 4]; } Vector3 temp = _currentFrustumCorners[3]; _currentFrustumCorners[3] = _currentFrustumCorners[2]; _currentFrustumCorners[2] = temp; }
public void RenderToGBuffer(Camera camera, GraphicsDevice graphicsDevice) { for (int index = 0; index < _instancingGroups.Count; index++) { InstancingGroup instancingGroup = _instancingGroups[index]; instancingGroup.RenderToGBuffer(camera, graphicsDevice); } }