public override void Run() { #region Create renderers // Note: the renderers take care of creating their own // device resources and listen for DeviceManager.OnInitialize // Create a axis-grid renderer var axisGrid = ToDispose(new AxisGridRenderer()); axisGrid.Initialize(this); var triangle = new TriangleRenderer(); triangle.Initialize(this); var quad = new QuadRenderer(); quad.Initialize(this); var bezier = new BezierPatchRenderer(); bezier.Initialize(this); var parametric = new ParametricRenderer(); parametric.Initialize(this); parametric.Show = false; // Create and initialize a Direct2D FPS text renderer var fps = ToDispose(new Common.FpsRenderer("Calibri", Color.CornflowerBlue, new Point(8, 8), 16)); fps.Initialize(this); // Create and initialize a general purpose Direct2D text renderer // This will display some instructions and the current view and rotation offsets var textRenderer = ToDispose(new Common.TextRenderer("Calibri", Color.CornflowerBlue, new Point(8, 40), 12)); textRenderer.Initialize(this); #endregion // Initialize the world matrix var worldMatrix = Matrix.Identity; // Set the camera position var cameraPosition = new Vector3(0, 0, 2); var cameraTarget = Vector3.Zero; // Looking at the origin 0,0,0 var cameraUp = Vector3.UnitY; // Y+ is Up // Prepare matrices // Create the view matrix from our camera position, look target and up direction var viewMatrix = Matrix.LookAtRH(cameraPosition, cameraTarget, cameraUp); viewMatrix.TranslationVector += new Vector3(0, -0.98f, 0); // Create the projection matrix /* FoV 60degrees = Pi/3 radians */ // Aspect ratio (based on window size), Near clip, Far clip var projectionMatrix = Matrix.PerspectiveFovRH((float)Math.PI / 3f, Width / (float)Height, 0.5f, 100f); // Maintain the correct aspect ratio on resize Window.Resize += (s, e) => { projectionMatrix = Matrix.PerspectiveFovRH((float)Math.PI / 3f, Width / (float)Height, 0.5f, 100f); }; #region Rotation and window event handlers // Create a rotation vector to keep track of the rotation // around each of the axes var rotation = new Vector3(0.0f, 0.0f, 0.0f); var tessellationFactor = 1f; var tessellationPartition = "Integer"; // We will call this action to update text // for the text renderer Action updateText = () => { textRenderer.Text = String.Format("Tessellation Factor: {0:#0.0} (+/- to change)" + "\nPartitioning: {1} (F1,F2,F3,F4 to change)" + "\nPress F to toggle wireframe" + "\nPress 1,2,3,4,5,6,7,8 to switch shaders", tessellationFactor, tessellationPartition, DeviceManager.Direct3DDevice.NativePointer); }; Dictionary <Keys, bool> keyToggles = new Dictionary <Keys, bool>(); keyToggles[Keys.Z] = false; keyToggles[Keys.F] = false; // Support keyboard/mouse input to rotate or move camera view var moveFactor = 0.02f; // how much to change on each keypress var shiftKey = false; var ctrlKey = false; var background = Color.White; var activeTriTessellator = tessellateTriIntegerShader; var activeQuadTessellator = tessellateQuadIntegerShader; var activeBezierTessellator = tessellateBezierIntegerShader; var activeParametricTessellator = tessellateParametricIntegerShader; var showNormals = false; Window.KeyDown += (s, e) => { var context = DeviceManager.Direct3DContext; shiftKey = e.Shift; ctrlKey = e.Control; switch (e.KeyCode) { // WASD -> pans view case Keys.A: viewMatrix.TranslationVector += new Vector3(moveFactor * 2, 0f, 0f); break; case Keys.D: viewMatrix.TranslationVector -= new Vector3(moveFactor * 2, 0f, 0f); break; case Keys.S: if (shiftKey) { viewMatrix.TranslationVector += new Vector3(0f, moveFactor * 2, 0f); } else { viewMatrix.TranslationVector -= new Vector3(0f, 0f, 1) * moveFactor * 2; } break; case Keys.W: if (shiftKey) { viewMatrix.TranslationVector -= new Vector3(0f, moveFactor * 2, 0f); } else { viewMatrix.TranslationVector += new Vector3(0f, 0f, 1) * moveFactor * 2; } break; // Up/Down and Left/Right - rotates around X / Y respectively // (Mouse wheel rotates around Z) case Keys.Down: worldMatrix *= Matrix.RotationX(moveFactor); rotation += new Vector3(moveFactor, 0f, 0f); break; case Keys.Up: worldMatrix *= Matrix.RotationX(-moveFactor); rotation -= new Vector3(moveFactor, 0f, 0f); break; case Keys.Left: worldMatrix *= Matrix.RotationY(moveFactor); rotation += new Vector3(0f, moveFactor, 0f); break; case Keys.Right: worldMatrix *= Matrix.RotationY(-moveFactor); rotation -= new Vector3(0f, moveFactor, 0f); break; case Keys.T: fps.Show = !fps.Show; textRenderer.Show = !textRenderer.Show; break; case Keys.B: if (background == Color.White) { background = new Color(30, 30, 34); } else { background = Color.White; } break; case Keys.G: axisGrid.Show = !axisGrid.Show; break; case Keys.P: // // Pause or resume mesh animation // meshes.ForEach(m => { // if (m.Clock.IsRunning) // m.Clock.Stop(); // else // m.Clock.Start(); // }); var p = Matrix.OrthoRH(3 * (Width / (float)Height), 3, 0.1f, 100f); if (projectionMatrix != p) { projectionMatrix = p; } else { projectionMatrix = Matrix.PerspectiveFovRH((float)Math.PI / 3f, Width / (float)Height, 0.5f, 100f); } break; case Keys.X: // To test for correct resource recreation // Simulate device reset or lost. System.Diagnostics.Debug.WriteLine(SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects()); DeviceManager.Initialize(DeviceManager.Dpi); System.Diagnostics.Debug.WriteLine(SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects()); break; case Keys.Z: keyToggles[Keys.Z] = !keyToggles[Keys.Z]; if (keyToggles[Keys.Z]) { context.PixelShader.Set(depthPixelShader); } else { context.PixelShader.Set(pixelShader); } break; case Keys.F: keyToggles[Keys.F] = !keyToggles[Keys.F]; RasterizerStateDescription rasterDesc; if (context.Rasterizer.State != null) { rasterDesc = context.Rasterizer.State.Description; } else { rasterDesc = new RasterizerStateDescription() { CullMode = CullMode.Back, FillMode = FillMode.Solid } }; if (keyToggles[Keys.F]) { rasterDesc.FillMode = FillMode.Wireframe; context.Rasterizer.State = ToDispose(new RasterizerState(context.Device, rasterDesc)); } else { rasterDesc.FillMode = FillMode.Solid; context.Rasterizer.State = ToDispose(new RasterizerState(context.Device, rasterDesc)); } break; case Keys.N: showNormals = !showNormals; break; case Keys.D1: context.PixelShader.Set(pixelShader); break; case Keys.D2: context.PixelShader.Set(lambertShader); break; case Keys.D3: context.PixelShader.Set(phongShader); break; case Keys.D4: context.PixelShader.Set(blinnPhongShader); break; case Keys.Add: tessellationFactor += 0.2f; tessellationFactor = Math.Min(tessellationFactor, 64); break; case Keys.Subtract: tessellationFactor -= 0.2f; tessellationFactor = Math.Max(tessellationFactor, 1); break; case Keys.F1: tessellationPartition = "Integer"; activeTriTessellator = tessellateTriIntegerShader; activeQuadTessellator = tessellateQuadIntegerShader; activeBezierTessellator = tessellateBezierIntegerShader; activeParametricTessellator = tessellateParametricIntegerShader; break; case Keys.F2: tessellationPartition = "Pow2"; activeTriTessellator = tessellateTriPow2Shader; activeQuadTessellator = tessellateQuadPow2Shader; activeBezierTessellator = tessellateBezierPow2Shader; activeParametricTessellator = tessellateParametricPow2Shader; break; case Keys.F3: tessellationPartition = "Fractional Even"; activeTriTessellator = tessellateTriFractionalEvenShader; activeQuadTessellator = tessellateQuadFractionalEvenShader; activeBezierTessellator = tessellateBezierFractionalEvenShader; activeParametricTessellator = tessellateParametricFractionalEvenShader; break; case Keys.F4: tessellationPartition = "Fractional Odd"; activeTriTessellator = tessellateTriFractionalOddShader; activeQuadTessellator = tessellateQuadFractionalOddShader; activeBezierTessellator = tessellateBezierFractionalOddShader; activeParametricTessellator = tessellateParametricFractionalOddShader; break; case Keys.Back: if (triangle.Show && quad.Show && bezier.Show) { triangle.Show = true; quad.Show = false; bezier.Show = false; parametric.Show = false; } else if (triangle.Show && quad.Show) { triangle.Show = false; quad.Show = false; bezier.Show = true; } else if (triangle.Show) { quad.Show = true; } else if (bezier.Show) { parametric.Show = true; bezier.Show = false; } else if (parametric.Show) { triangle.Show = true; quad.Show = true; bezier.Show = true; } break; } updateText(); }; Window.KeyUp += (s, e) => { // Clear the shift/ctrl keys so they aren't sticky if (e.KeyCode == Keys.ShiftKey) { shiftKey = false; } if (e.KeyCode == Keys.ControlKey) { ctrlKey = false; } }; Window.MouseWheel += (s, e) => { if (shiftKey) { // Zoom in/out viewMatrix.TranslationVector += new Vector3(0f, 0f, (e.Delta / 120f) * moveFactor * 2); } else { // rotate around Z-axis viewMatrix *= Matrix.RotationZ((e.Delta / 120f) * moveFactor); rotation += new Vector3(0f, 0f, (e.Delta / 120f) * moveFactor); } updateText(); }; var lastX = 0; var lastY = 0; Window.MouseDown += (s, e) => { if (e.Button == MouseButtons.Left) { lastX = e.X; lastY = e.Y; } }; Window.MouseMove += (s, e) => { if (e.Button == MouseButtons.Left) { var yRotate = lastX - e.X; var xRotate = lastY - e.Y; lastY = e.Y; lastX = e.X; // Mouse move changes viewMatrix *= Matrix.RotationX(-xRotate * moveFactor); viewMatrix *= Matrix.RotationY(-yRotate * moveFactor); updateText(); } }; // Display instructions with initial values updateText(); #endregion var clock = new System.Diagnostics.Stopwatch(); clock.Start(); #region Render loop // Create and run the render loop RenderLoop.Run(Window, () => { // Start of frame: // Retrieve immediate context var context = DeviceManager.Direct3DContext; // Clear depth stencil view context.ClearDepthStencilView(DepthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0); // Clear render target view context.ClearRenderTargetView(RenderTargetView, background); // Create viewProjection matrix var viewProjection = Matrix.Multiply(viewMatrix, projectionMatrix); // Extract camera position from view var camPosition = Matrix.Transpose(Matrix.Invert(viewMatrix)).Column4; cameraPosition = new Vector3(camPosition.X, camPosition.Y, camPosition.Z); // If Keys.CtrlKey is down, auto rotate viewProjection based on time var time = clock.ElapsedMilliseconds / 1000.0f; var perFrame = new ConstantBuffers.PerFrame(); 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);// new Vector3(Vector3.Transform(new Vector3(1f, -1f, 1f), worldMatrix * worldRotation).ToArray().Take(3).ToArray()); perFrame.CameraPosition = cameraPosition; perFrame.TessellationFactor = tessellationFactor; context.UpdateSubresource(ref perFrame, perFrameBuffer); // Render each object var perMaterial = new ConstantBuffers.PerMaterial(); perMaterial.Ambient = new Color4(0.2f); perMaterial.Diffuse = Color.White; perMaterial.Emissive = new Color4(0); perMaterial.Specular = Color.White; perMaterial.SpecularPower = 20f; perMaterial.HasTexture = 1; perMaterial.UVTransform = Matrix.Identity; context.UpdateSubresource(ref perMaterial, perMaterialBuffer); if (showNormals) { context.GeometryShader.Set(debugNormals); } var perObject = new ConstantBuffers.PerObject(); // MESH perObject.World = worldMatrix; perObject.WorldInverseTranspose = Matrix.Transpose(Matrix.Invert(perObject.World)); perObject.WorldViewProjection = perObject.World * viewProjection; perObject.ViewProjection = viewProjection; perObject.Transpose(); context.UpdateSubresource(ref perObject, perObjectBuffer); // TRIANGLE context.VertexShader.Set(tessellateVertexShader); context.HullShader.Set(activeTriTessellator); context.DomainShader.Set(tessellateTriDomainShader); triangle.Render(); // QUAD context.VertexShader.Set(tessellateVertexShader); context.HullShader.Set(activeQuadTessellator); context.DomainShader.Set(tessellateQuadDomainShader); quad.Render(); // BEZIER context.VertexShader.Set(tessellateVertexShader); context.HullShader.Set(activeBezierTessellator); context.DomainShader.Set(tessellateBezierDomainShader); bezier.Render(); // PARAMETRIC context.VertexShader.Set(tessellateVertexShader); context.HullShader.Set(activeParametricTessellator); context.DomainShader.Set(tessellateParametricDomainShader); parametric.Render(); // AXIS GRID context.VertexShader.Set(vertexShader); context.HullShader.Set(null); context.DomainShader.Set(null); context.GeometryShader.Set(null); using (var prevPixelShader = context.PixelShader.Get()) { perMaterial.HasTexture = 0; perMaterial.UVTransform = Matrix.Identity; context.UpdateSubresource(ref perMaterial, perMaterialBuffer); context.PixelShader.Set(pixelShader); perObject = new ConstantBuffers.PerObject(); perObject.World = worldMatrix; perObject.WorldInverseTranspose = Matrix.Transpose(Matrix.Invert(perObject.World)); perObject.WorldViewProjection = perObject.World * viewProjection; perObject.ViewProjection = viewProjection; perObject.Transpose(); context.UpdateSubresource(ref perObject, perObjectBuffer); axisGrid.Render(); context.PixelShader.Set(prevPixelShader); } // Render FPS fps.Render(); // Render instructions + position changes textRenderer.Render(); // Present the frame Present(); }); #endregion }
public override void Run() { #region Create renderers // Note: the renderers take care of creating their own // device resources and listen for DeviceManager.OnInitialize // Create a axis-grid renderer var axisGrid = ToDispose(new AxisGridRenderer()); axisGrid.Initialize(this); var triangle = new TriangleRenderer(); triangle.Initialize(this); var quad = new QuadRenderer(); quad.Initialize(this); var bezier = new BezierPatchRenderer(); bezier.Initialize(this); var parametric = new ParametricRenderer(); parametric.Initialize(this); parametric.Show = false; // Create and initialize a Direct2D FPS text renderer var fps = ToDispose(new Common.FpsRenderer("Calibri", Color.CornflowerBlue, new Point(8, 8), 16)); fps.Initialize(this); // Create and initialize a general purpose Direct2D text renderer // This will display some instructions and the current view and rotation offsets var textRenderer = ToDispose(new Common.TextRenderer("Calibri", Color.CornflowerBlue, new Point(8, 40), 12)); textRenderer.Initialize(this); #endregion // Initialize the world matrix var worldMatrix = Matrix.Identity; // Set the camera position var cameraPosition = new Vector3(0, 0, 2); var cameraTarget = Vector3.Zero; // Looking at the origin 0,0,0 var cameraUp = Vector3.UnitY; // Y+ is Up // Prepare matrices // Create the view matrix from our camera position, look target and up direction var viewMatrix = Matrix.LookAtRH(cameraPosition, cameraTarget, cameraUp); viewMatrix.TranslationVector += new Vector3(0, -0.98f, 0); // Create the projection matrix /* FoV 60degrees = Pi/3 radians */ // Aspect ratio (based on window size), Near clip, Far clip var projectionMatrix = Matrix.PerspectiveFovRH((float)Math.PI / 3f, Width / (float)Height, 0.5f, 100f); // Maintain the correct aspect ratio on resize Window.Resize += (s, e) => { projectionMatrix = Matrix.PerspectiveFovRH((float)Math.PI / 3f, Width / (float)Height, 0.5f, 100f); }; #region Rotation and window event handlers // Create a rotation vector to keep track of the rotation // around each of the axes var rotation = new Vector3(0.0f, 0.0f, 0.0f); var tessellationFactor = 1f; var tessellationPartition = "Integer"; // We will call this action to update text // for the text renderer Action updateText = () => { textRenderer.Text = String.Format("Tessellation Factor: {0:#0.0} (+/- to change)" + "\nPartitioning: {1} (F1,F2,F3,F4 to change)" + "\nPress F to toggle wireframe" + "\nPress 1,2,3,4,5,6,7,8 to switch shaders", tessellationFactor, tessellationPartition, DeviceManager.Direct3DDevice.NativePointer); }; Dictionary<Keys, bool> keyToggles = new Dictionary<Keys, bool>(); keyToggles[Keys.Z] = false; keyToggles[Keys.F] = false; // Support keyboard/mouse input to rotate or move camera view var moveFactor = 0.02f; // how much to change on each keypress var shiftKey = false; var ctrlKey = false; var background = Color.White; var activeTriTessellator = tessellateTriIntegerShader; var activeQuadTessellator = tessellateQuadIntegerShader; var activeBezierTessellator = tessellateBezierIntegerShader; var activeParametricTessellator = tessellateParametricIntegerShader; var showNormals = false; Window.KeyDown += (s, e) => { var context = DeviceManager.Direct3DContext; shiftKey = e.Shift; ctrlKey = e.Control; switch (e.KeyCode) { // WASD -> pans view case Keys.A: viewMatrix.TranslationVector += new Vector3(moveFactor * 2, 0f, 0f); break; case Keys.D: viewMatrix.TranslationVector -= new Vector3(moveFactor * 2, 0f, 0f); break; case Keys.S: if (shiftKey) viewMatrix.TranslationVector += new Vector3(0f, moveFactor * 2, 0f); else viewMatrix.TranslationVector -= new Vector3(0f, 0f, 1) * moveFactor * 2; break; case Keys.W: if (shiftKey) viewMatrix.TranslationVector -= new Vector3(0f, moveFactor * 2, 0f); else viewMatrix.TranslationVector += new Vector3(0f, 0f, 1) * moveFactor * 2; break; // Up/Down and Left/Right - rotates around X / Y respectively // (Mouse wheel rotates around Z) case Keys.Down: worldMatrix *= Matrix.RotationX(moveFactor); rotation += new Vector3(moveFactor, 0f, 0f); break; case Keys.Up: worldMatrix *= Matrix.RotationX(-moveFactor); rotation -= new Vector3(moveFactor, 0f, 0f); break; case Keys.Left: worldMatrix *= Matrix.RotationY(moveFactor); rotation += new Vector3(0f, moveFactor, 0f); break; case Keys.Right: worldMatrix *= Matrix.RotationY(-moveFactor); rotation -= new Vector3(0f, moveFactor, 0f); break; case Keys.T: fps.Show = !fps.Show; textRenderer.Show = !textRenderer.Show; break; case Keys.B: if (background == Color.White) { background = new Color(30, 30, 34); } else { background = Color.White; } break; case Keys.G: axisGrid.Show = !axisGrid.Show; break; case Keys.P: // // Pause or resume mesh animation // meshes.ForEach(m => { // if (m.Clock.IsRunning) // m.Clock.Stop(); // else // m.Clock.Start(); // }); var p = Matrix.OrthoRH(3 * (Width / (float)Height), 3, 0.1f, 100f); if (projectionMatrix != p) projectionMatrix = p; else { projectionMatrix = Matrix.PerspectiveFovRH((float)Math.PI / 3f, Width / (float)Height, 0.5f, 100f); } break; case Keys.X: // To test for correct resource recreation // Simulate device reset or lost. System.Diagnostics.Debug.WriteLine(SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects()); DeviceManager.Initialize(DeviceManager.Dpi); System.Diagnostics.Debug.WriteLine(SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects()); break; case Keys.Z: keyToggles[Keys.Z] = !keyToggles[Keys.Z]; if (keyToggles[Keys.Z]) { context.PixelShader.Set(depthPixelShader); } else { context.PixelShader.Set(pixelShader); } break; case Keys.F: keyToggles[Keys.F] = !keyToggles[Keys.F]; RasterizerStateDescription rasterDesc; if (context.Rasterizer.State != null) rasterDesc = context.Rasterizer.State.Description; else rasterDesc = new RasterizerStateDescription() { CullMode = CullMode.Back, FillMode = FillMode.Solid }; if (keyToggles[Keys.F]) { rasterDesc.FillMode = FillMode.Wireframe; context.Rasterizer.State = ToDispose(new RasterizerState(context.Device, rasterDesc)); } else { rasterDesc.FillMode = FillMode.Solid; context.Rasterizer.State = ToDispose(new RasterizerState(context.Device, rasterDesc)); } break; case Keys.N: showNormals = !showNormals; break; case Keys.D1: context.PixelShader.Set(pixelShader); break; case Keys.D2: context.PixelShader.Set(lambertShader); break; case Keys.D3: context.PixelShader.Set(phongShader); break; case Keys.D4: context.PixelShader.Set(blinnPhongShader); break; case Keys.Add: tessellationFactor += 0.2f; tessellationFactor = Math.Min(tessellationFactor, 64); break; case Keys.Subtract: tessellationFactor -= 0.2f; tessellationFactor = Math.Max(tessellationFactor, 1); break; case Keys.F1: tessellationPartition = "Integer"; activeTriTessellator = tessellateTriIntegerShader; activeQuadTessellator = tessellateQuadIntegerShader; activeBezierTessellator = tessellateBezierIntegerShader; activeParametricTessellator = tessellateParametricIntegerShader; break; case Keys.F2: tessellationPartition = "Pow2"; activeTriTessellator = tessellateTriPow2Shader; activeQuadTessellator = tessellateQuadPow2Shader; activeBezierTessellator = tessellateBezierPow2Shader; activeParametricTessellator = tessellateParametricPow2Shader; break; case Keys.F3: tessellationPartition = "Fractional Even"; activeTriTessellator = tessellateTriFractionalEvenShader; activeQuadTessellator = tessellateQuadFractionalEvenShader; activeBezierTessellator = tessellateBezierFractionalEvenShader; activeParametricTessellator = tessellateParametricFractionalEvenShader; break; case Keys.F4: tessellationPartition = "Fractional Odd"; activeTriTessellator = tessellateTriFractionalOddShader; activeQuadTessellator = tessellateQuadFractionalOddShader; activeBezierTessellator = tessellateBezierFractionalOddShader; activeParametricTessellator = tessellateParametricFractionalOddShader; break; case Keys.Back: if (triangle.Show && quad.Show && bezier.Show) { triangle.Show = true; quad.Show = false; bezier.Show = false; parametric.Show = false; } else if (triangle.Show && quad.Show) { triangle.Show = false; quad.Show = false; bezier.Show = true; } else if (triangle.Show) { quad.Show = true; } else if (bezier.Show) { parametric.Show = true; bezier.Show = false; } else if (parametric.Show) { triangle.Show = true; quad.Show = true; bezier.Show = true; } break; } updateText(); }; Window.KeyUp += (s, e) => { // Clear the shift/ctrl keys so they aren't sticky if (e.KeyCode == Keys.ShiftKey) shiftKey = false; if (e.KeyCode == Keys.ControlKey) ctrlKey = false; }; Window.MouseWheel += (s, e) => { if (shiftKey) { // Zoom in/out viewMatrix.TranslationVector += new Vector3(0f, 0f, (e.Delta / 120f) * moveFactor * 2); } else { // rotate around Z-axis viewMatrix *= Matrix.RotationZ((e.Delta / 120f) * moveFactor); rotation += new Vector3(0f, 0f, (e.Delta / 120f) * moveFactor); } updateText(); }; var lastX = 0; var lastY = 0; Window.MouseDown += (s, e) => { if (e.Button == MouseButtons.Left) { lastX = e.X; lastY = e.Y; } }; Window.MouseMove += (s, e) => { if (e.Button == MouseButtons.Left) { var yRotate = lastX - e.X; var xRotate = lastY - e.Y; lastY = e.Y; lastX = e.X; // Mouse move changes viewMatrix *= Matrix.RotationX(-xRotate * moveFactor); viewMatrix *= Matrix.RotationY(-yRotate * moveFactor); updateText(); } }; // Display instructions with initial values updateText(); #endregion var clock = new System.Diagnostics.Stopwatch(); clock.Start(); #region Render loop // Create and run the render loop RenderLoop.Run(Window, () => { // Start of frame: // Retrieve immediate context var context = DeviceManager.Direct3DContext; // Clear depth stencil view context.ClearDepthStencilView(DepthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0); // Clear render target view context.ClearRenderTargetView(RenderTargetView, background); // Create viewProjection matrix var viewProjection = Matrix.Multiply(viewMatrix, projectionMatrix); // Extract camera position from view var camPosition = Matrix.Transpose(Matrix.Invert(viewMatrix)).Column4; cameraPosition = new Vector3(camPosition.X, camPosition.Y, camPosition.Z); // If Keys.CtrlKey is down, auto rotate viewProjection based on time var time = clock.ElapsedMilliseconds / 1000.0f; var perFrame = new ConstantBuffers.PerFrame(); 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);// new Vector3(Vector3.Transform(new Vector3(1f, -1f, 1f), worldMatrix * worldRotation).ToArray().Take(3).ToArray()); perFrame.CameraPosition = cameraPosition; perFrame.TessellationFactor = tessellationFactor; context.UpdateSubresource(ref perFrame, perFrameBuffer); // Render each object var perMaterial = new ConstantBuffers.PerMaterial(); perMaterial.Ambient = new Color4(0.2f); perMaterial.Diffuse = Color.White; perMaterial.Emissive = new Color4(0); perMaterial.Specular = Color.White; perMaterial.SpecularPower = 20f; perMaterial.HasTexture = 1; perMaterial.UVTransform = Matrix.Identity; context.UpdateSubresource(ref perMaterial, perMaterialBuffer); if (showNormals) context.GeometryShader.Set(debugNormals); var perObject = new ConstantBuffers.PerObject(); // MESH perObject.World = worldMatrix; perObject.WorldInverseTranspose = Matrix.Transpose(Matrix.Invert(perObject.World)); perObject.WorldViewProjection = perObject.World * viewProjection; perObject.ViewProjection = viewProjection; perObject.Transpose(); context.UpdateSubresource(ref perObject, perObjectBuffer); // TRIANGLE context.VertexShader.Set(tessellateVertexShader); context.HullShader.Set(activeTriTessellator); context.DomainShader.Set(tessellateTriDomainShader); triangle.Render(); // QUAD context.VertexShader.Set(tessellateVertexShader); context.HullShader.Set(activeQuadTessellator); context.DomainShader.Set(tessellateQuadDomainShader); quad.Render(); // BEZIER context.VertexShader.Set(tessellateVertexShader); context.HullShader.Set(activeBezierTessellator); context.DomainShader.Set(tessellateBezierDomainShader); bezier.Render(); // PARAMETRIC context.VertexShader.Set(tessellateVertexShader); context.HullShader.Set(activeParametricTessellator); context.DomainShader.Set(tessellateParametricDomainShader); parametric.Render(); // AXIS GRID context.VertexShader.Set(vertexShader); context.HullShader.Set(null); context.DomainShader.Set(null); context.GeometryShader.Set(null); using (var prevPixelShader = context.PixelShader.Get()) { perMaterial.HasTexture = 0; perMaterial.UVTransform = Matrix.Identity; context.UpdateSubresource(ref perMaterial, perMaterialBuffer); context.PixelShader.Set(pixelShader); perObject = new ConstantBuffers.PerObject(); perObject.World = worldMatrix; perObject.WorldInverseTranspose = Matrix.Transpose(Matrix.Invert(perObject.World)); perObject.WorldViewProjection = perObject.World * viewProjection; perObject.ViewProjection = viewProjection; perObject.Transpose(); context.UpdateSubresource(ref perObject, perObjectBuffer); axisGrid.Render(); context.PixelShader.Set(prevPixelShader); } // Render FPS fps.Render(); // Render instructions + position changes textRenderer.Render(); // Present the frame Present(); }); #endregion }