Drawing an Arc with a linear gradient brush using Microsoft Maui Graphics - c#

I'm having difficulty drawing a gradient colored arc with Microsoft Maui Graphics.
I'm using Windows Forms, Visual Studio Preview 5, and .NET Core 6.
Here is what I have tried:
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Graphics.Skia;
using System;
using System.Windows.Forms;
namespace MauiWinForms {
public partial class Form1:Form {
public Form1() {
InitializeComponent();
}
private void skglControl1_PaintSurface(object sender, SkiaSharp.Views.Desktop.SKPaintGLSurfaceEventArgs e) {
ICanvas canvas = new SkiaCanvas() { Canvas = e.Surface.Canvas };
var canvasWidth = skglControl1.Width = 800;
var canvasHeight = skglControl1.Height = 800;
canvas.FillColor = Colors.LightGrey;
canvas.FillRectangle(0, 0, canvasWidth, canvasHeight);
canvas.StrokeColor = Colors.Red;
canvas.DrawRectangle(1, 1, 800-2, 800-2);
var centerX = canvasWidth / 2;
var centerY = canvasHeight / 2;
canvas.StrokeColor = Colors.Teal;
canvas.StrokeSize = 10;
var X = centerX - 200;
canvas.DrawArc(X, 0, 400, 400, 0, 90, false, false);
var linearGradientPaint = new LinearGradientPaint {
StartColor = Colors.White,
EndColor = Colors.Green,
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 0)
};
var myRectangle = new RectangleF(X, 0, 410, 410);
canvas.SetFillPaint(linearGradientPaint, myRectangle);
canvas.DrawArc(X, 0, 400, 400, 0, -90, false, false);
}
private void skglControl1_SizeChanged(object sender, EventArgs e) => skglControl1.Invalidate();
}
}
And this is what I get:
As you can see, the linear gradient is not applied.
Any help will be greatly appreciated.
Charles

Related

C# ToolStripProfessionalRender, event OnRenderItemText applied only on the first item

I'm drawing a custom toolstrip using ToolStripProfessionalRender and editing the OnRenderItemText event as follows:
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
e.Item.ForeColor = Clr.White;
e.Item.TextAlign = ContentAlignment.MiddleLeft;
e.Item.Alignment = ToolStripItemAlignment.Left;
base.OnRenderItemText(e);
if (e.Item.GetType() == typeof(ToolStripDropDownButton))
{
ToolStripDropDownButton tsmi = (ToolStripDropDownButton)e.Item;
if (tsmi.HasDropDownItems && tsmi.OwnerItem == null)
{
Rectangle bounds = tsmi.Bounds;
bounds.X = bounds.Right - 25;
bounds.Width = 25;
bounds.Y = 10;
// Draw the corner
Graphics G = e.Graphics;
SolidBrush brushw = new SolidBrush(Color.FromArgb(70,70,70));
Point[] points =
{
new Point(bounds.Right - 3, bounds.Height - 11), // point top right
new Point(bounds.Right - 3, bounds.Bottom - 14), // point bottom right
new Point(bounds.Right - 10, bounds.Bottom - 14) // point bottom left
};
G.FillPolygon(brushw, points);
}
}
}
and basically the output i'm trying to obtain is the following:
So drawing a little triangle on the bottom right corner when i got a ToolStripDropDownButton. The problem is that the little triangle is drawn only first item.
To end up the question i draw this toolstrip dynamically using a function that adds a dropdownbutton at each call.
ToolStripDropDownButton m_Item = new ToolStripDropDownButton(text, image);
m_Item.ImageAlign = ContentAlignment.MiddleCenter;
m_Item.ImageScaling = ToolStripItemImageScaling.None;
m_Item.Name = name;
m_Item.ForeColor = Color.White;
m_Item.BackColor = Color.FromArgb(95, 95, 95);
m_Item.Padding = new Padding(5);
m_Item.ShowDropDownArrow = false;
m_Item.Paint += new PaintEventHandler(this.PaintButtonBorder);
if (tabPage != null)
m_Item.Click += (sender, e) => AddClickTab(sender, e, tabPage);
((ToolStripDropDownMenu)m_Item.DropDown).ShowImageMargin = false;
((ToolStripDropDownMenu)m_Item.DropDown).ShowCheckMargin = false;
((ToolStripDropDownMenu)m_Item.DropDown).Cursor = Cursors.Hand;
toolStrip1.Items.Add(m_Item);
if (SubItems != null)
{
for(int i = 0; i < SubItems.Length; i++)
{
object[] subitem = (object[])SubItems[i];
FnAddToolStripMenuItem(
subitem[0].ToString(),
subitem[1].ToString(),
(Bitmap)subitem[2],
m_Item,
(TabPage)subitem[3]
);
}
}
Am i missing some "new" maybe?
Override the OnRenderItemText method only to draw the text part as it says, and/or to set the default properties used when rendering the text. To change the look and the shape of the arrows of the dropdown items, override the OnRenderArrow method.
Example
using System.Drawing;
using System.Drawing.Drawing2D;
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
{
// Optional: to be the default color of the arrows.
e.ArrowColor = Color.FromArgb(70, 70, 70);
if (e.Item is ToolStripDropDownButton item && item.OwnerItem == null)
{
var g = e.Graphics;
var r = new Rectangle(item.Bounds.Width - 10, item.Bounds.Height - 10, 8, 8);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.PixelOffsetMode = PixelOffsetMode.Half;
using (var br = new SolidBrush(e.ArrowColor))
g.FillPolygon(br, new[]
{
new Point(r.Left, r.Bottom),
new Point(r.Right, r.Top),
new Point(r.Right, r.Bottom)
});
g.SmoothingMode = SmoothingMode.None;
g.PixelOffsetMode = PixelOffsetMode.Default;
}
else
base.OnRenderArrow(e);
}
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
e.Item.ForeColor = Color.White;
e.Item.TextAlign = ContentAlignment.MiddleLeft;
e.Item.Alignment = ToolStripItemAlignment.Left;
base.OnRenderItemText(e);
}
Make sure to enable the ShowDropDownArrow property of the dropdown buttons. So comment this m_Item.ShowDropDownArrow = false;.
If you are also interested to change the color according to the current state of the dropdown button (Selected, Pressed), then you can do for example:
using (var br = new SolidBrush(item.Selected
? Color.FromArgb(150, 150, 150) : item.Pressed
? Color.FromArgb(100, 100, 100) :
Color.FromArgb(70, 70, 70)))
//...

