using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SharpDX;
using SharpDX.DXGI;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.Direct2D1;
using SharpDX.Windows;
using Device = SharpDX.Direct3D11.Device;
using FactoryD2D = SharpDX.Direct2D1.Factory;
using FactoryDXGI = SharpDX.DXGI.Factory1;
namespace Direct2DTest
{
public partial class Form1 : Form
{
int testcounter = 0;
int testbcounter = 0;
int c,d;
int[,] cloudcoord = new int [11,2];
RenderTarget renderTarget;
Random rnd;
public Form1()
{
InitializeComponent();
//Enable Timer
timer1.Interval = 20; //50 FPS
timer1.Enabled = false;
rnd = new Random();
}
public void IdentityMatrix(ref SharpDX.Mathematics.Interop.RawMatrix3x2 b)
{
var a = new SharpDX.Mathematics.Interop.RawMatrix3x2();
a.M11 = 1; a.M12 = 0; a.M21 = 0; a.M22 = 1; a.M31 = 0; a.M32 = 0;
b = a;
}
public static SharpDX.Direct2D1.Bitmap LoadFromFileTransparent(RenderTarget renderTarget, string file, System.Drawing.Color cmatch)
{
// Loads from file using System.Drawing.Image
using (var bitmap = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(file))
{
var sourceArea = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height);
var bitmapProperties = new SharpDX.Direct2D1.BitmapProperties(new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.R8G8B8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied));
var size = new Size2(bitmap.Width, bitmap.Height);
// Transform pixels from BGRA to RGBA
int stride = bitmap.Width * sizeof(int);
using (var tempStream = new DataStream(bitmap.Height * stride, true, true))
{
// Lock System.Drawing.Bitmap
var bitmapData = bitmap.LockBits(sourceArea, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
// Convert all pixels
for (int y = 0; y < bitmap.Height; y++)
{
int offset = bitmapData.Stride * y;
for (int x = 0; x < bitmap.Width; x++)
{
// Not optimized
byte B = Marshal.ReadByte(bitmapData.Scan0, offset++);
byte G = Marshal.ReadByte(bitmapData.Scan0, offset++);
byte R = Marshal.ReadByte(bitmapData.Scan0, offset++);
byte A = Marshal.ReadByte(bitmapData.Scan0, offset++);
if ((cmatch.R == R) && (cmatch.B == B) && (cmatch.G == G))
{
//Matched our color, make transparent.
R = 0; G = 0; B = 0; A = 0;
}
int rgba = R | (G << 8) | (B << 16) | (A << 24);
tempStream.Write(rgba);
}
}
bitmap.UnlockBits(bitmapData);
tempStream.Position = 0;
return new SharpDX.Direct2D1.Bitmap(renderTarget, size, tempStream, stride, bitmapProperties);
}
}
}
private void button1_Click(object sender, EventArgs e)
{ //click
//Blank out the clouds
for (testcounter = 0; testcounter <= 10; testcounter++)
{
cloudcoord[testcounter, 0] = 0; cloudcoord[testcounter, 1] = 0;
}
// Create render target window
var form = new RenderForm("Direct2D Demo");
// Create swap chain description
var swapChainDesc = new SwapChainDescription()
{
BufferCount = 2,
Usage = Usage.RenderTargetOutput,
OutputHandle = form.Handle,
IsWindowed = true,
ModeDescription = new ModeDescription(260, 260, new Rational(60, 1), Format.R8G8B8A8_UNorm),
SampleDescription = new SampleDescription(1, 0),
Flags = SwapChainFlags.AllowModeSwitch, //SwapChainFlags.FrameLatencyWaitAbleObject,
SwapEffect = SwapEffect.Discard
};
// Create swap chain and Direct3D device
// The BgraSupport flag is needed for Direct2D compatibility otherwise RenderTarget.FromDXGI will fail!
Device device;
SwapChain swapChain;
Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.BgraSupport, swapChainDesc, out device, out swapChain);
// Get back buffer in a Direct2D-compatible format (DXGI surface)
Surface backBuffer = Surface.FromSwapChain(swapChain, 0);
// Create Direct2D factory
using (var factory = new FactoryD2D())
{
// Get desktop DPI
var dpi = factory.DesktopDpi;
// Create bitmap render target from DXGI surface
renderTarget = new RenderTarget(factory, backBuffer, new RenderTargetProperties()
{ //RenderTarget
DpiX = dpi.Width,
DpiY = dpi.Height,
MinLevel = SharpDX.Direct2D1.FeatureLevel.Level_DEFAULT,
PixelFormat = new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.R8G8B8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied),
Type = RenderTargetType.Default,
Usage = RenderTargetUsage.None}); //RenderTarget
} //using factory
renderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive; /* Not that this appears to effect anything. */
// Disable automatic ALT+Enter processing because it doesn't work properly with WinForms
using (var factory = swapChain.GetParent())
{
factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAltEnter);
}
// Add event handler for ALT+Enter
form.KeyDown += (o, f) =>
{
if (f.Alt && f.KeyCode == Keys.Enter)
swapChain.IsFullScreen = !swapChain.IsFullScreen;
};
// Set window size
form.Size = new System.Drawing.Size(260,260);
// Prevent window from being re-sized
form.AutoSizeMode = AutoSizeMode.GrowAndShrink;
//Load our Bitmaps
SharpDX.WIC.ImagingFactory imagingFactory = new SharpDX.WIC.ImagingFactory();
SharpDX.IO.NativeFileStream fileStream = new SharpDX.IO.NativeFileStream("background.png",
SharpDX.IO.NativeFileMode.Open, SharpDX.IO.NativeFileAccess.Read);
SharpDX.WIC.BitmapDecoder BMDecode = new SharpDX.WIC.BitmapDecoder(imagingFactory, fileStream, SharpDX.WIC.DecodeOptions.CacheOnDemand);
SharpDX.WIC.BitmapFrameDecode frame = BMDecode.GetFrame(0);
SharpDX.WIC.FormatConverter converter = new SharpDX.WIC.FormatConverter(imagingFactory);
converter.Initialize(frame, SharpDX.WIC.PixelFormat.Format32bppPRGBA);
SharpDX.Direct2D1.Bitmap backBitmap = SharpDX.Direct2D1.Bitmap1.FromWicBitmap(renderTarget, converter);
fileStream.Dispose(); imagingFactory.Dispose(); BMDecode.Dispose(); frame.Dispose(); converter.Dispose();
SharpDX.Direct2D1.Bitmap cloudBitmap = LoadFromFileTransparent(renderTarget, "cloud.png",Color.Magenta);
c = (int)renderTarget.Size.Height - 50;
d = (int)renderTarget.Size.Width;
timer1.Enabled = true; //Now, we can turn on the timer.
// Rendering function
RenderLoop.Run(form, () =>
{
int a;
var junkmatrix = new SharpDX.Mathematics.Interop.RawMatrix3x2();
IdentityMatrix(ref junkmatrix);
renderTarget.BeginDraw();
renderTarget.Transform = junkmatrix; //Matrix3x2.Identity;
renderTarget.Clear(new SharpDX.Mathematics.Interop.RawColor4(128,128,128,255));
renderTarget.DrawBitmap(
backBitmap,
new SharpDX.Mathematics.Interop.RawRectangleF(0,0,renderTarget.Size.Width,renderTarget.Size.Height),
1.0f,
SharpDX.Direct2D1.BitmapInterpolationMode.Linear,
new SharpDX.Mathematics.Interop.RawRectangleF(0, 0, 259,259)
);
// put drawing code here (see below)
/* Old demo code.
var v1 = new SharpDX.Mathematics.Interop.RawVector2();
var v2 = new SharpDX.Mathematics.Interop.RawVector2();
using (var brush = new SolidColorBrush(renderTarget, new SharpDX.Mathematics.Interop.RawColor4(100, 120, 140, 255)))
{
for (int x = 0; x < renderTarget.Size.Width; x += 10)
{
v1.X = x; v1.Y = 0;
v2.X = x; v2.Y = renderTarget.Size.Height;
renderTarget.DrawLine(v1, v2, brush, 0.5f);
}
for (int y = 0; y < renderTarget.Size.Height; y += 10)
{
v1.X = 0; v1.Y = y;
v2.X = renderTarget.Size.Width; v2.Y = y;
renderTarget.DrawLine(v1, v2, brush, 0.5f);
}
renderTarget.FillRectangle(new SharpDX.Mathematics.Interop.RawRectangleF(50,150, 100, 200), brush);
var MyText = new SharpDX.DirectWrite.Factory();
var MyTextFormat = new SharpDX.DirectWrite.TextFormat(MyText,"Arial",22);
renderTarget.DrawText("This is a test" + testcounter.ToString(), MyTextFormat, new SharpDX.Mathematics.Interop.RawRectangleF(150, 150, 350, 200), brush, 0, 0);
} //using brush */
for (a = 0; a <= 10; a++)
{ // cloud loop
if (cloudcoord[a,0] > 0)
{
renderTarget.DrawBitmap(
cloudBitmap,
new SharpDX.Mathematics.Interop.RawRectangleF(cloudcoord[a,0],cloudcoord[a,1],cloudcoord[a,0] +38,cloudcoord[a,1]+28),
0.5f,
SharpDX.Direct2D1.BitmapInterpolationMode.Linear,
new SharpDX.Mathematics.Interop.RawRectangleF(0, 0, 38,28)
);
}
}
/*
renderTarget.DrawRectangle(
new SharpDX.Mathematics.Interop.RawRectangleF(0,0, 200, 200),
new SolidColorBrush(renderTarget, new SharpDX.Mathematics.Interop.RawColor4(100, 160, 140, 0))); */
renderTarget.EndDraw();
swapChain.Present(0, PresentFlags.None);
});
//clean up
renderTarget.Dispose();
swapChain.Dispose();
device.Dispose();
}
private void button2_Click(object sender, EventArgs e)
{
//testcounter = testcounter + 1;
label1.Text = c.ToString() + "," + d.ToString(); // testbcounter.ToString();
}
private void timer1_Tick(object sender, EventArgs e)
{
int a, b;
if (testbcounter > 300) { testbcounter = 0; } else { testbcounter++; }
/* Manipulate clouds here */
for (a = 0; a <= 10; a++)
{
if (cloudcoord[a, 0] > d)
{ //Off the edge
cloudcoord[a, 0] = 0;
}
else
{
if (cloudcoord[a, 0] != 0)
{ //exists, just move it along
cloudcoord[a, 0]++;
}
else
{
//It does = 0
b = rnd.Next(1, 500);
if (b == 25)
{ //spawn a new cloud
cloudcoord[a, 1] = rnd.Next(1, c);
cloudcoord[a, 0] = 1;
}
}
} //else
} //for
} //click
} //Form 1
} //Direct2DTest