public void DrawShadows(GameTime gameTime, vxCamera3D camera) { // only render shadow map if we're not filling it with a block pattern if (mSceneShadowMode < vxEnumSceneShadowMode.BlockPattern) { vxEngine.GraphicsDevice.SetRenderTarget(vxEngine.Renderer.RT_ShadowMap); vxEngine.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.White, 1.0f, 0); vxEngine.GraphicsDevice.BlendState = BlendState.Opaque; vxEngine.GraphicsDevice.DepthStencilState = DepthStencilState.Default; vxEngine.GraphicsDevice.SamplerStates [0] = SamplerState.PointClamp; if (vxEngine.Profile.Settings.Graphics.ShadowQuality > Settings.vxEnumQuality.None) { foreach (vxEntity3D entity in Entities) { entity.RenderMeshShadow(); } foreach (InstanceSet instSet in InstanceSetCollection) { instSet.RenderInstancedShadow(instSet.InstancedModel.ModelShadow, camera, instSet.instances.Count); } foreach (KeyValuePair <object, InstanceSet> entry in Instances) { // do something with entry.Value or entry.Key entry.Value.RenderInstancedShadow(entry.Value.InstancedModel.ModelShadow, camera, entry.Value.instances.Count); } } } }
public CharacterCameraControlScheme(CharacterController character, vxCamera3D camera, vxEngine vxEngine) : base(camera, vxEngine) { Character = character; UseCameraSmoothing = true; StandingCameraOffset = 0.7f; CrouchingCameraOffset = 0.4f; }
/// <summary> /// Constructs the character and internal physics character controller. /// </summary> /// <param name="owningSpace">Space to add the character to.</param> /// <param name="camera">Camera to attach to the character.</param> /// <param name="game">The running game.</param> public CharacterControllerInput(Space owningSpace, vxCamera3D camera, vxEngine vxEngine) { CharacterController = new CharacterController(); Camera = camera; CameraControlScheme = new CharacterCameraControlScheme(CharacterController, camera, vxEngine); Space = owningSpace; }
/// <summary> /// Load graphics content for the game. /// </summary> public override void LoadContent() { if (content == null) { content = new ContentManager(vxEngine.Game.Services, "Content"); } //Get the Graphics Manager. mGraphicsManager = vxEngine.Game.Services.GetService(typeof(IGraphicsDeviceService)) as GraphicsDeviceManager; //Set the Current Gameplay Screen vxEngine.CurrentGameplayScreen = this; sphereModel = vxEngine.EngineContentManager.Load <Model> ("Models/lghtng/sphere"); //Setup Camera Camera = new vxCamera3D(vxEngine, new Vector3(0, 15, 0), 0, 0, Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)vxEngine.GraphicsDevice.Viewport.Width / vxEngine.GraphicsDevice.Viewport.Height, .1f, 10000), CameraType.ChaseCamera); Camera.Yaw = -MathHelper.PiOver2; DoFog = false; FogNear = Camera.FarPlane / 4; FogFar = Camera.FarPlane; //Setup Sun SunEmitter = new vxSunEntity(vxEngine); SkyBox = new vxSkyBoxEntity(vxEngine); //Setup Audio Manager AudioManager = new vxAudioManager(vxEngine); // Create and add the lensflare component. lensFlare = new LensFlareComponent(vxEngine); lensFlare.LoadContent(); if (GameType == vxEnumGameType.Networked) { IsPausable = false; } //Setup Renderer. //vxEngine.Renderer = new vxRenderer (vxEngine); // default window size mGraphicsManager.PreferMultiSampling = false; //vxEngine.Renderer.loadContent (mGraphicsManager); Camera.AspectRatio = mGraphicsManager.GraphicsDevice.Viewport.AspectRatio; #if VRTC_INCLDLIB_NET //InitialiseNetwork (); #endif }
/// <summary> /// Renders the instanced shadow. /// </summary> /// <param name="model">Model.</param> /// <param name="camera">Camera.</param> /// <param name="numInstances">Number instances.</param> public virtual void RenderInstancedShadow(Model model, vxCamera3D camera, int numInstances) { //Only XNA Supports Instance Drawing Currently #if VIRTICES_XNA for (int i = 0; i < vxEngine.Renderer.NumberOfShadowSplits; ++i) { { int x = i % 2; int y = i / 2; var viewPort = new Viewport( x * vxEngine.Renderer.ShadowMapSize, y * vxEngine.Renderer.ShadowMapSize, vxEngine.Renderer.ShadowMapSize, vxEngine.Renderer.ShadowMapSize); vxEngine.GraphicsDevice.Viewport = viewPort; } // now render the spheres if (numInstances > 0) { Matrix[] transforms = new Matrix[model.Bones.Count]; model.CopyAbsoluteBoneTransformsTo(transforms); foreach (ModelMesh mesh in model.Meshes) { foreach (var part in mesh.MeshParts) { part.Effect.CurrentTechnique = part.Effect.Techniques["ShadowInstanced"]; part.Effect.Parameters["ViewProjection_Sdw"].SetValue(vxEngine.Renderer.ShadowSplitProjections[i]); part.Effect.Parameters["World"].SetValue(transforms[mesh.ParentBone.Index]); part.Effect.Parameters["DepthBias_Sdw"].SetValue(new Vector2( vxEngine.Renderer.ShadowDepthBias[i, 0], vxEngine.Renderer.ShadowDepthBias[i, 1])); part.Effect.CurrentTechnique.Passes[0].Apply(); // set vertex buffer vxEngine.GraphicsDevice.SetVertexBuffers(new[] { part.VertexBuffer, new VertexBufferBinding(instanceVertexBuffer, 0, 1) }); // set index buffer and draw vxEngine.GraphicsDevice.Indices = part.IndexBuffer; vxEngine.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, part.VertexOffset, 0, part.NumVertices, part.StartIndex, part.PrimitiveCount, numInstances); } } } } #endif }
/// <summary> /// Sets the shadow transforms. /// </summary> /// <param name="camera">Camera.</param> public void setShadowTransforms(vxCamera3D camera) { Matrix viewProj = camera.View * camera.Projection; Matrix viewProjInverse = Matrix.Invert(viewProj); Matrix projInverse = Matrix.Invert(camera.Projection); Matrix viewInverse = Matrix.Invert(camera.View); // figure out closest geometry empassing near and far plances based on arena bounding box var viewSpaceBB = vxGeometryHelper.transformBoundingBox(bbDim, camera.View); var viewSpaceMin = Math.Min(-1, viewSpaceBB.Max.Z); var viewSpaceMax = Math.Min(0, viewSpaceBB.Min.Z); var viewDistance = new[] { bbDim.Max.X - bbDim.Min.X, bbDim.Max.Y - bbDim.Min.Y, bbDim.Max.Z - bbDim.Min.Z, }.Max() - 200.0f; var splitPlanes = vxGeometryHelper.practicalSplitScheme(NumberOfShadowSplits, 1, viewDistance) .Select(v => - v) .ToArray(); var splitDistances = splitPlanes.Select(c => { var d = Vector4.Transform(new Vector3(0, 0, c), camera.Projection); return(d.W != 0 ? d.Z / d.W : 0); }).ToArray(); var splitData = Enumerable.Range(0, NumberOfShadowSplits).Select(i => { var n = splitDistances[i]; var f = splitDistances[i + 1]; var viewSplit = vxGeometryHelper.splitFrustum(n, f, viewProjInverse).ToArray(); var frustumCorners = viewSplit.Select(v => Vector3.Transform(v, ShadowView)).ToArray(); var cameraPosition = Vector3.Transform(viewInverse.Translation, ShadowView); var viewMin = frustumCorners.Aggregate((v1, v2) => Vector3.Min(v1, v2)); var viewMax = frustumCorners.Aggregate((v1, v2) => Vector3.Max(v1, v2)); var arenaBB = vxGeometryHelper.transformBoundingBox(bbDim, ShadowView); var minZ = -arenaBB.Max.Z; var maxZ = -arenaBB.Min.Z; var range = Math.Max( 1.0f / camera.Projection.M11 * -splitPlanes[i + 1] * 2.0f, -splitPlanes[i + 1] - (-splitPlanes[i]) ); // range is slightly too small, so add in some padding float padding = 5.0f; var quantizationStep = (range + padding) / (float)ShadowMapSize; var x = vxGeometryHelper.determineShadowMinMax1D(frustumCorners.Select(v => v.X), cameraPosition.X, range); var y = vxGeometryHelper.determineShadowMinMax1D(frustumCorners.Select(v => v.Y), cameraPosition.Y, range); var projectionMin = new Vector3(x[0], y[0], minZ); var projectionMax = new Vector3(x[1], y[1], maxZ); // Add in padding { range += padding; projectionMin.X -= padding / 2.0f; projectionMin.Y -= padding / 2.0f; } // quantize if (mSnapShadowMaps) { // compute range var qx = (float)Math.IEEERemainder(projectionMin.X, quantizationStep); var qy = (float)Math.IEEERemainder(projectionMin.Y, quantizationStep); projectionMin.X = projectionMin.X - qx; projectionMin.Y = projectionMin.Y - qy; projectionMax.X = projectionMin.X + range; projectionMax.Y = projectionMin.Y + range; } // compute offset into texture atlas int tileX = i % 2; int tileY = i / 2; // [x min, x max, y min, y max] float tileBorder = 3.0f / (float)ShadowMapSize; var tileBounds = new Vector4( 0.5f * tileX + tileBorder, 0.5f * tileX + 0.5f - tileBorder, 0.5f * tileY + tileBorder, 0.5f * tileY + 0.5f - tileBorder ); var tileMatrix = Matrix.Identity; tileMatrix.M11 = 0.25f; tileMatrix.M22 = -0.25f; tileMatrix.Translation = new Vector3(0.25f + tileX * 0.5f, 0.25f + tileY * 0.5f, 0); return(new { Distance = f, ViewFrustum = viewSplit, Projection = Matrix.CreateOrthographicOffCenter(projectionMin.X, projectionMax.X, projectionMin.Y, projectionMax.Y, projectionMin.Z, projectionMax.Z), TileTransform = tileMatrix, TileBounds = tileBounds, }); }).ToArray(); ViewFrustumSplits = splitData.Select(s => s.ViewFrustum).ToArray(); ShadowSplitProjections = splitData.Select(s => ShadowView * s.Projection).ToArray(); ShadowSplitProjectionsWithTiling = splitData.Select(s => ShadowView * s.Projection * s.TileTransform).ToArray(); ShadowSplitTileBounds = splitData.Select(s => s.TileBounds).ToArray(); ShadowProjections = splitData.Select(s => s.Projection).ToArray(); }
public void DrawMain(GameTime gameTime, vxCamera3D camera) { //vxEngine.Profile.Settings.Graphics.Bool_DoGodRays = false; _halfPixel = -new Vector2(.5f / (float)vxEngine.GraphicsDevice.Viewport.Width, .5f / (float)vxEngine.GraphicsDevice.Viewport.Height); /****************************************************************************/ /* PREP PASS */ /****************************************************************************/ vxEngine.GraphicsDevice.SetRenderTargets( vxEngine.Renderer.RT_ColourMap, vxEngine.Renderer.RT_NormalMap, vxEngine.Renderer.RT_DepthMap); //Setup initial graphics states for prep pass vxEngine.GraphicsDevice.BlendState = BlendState.Opaque; vxEngine.GraphicsDevice.DepthStencilState = DepthStencilState.None; // //Reset Appropriate Values for Rendertargets //vxEngine.Assets.Shaders.DrfrdRndrClearGBuffer.Parameters["SkyColour"].SetValue(Color.White.ToVector4()); vxEngine.Assets.Shaders.DrfrdRndrClearGBuffer.Techniques[0].Passes[0].Apply(); vxEngine.Renderer.RenderQuad(Vector2.One * -1, Vector2.One); //Set the Depth Buffer appropriately vxEngine.GraphicsDevice.DepthStencilState = DepthStencilState.Default; foreach (vxEntity entity in Entities) { ((vxEntity3D)entity).RenderMeshPrepPass(); } #if VRTC_PLTFRM_XNA foreach (InstanceSet instSet in InstanceSetCollection) { instSet.RenderInstanced(instSet.InstancedModel.ModelMain, camera, instSet.instances.Count, "Technique_PrepPass_Instanced"); } foreach (KeyValuePair <object, InstanceSet> entry in Instances) { // do something with entry.Value or entry.Key entry.Value.RenderInstanced(entry.Value.InstancedModel.ModelMain, camera, entry.Value.instances.Count, "Technique_PrepPass_Instanced"); } #endif // Render God Rays //********************************************************************************************** vxEngine.GraphicsDevice.SetRenderTarget(vxEngine.Renderer.RT_SunMap); vxEngine.GraphicsDevice.BlendState = BlendState.Opaque; vxEngine.GraphicsDevice.DepthStencilState = DepthStencilState.Default; vxEngine.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0); SunEmitter.DrawGlow(); vxEngine.GraphicsDevice.SetRenderTarget(vxEngine.Renderer.RT_MaskMap); vxEngine.GraphicsDevice.BlendState = BlendState.Opaque; vxEngine.GraphicsDevice.DepthStencilState = DepthStencilState.Default; vxEngine.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0); Matrix orthoproj = Matrix.CreateOrthographicOffCenter(0, vxEngine.GraphicsDevice.Viewport.Width, vxEngine.GraphicsDevice.Viewport.Height, 0, 0, 1); Matrix halfPixelOffset = Matrix.CreateTranslation(-0.5f, -0.5f, 0); vxEngine.Assets.PostProcessShaders.MaskedSunEffect.Parameters["MatrixTransform"].SetValue(halfPixelOffset * orthoproj); vxEngine.Assets.PostProcessShaders.MaskedSunEffect.Parameters["DepthMap"].SetValue(vxEngine.Renderer.RT_DepthMap); vxEngine.SpriteBatch.Begin(0, BlendState.Opaque, null, null, null, vxEngine.Assets.PostProcessShaders.MaskedSunEffect); vxEngine.SpriteBatch.Draw(vxEngine.Renderer.RT_SunMap, Vector2.Zero, Color.White); vxEngine.SpriteBatch.End(); // Render the Water Reflection Map for the nearest water entity //********************************************************************************************** vxEngine.GraphicsDevice.SetRenderTarget(vxEngine.Renderer.RT_WaterReflectionMap); vxEngine.GraphicsDevice.Clear(Color.CornflowerBlue); vxEngine.GraphicsDevice.BlendState = BlendState.AlphaBlend; vxEngine.GraphicsDevice.DepthStencilState = DepthStencilState.Default; if (waterItems.Count > 0) { foreach (vxEntity3D entity in Entities) { entity.RenderMeshForWaterReflectionPass(waterItems[0].WrknPlane); } } //Now Render the Scene Into the Scene Render Target //********************************************************************************************** vxEngine.GraphicsDevice.SetRenderTarget(vxEngine.Renderer.RT_MainScene); vxEngine.GraphicsDevice.BlendState = BlendState.AlphaBlend; vxEngine.GraphicsDevice.DepthStencilState = DepthStencilState.Default; vxEngine.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, SkyColour, 1.0f, 0); if (vxEnviroment.GetVar(vxEnumEnvVarType.DEBUG_MESH).GetAsBool() == false) { switch (mSceneShadowMode) { case vxEnumSceneShadowMode.Default: case vxEnumSceneShadowMode.SplitColors: case vxEnumSceneShadowMode.BlockPattern: #if VRTC_PLTFRM_XNA foreach (InstanceSet instSet in InstanceSetCollection) { instSet.RenderInstanced(instSet.InstancedModel.ModelMain, camera, instSet.instances.Count, "Technique_Main_Instanced"); } foreach (KeyValuePair <object, InstanceSet> entry in Instances) { // do something with entry.Value or entry.Key entry.Value.RenderInstanced(entry.Value.InstancedModel.ModelMain, camera, entry.Value.instances.Count, "Technique_Main_Instanced"); } #endif // Render Main Pass //********************************************************************************************** foreach (vxEntity3D entity in Entities) { entity.RenderMesh("Technique_Main"); } // Now Generate Water Reflection Map //********************************************************************************************** foreach (vxWaterEntity water in waterItems) { water.DrawWater(vxEngine.Renderer.RT_WaterReflectionMap, camera.GetReflectionView(water.WrknPlane)); } break; } } /****************************************************************************/ /* LIGHT MAP PASS */ /****************************************************************************/ //Render Light Pass vxEngine.GraphicsDevice.SetRenderTarget(vxEngine.Renderer.RT_LightMap); vxEngine.GraphicsDevice.Clear(Color.Transparent); vxEngine.GraphicsDevice.BlendState = BlendState.AlphaBlend; vxEngine.GraphicsDevice.DepthStencilState = DepthStencilState.None; DrawDirectionalLight(-Vector3.Normalize(vxEngine.Renderer.lightPosition), Color.White * 0); vxEngine.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; vxEngine.GraphicsDevice.DepthStencilState = DepthStencilState.Default; foreach (vxLightEntity lightEntity in LightItems) { lightEntity.Draw(); } /****************************************************************************/ /* FINAL PASS */ /****************************************************************************/ //Set Render State vxEngine.GraphicsDevice.SetRenderTarget(vxEngine.Renderer.RT_FinalScene); vxEngine.GraphicsDevice.BlendState = BlendState.AlphaBlend; vxEngine.GraphicsDevice.DepthStencilState = DepthStencilState.None; vxEngine.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; Effect finalCombineEffect = vxEngine.Assets.Shaders.DrfrdRndrCombineFinal; //Combine everything finalCombineEffect.Parameters["colorMap"].SetValue(vxEngine.Renderer.RT_MainScene); finalCombineEffect.Parameters["lightMap"].SetValue(vxEngine.Renderer.RT_LightMap); finalCombineEffect.Parameters["halfPixel"].SetValue(_halfPixel); finalCombineEffect.Techniques[0].Passes[0].Apply(); vxEngine.Renderer.RenderQuad(Vector2.One * -1, Vector2.One); }
/// <summary> /// Efficiently draws several copies of a piece of geometry using hardware instancing. /// </summary> void DrawModelHardwareInstancing(InstanceSet instanceSet, vxCamera3D Camera, string technique) { Model model = instanceSet.InstancedModel; Matrix[] modelBones = instanceSet.instancedModelBones; Matrix[] instances = instanceSet.instanceTransforms; if (instances == null || instances.Length == 0) { return; } // If we have more instances than room in our vertex buffer, grow it to the neccessary size. if ((instanceSet.instanceVertexBuffer == null) || (instances.Length > instanceSet.instanceVertexBuffer.VertexCount)) { if (instanceSet.instanceVertexBuffer != null) { instanceSet.instanceVertexBuffer.Dispose(); } instanceSet.instanceVertexBuffer = new DynamicVertexBuffer(vxEngine.GraphicsDevice, InstanceSet.instanceVertexDeclaration, instances.Length, BufferUsage.WriteOnly); } // Transfer the latest instance transform matrices into the instanceVertexBuffer. instanceSet.instanceVertexBuffer.SetData(instances, 0, instances.Length, SetDataOptions.Discard); foreach (ModelMesh mesh in model.Meshes) { foreach (ModelMeshPart meshPart in mesh.MeshParts) { // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer. vxEngine.GraphicsDevice.SetVertexBuffers( new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0), new VertexBufferBinding(instanceSet.instanceVertexBuffer, 0, 1) ); vxEngine.GraphicsDevice.Indices = meshPart.IndexBuffer; // Set up the instance rendering effect. Effect effect = meshPart.Effect; // Specify which effect technique to use. effect.CurrentTechnique = effect.Techniques["Technique_PrepPass"]; effect.Parameters["World"].SetValue(Matrix.Identity); effect.Parameters["View"].SetValue(Camera.View); effect.Parameters["Projection"].SetValue(Camera.Projection); //if (effect.Parameters["LightDirection"] != null) effect.Parameters["LightDirection"].SetValue(Vector3.Normalize(vxEngine.Renderer.lightPosition)); if (effect.Parameters["ShadowMap"] != null) { effect.Parameters["ShadowMap"].SetValue(vxEngine.Renderer.RT_ShadowMap); } if (effect.Parameters["ShadowTransform"] != null) { effect.Parameters["ShadowTransform"].SetValue(vxEngine.Renderer.ShadowSplitProjectionsWithTiling); } if (effect.Parameters["TileBounds"] != null) { effect.Parameters["TileBounds"].SetValue(vxEngine.Renderer.ShadowSplitTileBounds); } if (effect.Parameters["SplitColors"] != null) { effect.Parameters["SplitColors"].SetValue(vxEngine.Renderer.ShadowSplitColors.Select(c => c.ToVector4()).ToArray()); } // Draw all the instance copies in a single call. foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); vxEngine.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount, instances.Length); } } } }
/// <summary> /// Instanced rendering. Draws instancedModel numInstances times. This demo uses hardware /// instancing: a secondary vertex stream is created, where the transform matrices of the /// individual instances are passed down to the shader. Note that in order to be efficient, /// the model should contain as little meshes and meshparts as possible. /// </summary> /// <param name="model">Model.</param> /// <param name="camera">Camera.</param> /// <param name="numInstances">Number instances.</param> /// <param name="technique">Technique.</param> public virtual void RenderInstanced(Model model, vxCamera3D camera, int numInstances, string technique) { //Only XNA Supports Instance Drawing Currently #if VIRTICES_XNA if (numInstances > 0) { // Draw the model. A model can have multiple meshes, so loop. Matrix[] transforms = new Matrix[model.Bones.Count]; model.CopyAbsoluteBoneTransformsTo(transforms); // loop through meshes foreach (ModelMesh mesh in model.Meshes) { /* * foreach (var shadowedEffect in mesh.Effects.Where(e => e.Parameters.Any(p => p.Name == "ShadowMap"))) * { * shadowedEffect.Parameters["ShadowMap"].SetValue(RT_ShadowMap); * shadowedEffect.Parameters["ShadowTransform"].SetValue(ShadowSplitProjectionsWithTiling); * shadowedEffect.Parameters["TileBounds"].SetValue(ShadowSplitTileBounds); * } */ // get bone matrix Matrix boneMatrix = transforms[mesh.ParentBone.Index]; foreach (ModelMeshPart part in mesh.MeshParts) { part.Effect.CurrentTechnique = part.Effect.Techniques[technique]; part.Effect.Parameters["World"].SetValue(transforms[mesh.ParentBone.Index]); part.Effect.Parameters["View"].SetValue(camera.View); part.Effect.Parameters["Projection"].SetValue(camera.Projection); part.Effect.Parameters["LightDirection"].SetValue(Vector3.Normalize(vxEngine.Renderer.lightPosition)); part.Effect.Parameters["ShadowMap"].SetValue(vxEngine.Renderer.RT_ShadowMap); part.Effect.Parameters["ShadowTransform"].SetValue(vxEngine.Renderer.ShadowSplitProjectionsWithTiling); part.Effect.Parameters["TileBounds"].SetValue(vxEngine.Renderer.ShadowSplitTileBounds); part.Effect.CurrentTechnique.Passes[0].Apply(); // set vertex buffer //mGraphicsDevice.SetVertexBuffers(new[] //{ // part.VertexBuffer, // new VertexBufferBinding(mInstanceDataStream, 0, 1 ) //}); //// draw primitives //mGraphicsDevice.Indices = part.IndexBuffer; //mGraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, part.VertexOffset, 0, part.NumVertices, part.StartIndex, part.PrimitiveCount, numInstances); // set vertex buffer vxEngine.GraphicsDevice.SetVertexBuffers(new[] { part.VertexBuffer, new VertexBufferBinding(instanceVertexBuffer, 0, 1) }); // set index buffer and draw vxEngine.GraphicsDevice.Indices = part.IndexBuffer; vxEngine.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, part.VertexOffset, 0, part.NumVertices, part.StartIndex, part.PrimitiveCount, numInstances); } } } #endif }
/// <summary> /// Instanced rendering. Draws instancedModel numInstances times. This demo uses hardware /// instancing: a secondary vertex stream is created, where the transform matrices of the /// individual instances are passed down to the shader. Note that in order to be efficient, /// the model should contain as little meshes and meshparts as possible. /// </summary> /// <param name="model">Model.</param> /// <param name="camera">Camera.</param> /// <param name="numInstances">Number instances.</param> /// <param name="technique">Technique.</param> public virtual void RenderInstanced(Model model, vxCamera3D camera, int numInstances, string technique) { //Only XNA Supports Instance Drawing Currently #if VRTC_PLTFRM_XNA if (numInstances > 0) { // Draw the model. A model can have multiple meshes, so loop. Matrix[] transforms = new Matrix[model.Bones.Count]; model.CopyAbsoluteBoneTransformsTo(transforms); // loop through meshes foreach (ModelMesh mesh in model.Meshes) { /* * foreach (var shadowedEffect in mesh.Effects.Where(e => e.Parameters.Any(p => p.Name == "ShadowMap"))) * { * shadowedEffect.Parameters["ShadowMap"].SetValue(vxEngine.Renderer.RT_ShadowMap); * shadowedEffect.Parameters["ShadowTransform"].SetValue(vxEngine.Renderer.ShadowSplitProjectionsWithTiling); * shadowedEffect.Parameters["TileBounds"].SetValue(vxEngine.Renderer.ShadowSplitTileBounds); * } */ // get bone matrix Matrix boneMatrix = transforms[mesh.ParentBone.Index]; foreach (ModelMeshPart part in mesh.MeshParts) { part.Effect.CurrentTechnique = part.Effect.Techniques[technique]; part.Effect.Parameters["World"].SetValue(transforms[mesh.ParentBone.Index]); part.Effect.Parameters["View"].SetValue(camera.View); part.Effect.Parameters["Projection"].SetValue(camera.Projection); part.Effect.Parameters["LightDirection"].SetValue(Vector3.Normalize(vxEngine.Renderer.lightPosition)); if (vxEngine.Profile.Settings.Graphics.ShadowQuality == Settings.vxEnumQuality.None) { DoShadowMap = false; } else { DoShadowMap = true; } //if (part.Effect.Parameters["DoShadow"] != null) part.Effect.Parameters["DoShadow"].SetValue(DoShadowMap); part.Effect.Parameters["ShadowMap"].SetValue(vxEngine.Renderer.RT_ShadowMap); part.Effect.Parameters["ShadowTransform"].SetValue(vxEngine.Renderer.ShadowSplitProjectionsWithTiling); part.Effect.Parameters["TileBounds"].SetValue(vxEngine.Renderer.ShadowSplitTileBounds); part.Effect.Parameters["SplitColors"].SetValue(vxEngine.Renderer.ShadowSplitColors.Select(c => c.ToVector4()).ToArray()); if (part.Effect.Parameters["CameraPos"] != null) { part.Effect.Parameters["CameraPos"].SetValue(vxEngine.Current3DSceneBase.Camera.WorldMatrix.Translation); } if (part.Effect.Parameters["FogNear"] != null) { part.Effect.Parameters["FogNear"].SetValue(5); } if (part.Effect.Parameters["FogFar"] != null) { part.Effect.Parameters["FogFar"].SetValue(vxEngine.Current3DSceneBase.Camera.FarPlane / 4); } if (part.Effect.Parameters["FogColor"] != null) { part.Effect.Parameters["FogColor"].SetValue(Vector4.One); } part.Effect.CurrentTechnique.Passes[0].Apply(); // set vertex buffer mGraphicsDevice.SetVertexBuffers(new[] { part.VertexBuffer, new VertexBufferBinding(mInstanceDataStream, 0, 1) }); // draw primitives mGraphicsDevice.Indices = part.IndexBuffer; mGraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, part.VertexOffset, 0, part.NumVertices, part.StartIndex, part.PrimitiveCount, numInstances); } } } #endif }
protected CameraControlScheme(vxCamera3D camera, vxEngine vxEngine) { Camera = camera; this.vxEngine = vxEngine; }