SharpDX is filling entire form instead of drawing triangle

I'm trying to write simple DirectX 11 app using C# and SharpDX. I wanted to test basic drawing but when i run the program, i will get entire form filled with red color. When i change the vertices its drawing unwanted shapes. Clear color works.
I tried changing some properties but nothing helps.
Here is the code:
private Vector3[] Vertices = new Vector3[]
{
new Vector3(-0.5f, 0.5f, 0), new Vector3(0.5f, 0.5f, 0), new Vector3(0, -0.5f, 0)
};
private D3D11.Buffer VertexBuffer;
public Game()
{
RenderForm = new RenderForm("Test Form");
RenderForm.ClientSize = new Size(Width, Height);
RenderForm.AllowUserResizing = false;
InitDeviceResources();
InitShaders();
InitVertexBuffer();
}
public void Run()
{
RenderLoop.Run(RenderForm, RenderCallback);
}
private void InitVertexBuffer()
{
VertexBuffer = D3D11.Buffer.Create<Vector3>(Device, BindFlags.VertexBuffer, Vertices);
}
private void InitShaders()
{
using (ShaderBytecode vertexShaderBytecode = ShaderBytecode.CompileFromFile("vertexShader.hlsl", "main", "vs_4_0", ShaderFlags.Debug))
{
InputSignature = ShaderSignature.GetInputSignature(vertexShaderBytecode);
VertexShader = new VertexShader(Device, vertexShaderBytecode);
}
using (ShaderBytecode pixelShaderBytecode = ShaderBytecode.CompileFromFile("pixelShader.hlsl", "main", "ps_4_0", ShaderFlags.Debug))
{
PixelShader = new PixelShader(Device, pixelShaderBytecode);
}
Context.VertexShader.Set(VertexShader);
Context.PixelShader.Set(PixelShader);
Context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
InputLayout = new InputLayout(Device, InputSignature, InputElements);
Context.InputAssembler.InputLayout = InputLayout;
}
private void InitDeviceResources()
{
ModeDescription backBufferDesc = new ModeDescription(Width, Height, new Rational(60, 1), Format.B8G8R8A8_UNorm);
SwapChainDescription swapChainDesc = new SwapChainDescription()
{
BufferCount = 1,
IsWindowed = true,
OutputHandle = RenderForm.Handle,
ModeDescription = backBufferDesc,
SampleDescription = new SampleDescription(1, 0),
Usage = Usage.RenderTargetOutput
};
D3D11.Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, swapChainDesc, out Device, out SwapChain);
Context = Device.ImmediateContext;
Viewport = new Viewport(0, 0, Width, Height);
Context.Rasterizer.SetViewport(Viewport);
using (Texture2D backBuffer = SwapChain.GetBackBuffer<Texture2D>(0))
{
RenderTarget = new RenderTargetView(Device, backBuffer);
}
}
private void RenderCallback()
{
Draw();
}
private void Draw()
{
Context.OutputMerger.SetRenderTargets(RenderTarget);
Context.ClearRenderTargetView(RenderTarget, new Color4(0, 0, 1, 1));
Context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VertexBuffer, Utilities.SizeOf<Vector3>(), 0));
Context.Draw(Vertices.Count(), 0);
SwapChain.Present(1, PresentFlags.None);
}
I finally solved this. There must be Format.R32G32B32_Float instead of Format.R32G32B32A32_Float

