Im getting an Access Violation when ever I run this code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
using System.IO;
namespace OpenTKTutorial1
{
class Game : GameWindow
{
int pgmID;
int vsID;
int fsID;
int attribute_vcol;
int attribute_vpos;
int uniform_mview;
int vbo_position;
int vbo_color;
int vbo_mview;
Vector3[] vertdata;
Vector3[] coldata;
Matrix4[] mviewdata;
void initProgram()
{
pgmID = GL.CreateProgram();
loadShader("vs.glsl", ShaderType.VertexShader, pgmID, out vsID);
loadShader("fs.glsl", ShaderType.FragmentShader, pgmID, out fsID);
GL.LinkProgram(pgmID);
Console.WriteLine(GL.GetProgramInfoLog(pgmID));
attribute_vpos = GL.GetAttribLocation(pgmID, "vPosition");
attribute_vcol = GL.GetAttribLocation(pgmID, "vColor");
uniform_mview = GL.GetUniformLocation(pgmID, "modelview");
if (attribute_vpos == -1 || attribute_vcol == -1 || uniform_mview == -1)
{
Console.WriteLine("Error binding attirbutes");
}
GL.GenBuffers(1, out vbo_position);
GL.GenBuffers(1, out vbo_color);
GL.GenBuffers(1, out vbo_mview);
}
void loadShader(String filename, ShaderType type, int program, out int address)
{
address = GL.CreateShader(type);
using (StreamReader sr = new StreamReader(filename))
{
GL.ShaderSource(address, sr.ReadToEnd());
}
GL.CompileShader(address);
GL.AttachShader(program, address);
Console.WriteLine(GL.GetShaderInfoLog(address));
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
initProgram();
vertdata = new Vector3[]{
new Vector3(-0.8f, -0.8f, 0f),
new Vector3(0.8f, -0.8f, 0f),
new Vector3(0f, 0.8f, 0f)};
coldata = new Vector3[]{
new Vector3(1f, 0f, 0f),
new Vector3(0f, 0f, 1f),
new Vector3(0f, 1f, 0f)};
mviewdata = new Matrix4[]{
Matrix4.Identity};
Title = "Title";
GL.ClearColor(Color.CornflowerBlue);
GL.PointSize(5f);
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Viewport(0, 0, Width, Height);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Enable(EnableCap.DepthTest);
GL.EnableVertexAttribArray(attribute_vpos);
GL.EnableVertexAttribArray(attribute_vcol);
GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
GL.DisableVertexAttribArray(attribute_vpos);
GL.DisableVertexAttribArray(attribute_vcol);
GL.Flush();
//Everything before this
SwapBuffers();
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, (IntPtr)(vertdata.Length * Vector3.SizeInBytes), vertdata, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(attribute_vpos, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_color);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, (IntPtr)(coldata.Length * Vector3.SizeInBytes), coldata, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(attribute_vcol, 3, VertexAttribPointerType.Float, true, 0, 0);
GL.UniformMatrix4(uniform_mview, false, ref mviewdata[0]);
GL.UseProgram(pgmID);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
}
}
}
It makes it to rendering the background then crashes.
I'm quite new to OpenTK and OpenGL so I'm not 100% sure what the problem is.
The error is thrown at
GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
There are a few minor issues with your code, but it works for me without changes.
Regardless, I have made a few changes and added commentary to explain why, maybe something fixes it for you. If not please post your shaders and more detail on the exact exception, if there is any.
using System;
using System.Drawing;
using System.IO;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace OpenTKTutorial1
{
public class Game
: GameWindow
{
int pgmID;
int vsID;
int fsID;
int attribute_vcol;
int attribute_vpos;
int uniform_mview;
int vbo_position;
int vbo_color;
int vbo_mview;
Vector3[] vertdata;
Vector3[] coldata;
Matrix4[] mviewdata;
public Game()
{
// better use the events instead of overriding the inherited methods
// at least thats what the documentation on Update- and RenderFrame says
Load += OnLoad;
UpdateFrame += OnUpdateFrame;
RenderFrame += OnRenderFrame;
}
void InitProgram()
{
pgmID = GL.CreateProgram();
LoadShader("vs.glsl", ShaderType.VertexShader, pgmID, out vsID);
LoadShader("fs.glsl", ShaderType.FragmentShader, pgmID, out fsID);
GL.LinkProgram(pgmID);
Console.WriteLine(GL.GetProgramInfoLog(pgmID));
attribute_vpos = GL.GetAttribLocation(pgmID, "vPosition");
attribute_vcol = GL.GetAttribLocation(pgmID, "vColor");
uniform_mview = GL.GetUniformLocation(pgmID, "modelview");
if (attribute_vpos == -1 || attribute_vcol == -1 || uniform_mview == -1)
{
Console.WriteLine("Error binding attributes");
}
GL.GenBuffers(1, out vbo_position);
GL.GenBuffers(1, out vbo_color);
// what is this buffer for?
//GL.GenBuffers(1, out vbo_mview);
}
void LoadShader(String filename, ShaderType type, int program, out int address)
{
address = GL.CreateShader(type);
using (StreamReader sr = new StreamReader(filename))
{
GL.ShaderSource(address, sr.ReadToEnd());
}
GL.CompileShader(address);
GL.AttachShader(program, address);
Console.WriteLine(GL.GetShaderInfoLog(address));
}
protected void OnLoad(object sender, EventArgs eventArgs)
{
InitProgram();
vertdata = new Vector3[]{
new Vector3(-0.8f, -0.8f, 0f),
new Vector3(0.8f, -0.8f, 0f),
new Vector3(0f, 0.8f, 0f)};
coldata = new Vector3[]{
new Vector3(1f, 0f, 0f),
new Vector3(0f, 0f, 1f),
new Vector3(0f, 1f, 0f)};
mviewdata = new Matrix4[]{
Matrix4.Identity};
Title = "Title";
GL.ClearColor(Color.CornflowerBlue);
GL.PointSize(5f);
}
protected void OnRenderFrame(object sender, FrameEventArgs frameEventArgs)
{
// if you only have one viewport you can safely move this to the OnResize event
GL.Viewport(0, 0, Width, Height);
// if the state never changes move it to OnLoad
GL.Enable(EnableCap.DepthTest);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.EnableVertexAttribArray(attribute_vpos);
GL.EnableVertexAttribArray(attribute_vcol);
// always make sure the program is enabled ..
GL.UseProgram(pgmID);
// .. before you set any uniforms
GL.UniformMatrix4(uniform_mview, false, ref mviewdata[0]);
// .. or draw anything
GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
GL.DisableVertexAttribArray(attribute_vpos);
GL.DisableVertexAttribArray(attribute_vcol);
// do not call glFlush unless you have a very good reason to
// it can result in significant slow downs
//GL.Flush();
SwapBuffers();
}
protected void OnUpdateFrame(object sender, FrameEventArgs frameEventArgs)
{
// your vertex and color data never changes, thus everything you do here
// could be moved to OnLoad instead of having it repeated all the time
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertdata.Length * Vector3.SizeInBytes), vertdata, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(attribute_vpos, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_color);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(coldata.Length * Vector3.SizeInBytes), coldata, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(attribute_vcol, 3, VertexAttribPointerType.Float, true, 0, 0);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
}
}
}
Related
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
I looked at the code in How to draw line in OpenGl? but glBegin and glEnd are marked as deprecated. How are you supposed to draw a line in the current OpenGL version? I found articles that talk about using VBO, and articles that talk about glVertexPointer and glColorPointer, but there's so much framework around building these methods with the shader program compiling and linking and the vertex attribute bit twiddling. Isn't there a simple way to draw a line without using deprecated functions?
I tried this without success:
OpenTK.Vector2[] linepts = { new Vector2(0, 0), new Vector2(1, 1), new Vector2(50, 0), new Vector2(0, 50) };
int h = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, h);
GL.BufferData<Vector2>(BufferTarget.ArrayBuffer, 16, linepts, BufferUsageHint.StreamDraw);
GL.DrawArrays(PrimitiveType.LineStrip, 0, 4);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.DeleteBuffer(h);
I don't know if I'm even in the right ballpark using DrawArrays or if that method requires a whole mess of framework to go along with it, so I don't necessarily want to make this code work. I just want to find the simplest code for drawing a line that's advisable to use in modern OpenGL.
This is the simplest program (using OpenTK) that I can create to draw a line.
using System;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace OpenGLLine
{
static class Program
{
static OpenTK.GameWindow gw;
static int shaderProgram;
static int vertexInfo;
static int lineVertexBuffer;
static int vertexCount;
[STAThread]
static void Main()
{
gw = new OpenTK.GameWindow(800, 600, OpenTK.Graphics.GraphicsMode.Default, "Game", OpenTK.GameWindowFlags.FixedWindow);
Initialize();
gw.RenderFrame += Gw_RenderFrame;
gw.Closed += Gw_Closed;
gw.Run(60);
}
private static void Gw_Closed(object sender, EventArgs e)
{
CleanUp();
}
private static void Initialize()
{
int vshader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vshader, #"#version 130
in vec2 vPosition;
void main()
{
gl_Position = vec4(vPosition, -1.0, 1.0);
}");
GL.CompileShader(vshader);
int fshader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fshader, #"#version 130
out vec4 fragColor;
void main()
{
fragColor = vec4(1.0, 1.0, 1.0, 1.0);
}");
GL.CompileShader(fshader);
shaderProgram = GL.CreateProgram();
GL.AttachShader(shaderProgram, vshader);
GL.AttachShader(shaderProgram, fshader);
GL.LinkProgram(shaderProgram);
GL.DetachShader(shaderProgram, vshader);
GL.DetachShader(shaderProgram, fshader);
GL.UseProgram(shaderProgram);
lineVertexBuffer = GL.GenBuffer();
Vector2[] lineVertices = { new Vector2(0, 0), new Vector2(.5f, .5f) };
vertexCount = lineVertices.Length;
GL.BindBuffer(BufferTarget.ArrayBuffer, lineVertexBuffer);
GL.BufferData(BufferTarget.ArrayBuffer, System.Runtime.InteropServices.Marshal.SizeOf(lineVertices[0]) * vertexCount,
lineVertices, BufferUsageHint.StreamDraw);
vertexInfo = GL.GenVertexArray();
GL.BindVertexArray(vertexInfo);
int locVPosition = GL.GetAttribLocation(shaderProgram, "vPosition");
GL.EnableVertexAttribArray(locVPosition);
GL.VertexAttribPointer(locVPosition, 2, VertexAttribPointerType.Float, false,
System.Runtime.InteropServices.Marshal.SizeOf(lineVertices[0]), 0);
GL.BindVertexArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.UseProgram(0);
}
static void CleanUp()
{
GL.DeleteProgram(shaderProgram);
GL.DeleteVertexArray(vertexInfo);
GL.DeleteBuffer(lineVertexBuffer);
}
private static void Gw_RenderFrame(object sender, OpenTK.FrameEventArgs e)
{
GL.ClearColor(Color4.Black);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.BindBuffer(BufferTarget.ArrayBuffer, lineVertexBuffer);
GL.UseProgram(shaderProgram);
GL.BindVertexArray(vertexInfo);
GL.DrawArrays(PrimitiveType.LineStrip, 0, vertexCount);
GL.BindVertexArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.UseProgram(0);
gw.SwapBuffers();
}
}
}
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
We are trying to make an app using Xamarin which will have a small animated face in a GLKView on a particular screen. We have looked for solutions for rendering sprites, and the best solution we came up with stems from this solution here. We are having trouble even drawing a simple image in the GLKView, and the error in the output does not really make sense. We are converting this from iOS to Xamarin C# so there are differences between certain calls, but we have tried to keep most pieces in tact.
Here are the parts of the code this is related to:
public class Sprite : NSObject
{
public void Render()
{
Effect.Texture2d0.GLName = TextureInfo.Name;
Effect.Texture2d0.Enabled = true;
Effect.PrepareToDraw();
GL.EnableVertexAttribArray((int)GLKVertexAttrib.Position);
GL.EnableVertexAttribArray((int)GLKVertexAttrib.TexCoord0);
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(Quad));
Marshal.StructureToPtr(Quad, ptr, false);
int offset = (int)ptr;
GL.VertexAttribPointer((uint)GLKVertexAttrib.Position, 2, VertexAttribPointerType.Float, false, Marshal.SizeOf(typeof(TexturedVertex)), offset + (int)Marshal.OffsetOf(typeof(TexturedVertex), "geomertryVertex"));
GL.VertexAttribPointer((uint)GLKVertexAttrib.Position, 2, VertexAttribPointerType.Float, false, Marshal.SizeOf(typeof(TexturedVertex)), offset + (int)Marshal.OffsetOf(typeof(TexturedVertex), "textureVertex"));
GL.DrawArrays(BeginMode.TriangleStrip, 0, 4);
Marshal.FreeHGlobal(ptr);
}
}
Sprite.Render() is called in this GLKViewController here:
public class AnimationViewController : GLKViewController
{
GLKView animationView;
EAGLContext context;
Sprite player;
GLKBaseEffect effect;
public override void ViewDidLoad()
{
base.ViewDidLoad();
context = new EAGLContext(EAGLRenderingAPI.OpenGLES2);
if (context == null)
Console.WriteLine("Failed to create ES context...");
animationView = new GLKView(new RectangleF(UIScreen.MainScreen.Bounds.Width * 0.05f,
UIScreen.MainScreen.Bounds.Height * 0.05f,
UIScreen.MainScreen.Bounds.Width * 0.9f,
UIScreen.MainScreen.Bounds.Height * 0.75f), context);
EAGLContext.SetCurrentContext(context);
animationView.DrawInRect += new EventHandler<GLKViewDrawEventArgs>(animationView_DrawInRect);
View.AddSubview(animationView);
effect = new GLKBaseEffect();
Matrix4 projectionMatrix = Matrix4.CreateOrthographicOffCenter(0, animationView.Frame.Width, 0, animationView.Frame.Height, -1024, 1024);
effect.Transform.ProjectionMatrix = projectionMatrix;
player = new Sprite(#"Player.png", effect);
}
void animationView_DrawInRect(object sender, GLKViewDrawEventArgs e)
{
GL.ClearColor(0.98f, 0.98f, 0.98f, 1.0f);
//GL.Clear((uint)(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit));
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.Enable(EnableCap.Blend);
player.Render();
}
}
Links to whole code files:
Sprite Class and related Structs
AnimationViewController Class
Looks like the problem is just a typo in the second call to VertexAttribPointer. The second GLKVertexAttrib.Position should instead be GLKVertexAttrib.TexCoord0:
GL.VertexAttribPointer((uint)GLKVertexAttrib.Position, 2, VertexAttribPointerType.Float, false, Marshal.SizeOf(typeof(TexturedVertex)), offset + (int)Marshal.OffsetOf(typeof(TexturedVertex), "geomertryVertex"));
GL.VertexAttribPointer((uint)GLKVertexAttrib.TexCoord0, 2, VertexAttribPointerType.Float, false, Marshal.SizeOf(typeof(TexturedVertex)), offset + (int)Marshal.OffsetOf(typeof(TexturedVertex), "textureVertex"));
How can I play a movie and add a text overlay with DirectX in C#, please specify some references, because I am new in this area.
the specific part of DirectX tused for video playback is called DirectShow, you need a reference on how to use DirectShow from c#, a staring point could be this one:
http://www.codeproject.com/KB/directx/directshowmediaplayer.aspx
see http://www.riemers.net/eng/Tutorials/DirectX/Csharp/Series2/tut18.php for some source code on displaying text on a DirectX surface...
Here is a form that initializes a Direct3D, creates a couple of triangle vertices, and displays the video on them. Because I have no understanding of vertices it isn't quite lined up correctly, but it successfully loads the video and renders it as a texture onto the triangles.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Microsoft.DirectX.Direct3D.Device _device;
private Microsoft.DirectX.Direct3D.Font font;
private Microsoft.DirectX.AudioVideoPlayback.Video _video;
CustomVertex.PositionTextured[] vertices;
public void Init()
{
PresentParameters present_params = new PresentParameters();
present_params.Windowed = true;
present_params.SwapEffect = SwapEffect.Discard;
_device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, present_params);
font = new Microsoft.DirectX.Direct3D.Font(_device, 20, 0, FontWeight.Bold, 0, false, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.DefaultPitch, "Arial");
_video = new Video("clock.avi");
_video.TextureReadyToRender += new TextureRenderEventHandler(_video_TextureReadyToRender);
_video.RenderToTexture(_device);
vertices = new CustomVertex.PositionTextured[6];
vertices[0].Position = new Vector3(1f, 1f, 0f);
vertices[0].Tu = 0;
vertices[0].Tv = 1;
vertices[1].Position = new Vector3(-1f, -1f, 0f);
vertices[1].Tu = 1;
vertices[1].Tv = 1;
vertices[2].Position = new Vector3(1f, -1f, 0f);
vertices[2].Tu = 0;
vertices[2].Tv = 0;
vertices[3].Position = new Vector3(-1.1f, -0.99f, 0f);
vertices[3].Tu = 1;
vertices[3].Tv = 0;
vertices[4].Position = new Vector3(0.99f, 1.1f, 0f);
vertices[4].Tu = 0;
vertices[4].Tv = 0;
vertices[5].Position = new Vector3(-1.1f, 1.1f, 0f);
vertices[5].Tu = 1;
vertices[5].Tv = 1;
}
void _video_TextureReadyToRender(object sender, TextureRenderEventArgs e)
{
_device.BeginScene();
_device.SetTexture(0, e.Texture);
_device.VertexFormat = CustomVertex.PositionTextured.Format;
_device.DrawUserPrimitives(PrimitiveType.TriangleList, 2, vertices);
font.DrawText(null, "test overlay", 5, 5, Color.Red);
_device.EndScene();
_device.Present();
}
protected override void OnPaint(PaintEventArgs e)
{
_device.Clear(ClearFlags.Target, Color.Blue, 0.0F, 0);
}
private void Form1_Load(object sender, EventArgs e)
{
_video.Play();
}
}
You need to put your scene drawing code within the TextureReadyToRender event, otherwise your video will never show up.