protected override void DoRender() { // Calculate elapsed seconds var time = clock.ElapsedMilliseconds / 1000.0f; // Retrieve device context var context = this.DeviceManager.Direct3DContext; // Calculate skin matrices for each bone ConstantBuffers.PerArmature skinMatrices = new ConstantBuffers.PerArmature(); if (mesh.Bones != null) { // Retrieve each bone's local transform for (var i = 0; i < mesh.Bones.Count; i++) { skinMatrices.Bones[i] = mesh.Bones[i].BoneLocalTransform; } // Load bone transforms from animation frames if (CurrentAnimation.HasValue) { // Keep track of the last key-frame used for each bone Mesh.Keyframe?[] lastKeyForBones = new Mesh.Keyframe?[mesh.Bones.Count]; // Keep track of whether a bone has been interpolated bool[] lerpedBones = new bool[mesh.Bones.Count]; for (var i = 0; i < CurrentAnimation.Value.Keyframes.Count; i++) { // Retrieve current key-frame var frame = CurrentAnimation.Value.Keyframes[i]; // If the current frame is not in the future if (frame.Time <= time) { // Keep track of last key-frame for bone lastKeyForBones[frame.BoneIndex] = frame; // Retrieve transform from current key-frame skinMatrices.Bones[frame.BoneIndex] = frame.Transform; } // Frame is in the future, check if we should interpolate else { // Only interpolate a bone's key-frames ONCE if (!lerpedBones[frame.BoneIndex]) { // Retrieve the previous key-frame if exists Mesh.Keyframe prevFrame; if (lastKeyForBones[frame.BoneIndex] != null) { prevFrame = lastKeyForBones[frame.BoneIndex].Value; } else { continue; // nothing to interpolate } // Make sure we only interpolate with // one future frame for this bone lerpedBones[frame.BoneIndex] = true; // Calculate time difference between frames var frameLength = frame.Time - prevFrame.Time; var timeDiff = time - prevFrame.Time; var amount = timeDiff / frameLength; // Interpolation using Lerp on scale and translation, and Slerp on Rotation (Quaternion) Vector3 t1, t2; // Translation Quaternion q1, q2; // Rotation float s1, s2; // Scale // Decompose the previous key-frame's transform prevFrame.Transform.DecomposeUniformScale(out s1, out q1, out t1); // Decompose the current key-frame's transform frame.Transform.DecomposeUniformScale(out s2, out q2, out t2); // Perform interpolation and reconstitute matrix skinMatrices.Bones[frame.BoneIndex] = Matrix.Scaling(MathUtil.Lerp(s1, s2, amount)) * Matrix.RotationQuaternion(Quaternion.Slerp(q1, q2, amount)) * Matrix.Translation(Vector3.Lerp(t1, t2, amount)); } } } } // Apply parent bone transforms // We assume here that the first bone has no parent // and that each parent bone appears before children for (var i = 1; i < mesh.Bones.Count; i++) { var bone = mesh.Bones[i]; if (bone.ParentIndex > -1) { var parentTransform = skinMatrices.Bones[bone.ParentIndex]; skinMatrices.Bones[i] = (skinMatrices.Bones[i] * parentTransform); } } // Change the bone transform from rest pose space into bone space (using the inverse of the bind/rest pose) for (var i = 0; i < mesh.Bones.Count; i++) { skinMatrices.Bones[i] = Matrix.Transpose(mesh.Bones[i].InvBindPose * skinMatrices.Bones[i]); } // Check need to loop animation if (!PlayOnce && CurrentAnimation.HasValue && CurrentAnimation.Value.EndTime <= time) { this.Clock.Restart(); } } // Update the constant buffer with the skin matrices for each bone context.UpdateSubresource(skinMatrices.Bones, PerArmatureBuffer); // Draw sub-meshes grouped by material for (var mIndx = 0; mIndx < mesh.Materials.Count; mIndx++) { // Retrieve sub meshes for this material var subMeshesForMaterial = (from sm in mesh.SubMeshes where sm.MaterialIndex == mIndx select sm).ToArray(); // If the material buffer is available and there are submeshes // using the material update the PerMaterialBuffer if (PerMaterialBuffer != null && subMeshesForMaterial.Length > 0) { // update the PerMaterialBuffer constant buffer var material = new ConstantBuffers.PerMaterial() { Ambient = new Color4(mesh.Materials[mIndx].Ambient), Diffuse = new Color4(mesh.Materials[mIndx].Diffuse), Emissive = new Color4(mesh.Materials[mIndx].Emissive), Specular = new Color4(mesh.Materials[mIndx].Specular), SpecularPower = mesh.Materials[mIndx].SpecularPower, UVTransform = mesh.Materials[mIndx].UVTransform, }; // Bind textures to the pixel shader int texIndxOffset = mIndx * Common.Mesh.MaxTextures; material.HasTexture = (uint)(textureViews[texIndxOffset] != null ? 1 : 0); // 0=false context.PixelShader.SetShaderResources(0, textureViews.GetRange(texIndxOffset, Common.Mesh.MaxTextures).ToArray()); // Set texture sampler state context.PixelShader.SetSampler(0, samplerState); // Update material buffer context.UpdateSubresource(ref material, PerMaterialBuffer); } // For each sub-mesh foreach (var subMesh in subMeshesForMaterial) { // Ensure the vertex buffer and index buffers are in range if (subMesh.VertexBufferIndex < vertexBuffers.Count && subMesh.IndexBufferIndex < indexBuffers.Count) { // Retrieve and set the vertex and index buffers var vertexBuffer = vertexBuffers[(int)subMesh.VertexBufferIndex]; context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBuffer, Utilities.SizeOf <Vertex>(), 0)); context.InputAssembler.SetIndexBuffer(indexBuffers[(int)subMesh.IndexBufferIndex], Format.R16_UInt, 0); // Set topology context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList; } // Draw the sub-mesh (includes Primitive count which we multiply by 3) // The submesh also includes a start index into the vertex buffer context.DrawIndexed((int)subMesh.PrimCount * 3, (int)subMesh.StartIndex, 0); } } }
public override void Render() { if (!ResourcesLoaded) { return; } var context = this.DeviceManager.Direct3DContext; var vs = this.vertexShader; // OutputMerger targets must be set for every frame in Windows Store apps context.OutputMerger.SetTargets(this.DepthStencilView, this.RenderTargetView); context.ClearDepthStencilView(this.DepthStencilView, SharpDX.Direct3D11.DepthStencilClearFlags.Depth | SharpDX.Direct3D11.DepthStencilClearFlags.Stencil, 1.0f, 0); context.ClearRenderTargetView(this.RenderTargetView, new SharpDX.Color(Color.R, Color.G, Color.B, 1)); // Set the context pipeline state SetContextState(context); ViewMatrix = Matrix.LookAtRH(Camera.Position, Camera.Position + Camera.LookAtDir, Vector3.UnitY); var viewProjection = ViewMatrix * ProjectionMatrix; // Extract camera position from view var camPosition = Matrix.Transpose(Matrix.Invert(ViewMatrix)).Column4; Camera.Position = new Vector3(camPosition.X, camPosition.Y, camPosition.Z); var perFrame = new ConstantBuffers.PerFrame(); perFrame.CameraPosition = Camera.Position; perFrame.Light.Color = new Color(0.8f, 0.8f, 0.8f, 1.0f); var lightDir = Vector3.Transform(new Vector3(1f, -1f, -1f), WorldMatrix); perFrame.Light.Direction = new Vector3(lightDir.X, lightDir.Y, lightDir.Z); context.UpdateSubresource(ref perFrame, perFrameBuffer); var perMaterial = new ConstantBuffers.PerMaterial(); perMaterial.Ambient = new Color4(0.2f); perMaterial.Diffuse = SharpDX.Color.White; perMaterial.Emissive = new Color4(0); perMaterial.Specular = SharpDX.Color.White; perMaterial.SpecularPower = 20f; context.UpdateSubresource(ref perMaterial, perMaterialBuffer); //var scale = this.SwapChainPanel.CompositionScaleX; foreach (var m in meshRenderers) { var worldRotation = Matrix.Identity;// *Matrix.RotationAxis(Vector3.UnitY, clock.ElapsedMilliseconds / 1000.0f); var perObject = new ConstantBuffers.PerObject(); perObject.World = m.World * WorldMatrix * worldRotation; perObject.WorldInverseTranspose = Matrix.Transpose(Matrix.Invert(perObject.World)); perObject.WorldViewProjection = perObject.World * viewProjection; perObject.Transpose(); context.UpdateSubresource(ref perObject, perObjectBuffer); m.Render(); } //textRenderer.Text = "Async resource loading"; //textRenderer.Render(); fpsRenderer.Render(); //// Draw a circle. //var d2dContext = DeviceManager.Direct2DContext; //float radiusX = this.RenderTargetSize.Width / 3.0f; //float radiusY = this.RenderTargetSize.Height / 3.0f; //float strokeWidth = 10.0f *this.SwapChainPanel.CompositionScaleX; //var brush = new SharpDX.Direct2D1.SolidColorBrush(d2dContext, SharpDX.Color.Black); //d2dContext.BeginDraw(); //using (var sc2 = SwapChain.QueryInterface<SwapChain2>()) //{ // d2dContext.Transform = sc2.MatrixTransform; //} //d2dContext.DrawEllipse(new SharpDX.Direct2D1.Ellipse(new Vector2(this.RenderTargetSize.Width / 2.0f, this.RenderTargetSize.Height / 2.0f), radiusX, radiusY), brush, strokeWidth ); //d2dContext.EndDraw(); // Present the render result Present(); }
public override void Render() { if (!ResourcesLoaded) return; var context = this.DeviceManager.Direct3DContext; var vs = this.vertexShader; // OutputMerger targets must be set for every frame in Windows Store apps context.OutputMerger.SetTargets(this.DepthStencilView, this.RenderTargetView); context.ClearDepthStencilView(this.DepthStencilView, SharpDX.Direct3D11.DepthStencilClearFlags.Depth | SharpDX.Direct3D11.DepthStencilClearFlags.Stencil, 1.0f, 0); context.ClearRenderTargetView(this.RenderTargetView, new SharpDX.Color(Color.R, Color.G, Color.B, 1)); // Set the context pipeline state SetContextState(context); ViewMatrix = Matrix.LookAtRH(Camera.Position, Camera.Position + Camera.LookAtDir, Vector3.UnitY); var viewProjection = ViewMatrix * ProjectionMatrix; // Extract camera position from view var camPosition = Matrix.Transpose(Matrix.Invert(ViewMatrix)).Column4; Camera.Position = new Vector3(camPosition.X, camPosition.Y, camPosition.Z); var perFrame = new ConstantBuffers.PerFrame(); perFrame.CameraPosition = Camera.Position; perFrame.Light.Color = new Color(0.8f, 0.8f, 0.8f, 1.0f); var lightDir = Vector3.Transform(new Vector3(1f, -1f, -1f), WorldMatrix); perFrame.Light.Direction = new Vector3(lightDir.X, lightDir.Y, lightDir.Z); context.UpdateSubresource(ref perFrame, perFrameBuffer); var perMaterial = new ConstantBuffers.PerMaterial(); perMaterial.Ambient = new Color4(0.2f); perMaterial.Diffuse = SharpDX.Color.White; perMaterial.Emissive = new Color4(0); perMaterial.Specular = SharpDX.Color.White; perMaterial.SpecularPower = 20f; context.UpdateSubresource(ref perMaterial, perMaterialBuffer); //var scale = this.SwapChainPanel.CompositionScaleX; foreach (var m in meshRenderers) { var worldRotation = Matrix.Identity;// *Matrix.RotationAxis(Vector3.UnitY, clock.ElapsedMilliseconds / 1000.0f); var perObject = new ConstantBuffers.PerObject(); perObject.World = m.World * WorldMatrix * worldRotation; perObject.WorldInverseTranspose = Matrix.Transpose(Matrix.Invert(perObject.World)); perObject.WorldViewProjection = perObject.World * viewProjection; perObject.Transpose(); context.UpdateSubresource(ref perObject, perObjectBuffer); m.Render(); } //textRenderer.Text = "Async resource loading"; //textRenderer.Render(); fpsRenderer.Render(); //// Draw a circle. //var d2dContext = DeviceManager.Direct2DContext; //float radiusX = this.RenderTargetSize.Width / 3.0f; //float radiusY = this.RenderTargetSize.Height / 3.0f; //float strokeWidth = 10.0f *this.SwapChainPanel.CompositionScaleX; //var brush = new SharpDX.Direct2D1.SolidColorBrush(d2dContext, SharpDX.Color.Black); //d2dContext.BeginDraw(); //using (var sc2 = SwapChain.QueryInterface<SwapChain2>()) //{ // d2dContext.Transform = sc2.MatrixTransform; //} //d2dContext.DrawEllipse(new SharpDX.Direct2D1.Ellipse(new Vector2(this.RenderTargetSize.Width / 2.0f, this.RenderTargetSize.Height / 2.0f), radiusX, radiusY), brush, strokeWidth ); //d2dContext.EndDraw(); // Present the render result Present(); }