How to draw with Skia on Cairo context in Gtk3

I'm expecting to get colored rectangle, but getting rectangle of garbage instead. So far I have the following code:
using System;
using GLib;
using SkiaSharp;
using Gtk;
namespace SkiaSharpExample {
class CCDrawingArea : DrawingArea {
protected override bool OnDrawn (Cairo.Context cr) {
using (var skSurface = SKSurface.Create (100, 100, SKColorType.N_32, SKAlphaType.Premul)) {
var canvas = skSurface.Canvas;
var paint = new SKPaint {
StrokeWidth = 4,
Color = new SKColor (255, 255, 255, 255)
};
var rect = new SKRect (10, 10, 50, 50);
canvas.DrawRect (rect, paint);
var image = skSurface.Snapshot ();
Cairo.Surface surface = new Cairo.ImageSurface (
image.Encode ().Data,
Cairo.Format.Argb32,
image.Width, image.Height,
4 * image.Width * image.Height);
surface.MarkDirty ();
cr.SetSourceSurface (surface, 0, 0);
cr.Paint ();
}
return true;
}
}
class MainClass {
public static void Main (string[] args){
ExceptionManager.UnhandledException += delegate(UnhandledExceptionArgs expArgs) {
Console.WriteLine (expArgs.ExceptionObject.ToString ());
expArgs.ExitApplication = true;
};
Gtk.Application.Init ();
var window = new Window ("Hello World");
window.SetDefaultSize (1024, 800);
window.SetPosition (WindowPosition.Center);
window.DeleteEvent += delegate {
Gtk.Application.Quit ();
};
var darea = new CCDrawingArea ();
window.Add (darea);
window.ShowAll ();
Gtk.Application.Run ();
}
}
}
I have no clue about Skia and I can't find any documentation on its image format, but the last argument here should be the stride. The natural stride would be 4*image.Width. Is that what Skia uses, too? (stride is the number of bytes between the beginning of a pixel and the pixel below that one)
Cairo.Surface surface = new Cairo.ImageSurface (
image.Encode ().Data,
Cairo.Format.Argb32,
image.Width, image.Height,
4 * image.Width * image.Height);
I have found the soulution I should have been using SKBitmap before creating SKSurface and SKCanvas. To get pixel data I should have been using SKBitmap.GetPixels method. Here follows the source code of working example:
using System;
using GLib;
using SkiaSharp;
using Gtk;
namespace SkiaSharpExample
{
class CCDrawingArea : DrawingArea
{
protected override bool OnDrawn(Cairo.Context cr)
{
const int width = 100;
const int height = 100;
using (var bitmap = new SKBitmap(width, height, SKColorType.N_32, SKAlphaType.Premul))
{
IntPtr len;
using (var skSurface = SKSurface.Create(bitmap.Info.Width, bitmap.Info.Height, SKColorType.N_32, SKAlphaType.Premul, bitmap.GetPixels(out len), bitmap.Info.RowBytes))
{
var canvas = skSurface.Canvas;
canvas.Clear(SKColors.White);
using (var paint = new SKPaint())
{
paint.StrokeWidth = 4;
paint.Color = new SKColor(0x2c, 0x3e, 0x50);
var rect = new SKRect(10, 10, 50, 50);
canvas.DrawRect(rect, paint);
}
Cairo.Surface surface = new Cairo.ImageSurface(
bitmap.GetPixels(out len),
Cairo.Format.Argb32,
bitmap.Width, bitmap.Height,
bitmap.Width * 4);
surface.MarkDirty();
cr.SetSourceSurface(surface, 0, 0);
cr.Paint();
}
}
return true;
}
}
class MainClass
{
public static void Main(string[] args)
{
ExceptionManager.UnhandledException += delegate(UnhandledExceptionArgs expArgs)
{
Console.WriteLine(expArgs.ExceptionObject.ToString());
expArgs.ExitApplication = true;
};
Gtk.Application.Init();
var window = new Window("Hello Skia World");
window.SetDefaultSize(1024, 800);
window.SetPosition(WindowPosition.Center);
window.DeleteEvent += delegate
{
Gtk.Application.Quit();
};
var darea = new CCDrawingArea();
window.Add(darea);
window.ShowAll();
Gtk.Application.Run();
}
void OnException(object o, UnhandledExceptionArgs args)
{
}
}
}

UIScrollView Scroll Not working Xamarin IOS

Create the scroll view added to UIViewController View
UIScroll scroll_View;
scroll_View = new UIScrollView {
BackgroundColor = UIColor.Black,
Frame = View.Frame,
ContentSize = new SizeF(320,720),
};
View.addSubView(scroll_View);// Added to Regisration ViewController
// Created text Fields
firstName = new UITextField {
Placeholder = "Enter firstName",
BorderStyle = UITextBorderStyle.None,
VerticalAlignment = UIControlContentVerticalAlignment.Center,
AutocorrectionType = UITextAutocorrectionType.No,
AutocapitalizationType = UITextAutocapitalizationType.None,
ClearButtonMode = UITextFieldViewMode.WhileEditing,
Background = TextFieldBackground,
LeftView = new UIView (new RectangleF (0, 0,8, 8)),
LeftViewMode = UITextFieldViewMode.Always,
ReturnKeyType = UIReturnKeyType.Next,
ShouldReturn = delegate {
lastName.BecomeFirstResponder ();
return true;
}
};
// Like this created 9 textfields and one submit button. added to ScrollView
Frame TextField.
firstName.Frame = new RectangleF(80, 20, 200, 41);
lastName.Frame = new RectangleF(80, 70, 200, 41);
middle.Frame = new RectangleF(80, 120, 200, 41);
email.Frame = new RectangleF(80, 127, 200, 41);
password.Frame = new RectangleF(80, 220, 200, 41);
conformPassword.Frame = new RectangleF(80, 270, 200, 41);
phoneNumber.Frame = new RectangleF(80, 320, 200, 41);
description.Frame = new RectangleF(80, 370, 200, 41);
other.Frame = new RectangleF(80, 420, 200, 41);
buttonSubmit.Frame = new RectangleF(80, 470, 420, 41);
Adding textfield to ScrollView
scroll_View.addSubView(firstName);
scroll_View.addSubView(lastName);
scroll_View.addSubView(middleName);
scroll_View.addSubView(email);
scroll_View.addSubView(Password);
scroll_View.addSubView(conformaPassword);
scroll_View.addSubView(phoneNumber);
scroll_View.addSubView(description);
scroll_View.addSubView(other);
scroll_View.addSubView(buttonSubmit);
Added Scroll View UIViewController View.
View.AddSubview (scroll_View);
When scrolling scrolling effect is not working. Xamarin IOS.
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
float h = 50.0f;
float w = 50.0f;
float padding = 10.0f;
int n = 25;
_scrollView = new UIScrollView {
Frame = new RectangleF (0, 0, View.Frame.Width, h + 2 * padding),
ContentSize = new SizeF ((w + padding) * n, h),
BackgroundColor = UIColor.DarkGray,
AutoresizingMask = UIViewAutoresizing.FlexibleWidth
};
for (int i=0; i<n; i++) {
var button = UIButton.FromType (UIButtonType.RoundedRect);
button.SetTitle (i.ToString (), UIControlState.Normal);
button.Frame = new RectangleF (padding * (i + 1) + (i * w), padding, w, h);
_scrollView.AddSubview (button);
_buttons.Add (button);
}
View.AddSubview (_scrollView);
}
Try to use "ContentSize " property in UIScrollView.
If you want to enable "Horizontal Scroll on UIScrollView" , need to increase the width of contentsize.
If you want to enable "Vertical Scroll on UIScrollView" , need to increase the height of contentsize.
UIScrollView *scrollView =[[UIScrollView
alloc]initWithFrame:CGRectMake(0, 40, 500, 300)];
scrollView.contentSize=CGSizeMake(1500, 200); //Horizontal scrolling
UIScrollView *scrollView =[[UIScrollView
alloc]initWithFrame:CGRectMake(0, 40, 500, 300)];
scrollView.contentSize=CGSizeMake(200, 1500); //vertical scrolling
Not a real answer yet it seems on this old question, but for future references: The problem in these cases is mostly that the ContentSize is equal to or smaller then the frame of the ScrollView. Therefore the ScrollView is unaware of the need to scroll.
In your case you should verify that the ContentSize of 320x720 is larger than the View.Frame you assign to the ScrollView Frame...
public class FirstTab : UIViewController
{
private UIView content1;
private UIView content2;
private UIView content3;
private UIView containerView;
private UIScrollView scrollView;
CoreGraphics.CGSize contentViewSize;
public FirstTab()
{
content1 = new UIView();
content2 = new UIView();
content3 = new UIView();
containerView = new UIView();
scrollView = new UIScrollView();
contentViewSize = new CoreGraphics.CGSize(View.Frame.Width, View.Frame.Height + 800);
}
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
scrollView.ContentSize = contentViewSize;
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
content1.BackgroundColor = UIColor.Red;
content2.BackgroundColor = UIColor.Black;
content3.BackgroundColor = UIColor.Brown;
Constraint();
}
private void Constraint()
{
containerView.AddSubviews(content1, content2, content3);
containerView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
containerView.AddConstraints(
content1.Width().EqualTo(300),
content1.Height().EqualTo(300),
content1.AtTopOf(containerView).Plus(20),
content1.WithSameCenterX(containerView),
content2.Width().EqualTo(300),
content2.Height().EqualTo(300),
content2.Below(content1).Plus(20),
content2.WithSameCenterX(containerView),
content3.Width().EqualTo(300),
content3.Height().EqualTo(300),
content3.Below(content2).Plus(20),
content3.WithSameCenterX(containerView)
);
scrollView.AddSubviews(containerView);
scrollView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
scrollView.AddConstraints(
containerView.WithSameHeight(scrollView).Plus(300),
containerView.WithSameWidth(scrollView)
);
View.AddSubviews(scrollView);
View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
View.AddConstraints(
scrollView.WithSameWidth(View),
scrollView.WithSameHeight(View).Plus(400)
);
}
}
UIScrollView will work when You put the ScrollView.ContentSize into ViewWillLayoutSubview() method.
It took me very long time to find this simple trick for a working UIScrollView. I have used Cirrious.FluentLayout for autolayout.
In this case u need better work with UITableView not UIScrollView.

SlimDX low performance with many vertices

So I've been playing around with SlimDX for quite a while now,
and experienced some issues with big STL files.
While on OpenGL they load without flinching I get down to 1-2 FPS an soon as I load files of about 100mb (same issues with multiple files) in SharpGL. Did I miss anything, or is there anything I am simply doing not right at all ?
Edit: Just to specify my question: is performance with SlimDX on 1.000.000+ vertices always that poor ?
Edit: I know, that using an index buffer would be more efficient, as well as I know that CullingMode.None isn't really a FPS-Saver, but in the OpenGL test I've even used two sided lighting and a bit of smoothing, which should be as hard as creating (in the worst case) 3 times as many points as necessary.
Edit: Out of curiosity I modified the code to include an indexBuffer, and it really did have some impact on the FPS, I am validating this right now
BasicFramework.cs
#region Using Statements
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using SlimDX;
using SlimDX.Direct3D11;
using SlimDX.DXGI;
using SlimDX.Windows;
using Device = SlimDX.Direct3D11.Device;
using Texture2D = SlimDX.Direct3D11.Texture2D;
#endregion
namespace SlimDX_Evaluation
{
public abstract class BasicFramework : IDisposable
{
#region Membervariables
//Objects
private RenderForm renderForm;
private SwapChain swapChain;
private Factory factory;
private Device device;
private DeviceContext deviceContext;
private Texture2D backBufffer;
private Texture2D depthBuffer;
private RenderTargetView renderTargetView;
private DepthStencilView depthStencilView;
private TimeSpan lastFrameTime;
private Stopwatch clock;
//Variables
private bool userResized;
private bool isResizing;
#endregion
#region Constructors
/**
* The Constructor initializes the default behavior of the Framework.
* It is not supposed to be replaced, the customization should be done in the Constructor
*/
public BasicFramework() : this("My Title") { }
public BasicFramework(string title)
{
//Create the winForm
renderForm = new RenderForm(title);
renderForm.ClientSize = new System.Drawing.Size(800, 480);
renderForm.MaximizeBox = true;
renderForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
//Hook into Windows.Forms Event
renderForm.ClientSizeChanged += HandleClientSizeChanged;
//Generate SwapChain
var desc = new SwapChainDescription()
{
BufferCount = 1,
ModeDescription = new ModeDescription(renderForm.ClientSize.Width,
renderForm.ClientSize.Height,
new Rational(60, 1),
Format.B8G8R8A8_UNorm),
IsWindowed = true,
OutputHandle = renderForm.Handle,
SampleDescription = new SampleDescription(1, 0),
SwapEffect = SwapEffect.Discard,
Usage = Usage.RenderTargetOutput,
};
Device.CreateWithSwapChain(
DriverType.Hardware,
DeviceCreationFlags.None,
desc,
out device,
out swapChain
);
//Set DeviceContext
deviceContext = device.ImmediateContext;
// prevent DXGI handling of alt+enter,prt scrn, etc which doesn't work properly with Winforms
using (var factory = swapChain.GetParent<Factory>())
factory.SetWindowAssociation(renderForm.Handle, WindowAssociationFlags.IgnoreAll);
//Generate Backbuffer
backBufffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0);
renderTargetView = new RenderTargetView(device, backBufffer);
//Generate Depthbuffer and DepthBufferView
depthBuffer = new Texture2D(device, new Texture2DDescription()
{
Format = Format.D16_UNorm,
ArraySize = 1,
MipLevels = 1,
Width = renderForm.ClientSize.Width,
Height = renderForm.ClientSize.Height,
SampleDescription = new SampleDescription(1, 0),
Usage = ResourceUsage.Default,
BindFlags = BindFlags.DepthStencil,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None,
});
depthStencilView = new DepthStencilView(device, depthBuffer);
//Define Rasterizer
RasterizerStateDescription rasterizerDescription = new RasterizerStateDescription()
{
CullMode = CullMode.None,
FillMode = FillMode.Solid,
IsAntialiasedLineEnabled = true,
IsFrontCounterclockwise = true,
IsMultisampleEnabled = true,
IsDepthClipEnabled = true,
IsScissorEnabled = false
};
deviceContext.Rasterizer.State = RasterizerState.FromDescription(device, rasterizerDescription);
//Set ViewPort
deviceContext.Rasterizer.SetViewports(new Viewport(
0,
0,
renderForm.Width,
renderForm.Height));
deviceContext.OutputMerger.SetTargets(depthStencilView, renderTargetView);
//Force recalibration on first load
userResized = true;
}
#endregion
#region Run
public void Run()
{
clock = new Stopwatch();
clock.Start();
this.lastFrameTime = clock.Elapsed;
Initialize();
LoadContent();
MessagePump.Run(renderForm, () =>
{
if (userResized)
{
backBufffer.Dispose();
RenderTargetView.Dispose();
depthBuffer.Dispose();
depthStencilView.Dispose();
//Resize the buffers
swapChain.ResizeBuffers(
0,
renderForm.ClientSize.Width,
renderForm.ClientSize.Height,
Format.Unknown,
SwapChainFlags.None
);
//Get the new Backbuffer
backBufffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0);
//Renew RenderTargetView
renderTargetView = new RenderTargetView(device, backBufffer);
//Create the new DepthBuffer
depthBuffer = new Texture2D(device, new Texture2DDescription()
{
Format = Format.D32_Float_S8X24_UInt,
ArraySize = 1,
MipLevels = 1,
Width = renderForm.ClientSize.Width,
Height = renderForm.ClientSize.Height,
SampleDescription = new SampleDescription(1, 0),
Usage = ResourceUsage.Default,
BindFlags = BindFlags.DepthStencil,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None
});
//Create DepthBufferView
depthStencilView = new DepthStencilView(device, depthBuffer);
//SetUp Targets and Viewports for Rendering
deviceContext.Rasterizer.SetViewports(new Viewport(0, 0, renderForm.Width, renderForm.Height));
deviceContext.OutputMerger.SetTargets(depthStencilView, renderTargetView);
//finished resizing
isResizing = userResized = false;
}
TimeSpan timeSinceLastFrame = clock.Elapsed - this.lastFrameTime;
this.lastFrameTime = clock.Elapsed;
Update(clock.Elapsed, timeSinceLastFrame);
BeginFrame();
Draw(clock.Elapsed, timeSinceLastFrame);
EndFrame();
});
UnloadContent();
}
#endregion
#region MethodsToOverride
public virtual void Update(TimeSpan totalRunTime, TimeSpan timeSinceLastFrame)
{
}
public virtual void Draw(TimeSpan totalRunTime, TimeSpan timeSinceLastFrame)
{
}
public virtual void BeginFrame()
{
}
public void EndFrame()
{
swapChain.Present(0, PresentFlags.None); //Presents the image to the user
}
public virtual void Initialize()
{
}
public virtual void LoadContent()
{
}
public virtual void UnloadContent()
{
}
public virtual void Dispose()
{
renderForm.Dispose();
backBufffer.Dispose();
deviceContext.ClearState();
deviceContext.Flush();
device.Dispose();
deviceContext.Dispose();
depthBuffer.Dispose();
depthStencilView.Dispose();
swapChain.Dispose();
}
#endregion
#region Handlers
private void HandleResize(object sender, EventArgs e)
{
backBufffer.Dispose();
RenderTargetView.Dispose();
depthBuffer.Dispose();
depthStencilView.Dispose();
//Resize the buffers
swapChain.ResizeBuffers(
0,
renderForm.ClientSize.Width,
renderForm.ClientSize.Height,
Format.Unknown,
SwapChainFlags.None
);
//Get the new Backbuffer
backBufffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0);
//Renew RenderTargetView
renderTargetView = new RenderTargetView(device, backBufffer);
//Create the new DepthBuffer
depthBuffer = new Texture2D(device, new Texture2DDescription()
{
Format = Format.D32_Float_S8X24_UInt,
ArraySize = 1,
MipLevels = 1,
Width = renderForm.ClientSize.Width,
Height = renderForm.ClientSize.Height,
SampleDescription = new SampleDescription(1, 0),
Usage = ResourceUsage.Default,
BindFlags = BindFlags.DepthStencil,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None
});
//Create DepthBufferView
depthStencilView = new DepthStencilView(device, depthBuffer);
//SetUp Targets and Viewports for Rendering
deviceContext.Rasterizer.SetViewports(new Viewport(0, 0, renderForm.Width, renderForm.Height));
deviceContext.OutputMerger.SetTargets(depthStencilView, renderTargetView);
//finished resizing
isResizing = userResized = false;
TimeSpan timeSinceLastFrame = clock.Elapsed - this.lastFrameTime;
this.lastFrameTime = clock.Elapsed;
Update(clock.Elapsed, timeSinceLastFrame);
BeginFrame();
Draw(clock.Elapsed, timeSinceLastFrame);
EndFrame();
}
private void HandleClientSizeChanged(object sender, EventArgs e)
{
userResized = true;
}
#endregion
#region GetAndSet
public Device Device
{
get
{
return this.device;
}
}
public DeviceContext DeviceContext
{
get
{
return this.deviceContext;
}
}
public RenderTargetView RenderTargetView
{
get
{
return this.renderTargetView;
}
}
public RenderForm RenderForm
{
get
{
return this.renderForm;
}
}
public DepthStencilView DepthStencilView
{
get
{
return this.depthStencilView;
}
}
#endregion
}
}
SimpleIntegration.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using SlimDX;
using SlimDX.D3DCompiler;
using SlimDX.Direct3D11;
using Buffer = SlimDX.Direct3D11.Buffer;
using System.Diagnostics;
namespace SlimDX_Evaluation
{
class SampleIntegration : BasicFramework
{
#region Members
private VertexShader vertexShader;
private PixelShader pixelShader;
private Buffer constantBuffer;
private VertexBufferBinding vertexBufferBinding_model;
private int vertCount;
private Stopwatch timer;
private long lastFrame;
private int frameCount;
private Matrix view;
private Matrix proj;
private Matrix viewProj;
Matrix worldViewProj;
#endregion
public override void Draw(TimeSpan totalRunTime, TimeSpan timeSinceLastFrame)
{
//Output FPS
frameCount++;
if (timer.ElapsedMilliseconds - lastFrame >= 1000)
{
Console.WriteLine("FPS: " + frameCount);
lastFrame = timer.ElapsedMilliseconds;
frameCount = 0;
}
worldViewProj = Matrix.Multiply(Matrix.RotationAxis(Vector3.UnitY, timer.ElapsedMilliseconds / 1000.0f), viewProj);
//Update ConstantBuffer
var buffer = new MyConstantBuffer();
buffer.worldViewProj = worldViewProj;
var data = new DataStream(System.Runtime.InteropServices.Marshal.SizeOf(new MyConstantBuffer()), true, true);
data.Write(buffer);
data.Position = 0;
DeviceContext.UpdateSubresource(new DataBox(0, 0, data),constantBuffer,0);
//Clear
Device.ImmediateContext.ClearRenderTargetView(RenderTargetView, Color.WhiteSmoke);
Device.ImmediateContext.ClearDepthStencilView(DepthStencilView, DepthStencilClearFlags.Depth, 1.0f, 0);
//Draw
DeviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
DeviceContext.InputAssembler.SetVertexBuffers(0, vertexBufferBinding_model);
Device.ImmediateContext.Draw(vertCount, 0);
base.Draw(totalRunTime, timeSinceLastFrame);
}
public override void LoadContent()
{
//Initialize the timer
timer = new Stopwatch();
timer.Start();
//Initialize Matrices
view = Matrix.LookAtLH(new Vector3(0, 100, -500), new Vector3(0, 0, 0), Vector3.UnitY);
proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, RenderForm.ClientSize.Width / RenderForm.ClientSize.Height, 0.1f, 10000.0f);
viewProj = Matrix.Multiply(view, proj);
//Load Shaders
ShaderBytecode vertexShaderByteCode;
ShaderBytecode pixelShaderByteCode;
try
{
vertexShaderByteCode = ShaderBytecode.CompileFromFile("Shaders/shader.hlsl", "VShader", "vs_4_0",ShaderFlags.None,EffectFlags.None);
pixelShaderByteCode = ShaderBytecode.CompileFromFile("Shaders/shader.hlsl", "PShader", "ps_4_0",ShaderFlags.None,EffectFlags.None);
}
catch (System.Exception ex)
{
throw ex;
}
vertexShader = new VertexShader(Device, vertexShaderByteCode);
pixelShader = new PixelShader(Device, pixelShaderByteCode);
DeviceContext.VertexShader.Set(vertexShader);
DeviceContext.PixelShader.Set(pixelShader);
var signature = ShaderSignature.GetInputSignature(vertexShaderByteCode);
//Define first 16 floats as Position, next 16 as Color, next 12 normal (4 cords, 4 Color, 3 normal parts)
InputElement[] elements = new InputElement[]
{
new InputElement("POSITION", 0, SlimDX.DXGI.Format.R32G32B32A32_Float, 0, 0),
new InputElement("COLOR" , 0, SlimDX.DXGI.Format.R32G32B32A32_Float, 16, 0),
new InputElement("NORMAL" , 0, SlimDX.DXGI.Format.R32G32B32_Float, 32, 0),
};
//Define Layout for the InputAssembler
DeviceContext.InputAssembler.InputLayout = new InputLayout(Device, signature, elements);
//Generate and link constant buffers
constantBuffer = new Buffer(Device, System.Runtime.InteropServices.Marshal.SizeOf(new Matrix()), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
DeviceContext.VertexShader.SetConstantBuffer(constantBuffer,0);
//load STL and generate Vertices from it
ModuleWorks.Meshf meshf = ModuleWorks.MeshHelper.ReadSTLf(#"C:\ModuleWorks\STL\Homer.stl", ModuleWorks.Unit.Metric);
try
{
vertCount = meshf.TriangleCount * 3;
var vertices_model = new DataStream(vertCount * System.Runtime.InteropServices.Marshal.SizeOf(typeof(Vertex)), true, true);
var stopWatch = new Stopwatch();
stopWatch.Start();
for (int x = 0; x < meshf.TriangleCount; x++)
{
var triangle = meshf.GetTriangle(x);
var normal = triangle.Normal;
vertices_model.Write(new Vertex(meshf.GetPoint(triangle.Idx1).X, meshf.GetPoint(triangle.Idx1).Y, meshf.GetPoint(triangle.Idx1).Z, 1.0f, 0.0f, 0.0f, 1.0f, normal.X, normal.Y, normal.Z));
vertices_model.Write(new Vertex(meshf.GetPoint(triangle.Idx2).X, meshf.GetPoint(triangle.Idx2).Y, meshf.GetPoint(triangle.Idx2).Z, 1.0f, 0.0f, 0.0f, 1.0f, normal.X, normal.Y, normal.Z));
vertices_model.Write(new Vertex(meshf.GetPoint(triangle.Idx3).X, meshf.GetPoint(triangle.Idx3).Y, meshf.GetPoint(triangle.Idx3).Z, 1.0f, 0.0f, 0.0f, 1.0f, normal.X, normal.Y, normal.Z));
}
vertices_model.Position = 0;
//Generate VertexBufferBinding
var sizeInBytes = vertCount * System.Runtime.InteropServices.Marshal.SizeOf(typeof(Vertex));
var stride = System.Runtime.InteropServices.Marshal.SizeOf(typeof(Vector4)) * 2 + System.Runtime.InteropServices.Marshal.SizeOf(typeof(Vector3));
var vertexBuffer_model = new Buffer(Device, vertices_model, sizeInBytes, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
vertexBufferBinding_model = new VertexBufferBinding(vertexBuffer_model, stride, 0);
vertices_model.Close();
}
catch (System.Exception ex)
{
Console.WriteLine(ex);
return;
}
}
public override void Dispose()
{
vertexShader.Dispose();
pixelShader.Dispose();
constantBuffer.Dispose();
base.Dispose();
}
}
}
shader.hlsl
cbuffer matrixBuffer : register(b0)
{
float4x4 worldViewProj;
};
struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
float3 normal : NORMAL;
};
VOut VShader(float4 position : POSITION, float4 color : COLOR, float3 normal : NORMAL)
{
VOut output = (VOut)0;
output.position = mul(worldViewProj, position);
output.normal = normalize(mul((float3x3)worldViewProj,normal));
output.color = color;
return output;
}
float4 PShader(VOut vout) : SV_TARGET
{
return vout.color;
}
Thanks in advance
I solved it.
The issue was based on an inperformant approach to adding the vertices.
For further information, checkout this nice paper I've found

Categories

Resources