attempt opentk4
This commit is contained in:
parent
0b409d641a
commit
f7b22649c6
19 changed files with 1831 additions and 389 deletions
14
GLWidget.sln
14
GLWidget.sln
|
@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.29709.97
|
||||||
MinimumVisualStudioVersion = 15.0.26124.0
|
MinimumVisualStudioVersion = 15.0.26124.0
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GLWidget", "GLWidget\GLWidget.csproj", "{2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GLWidget", "GLWidget\GLWidget.csproj", "{2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GLWidgetTestGTK3", "GLWidgetTestGTK3\GLWidgetTestGTK3.csproj", "{227DE1F9-A40A-440A-9A06-4AA5532DBA17}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -27,6 +29,18 @@ Global
|
||||||
{2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|x64.Build.0 = Release|Any CPU
|
{2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|x86.ActiveCfg = Release|Any CPU
|
{2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|x86.Build.0 = Release|Any CPU
|
{2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Release|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Release|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Release|x64.Build.0 = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Release|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{227DE1F9-A40A-440A-9A06-4AA5532DBA17}.Release|x86.Build.0 = Debug|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -35,9 +35,11 @@ using System.ComponentModel;
|
||||||
|
|
||||||
|
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using OpenTK.Platform;
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
|
||||||
|
|
||||||
using Gtk;
|
using Gtk;
|
||||||
|
using Cairo;
|
||||||
|
|
||||||
namespace OpenTK
|
namespace OpenTK
|
||||||
{
|
{
|
||||||
|
@ -56,78 +58,41 @@ namespace OpenTK
|
||||||
|
|
||||||
#region Attributes
|
#region Attributes
|
||||||
|
|
||||||
private IGraphicsContext _graphicsContext;
|
|
||||||
private IWindowInfo _windowInfo;
|
|
||||||
private bool _initialized;
|
private bool _initialized;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
/// <summary>Use a single buffer versus a double buffer.</summary>
|
|
||||||
[Browsable(true)]
|
|
||||||
public bool SingleBuffer { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Color Buffer Bits-Per-Pixel</summary>
|
|
||||||
public int ColorBPP { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Accumulation Buffer Bits-Per-Pixel</summary>
|
|
||||||
public int AccumulatorBPP { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Depth Buffer Bits-Per-Pixel</summary>
|
|
||||||
public int DepthBPP { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Stencil Buffer Bits-Per-Pixel</summary>
|
|
||||||
public int StencilBPP { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Number of samples</summary>
|
|
||||||
public int Samples { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Indicates if steropic renderering is enabled</summary>
|
|
||||||
public bool Stereo { get; set; }
|
|
||||||
|
|
||||||
/// <summary>The major version of OpenGL to use.</summary>
|
/// <summary>The major version of OpenGL to use.</summary>
|
||||||
public int GLVersionMajor { get; set; }
|
public int GLVersionMajor { get; set; }
|
||||||
|
|
||||||
/// <summary>The minor version of OpenGL to use.</summary>
|
/// <summary>The minor version of OpenGL to use.</summary>
|
||||||
public int GLVersionMinor { get; set; }
|
public int GLVersionMinor { get; set; }
|
||||||
|
|
||||||
public GraphicsContextFlags GraphicsContextFlags
|
private int _framebuffer;
|
||||||
{
|
private int _renderbuffer;
|
||||||
get;
|
private int _stencilbuffer;
|
||||||
set;
|
|
||||||
}
|
public Gdk.GLContext GraphicsContext { get; set; }
|
||||||
|
public bool ForwardCompatible { get; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Construction/Destruction
|
#region Construction/Destruction
|
||||||
|
|
||||||
/// <summary>Constructs a new GLWidget.</summary>
|
/// <summary>Constructs a new GLWidget</summary>
|
||||||
public GLWidget()
|
public GLWidget() : this(new Version(4, 0), true)
|
||||||
: this(GraphicsMode.Default)
|
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Constructs a new GLWidget using a given GraphicsMode</summary>
|
|
||||||
public GLWidget(GraphicsMode graphicsMode)
|
|
||||||
: this(graphicsMode, 1, 0, GraphicsContextFlags.Default)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Constructs a new GLWidget</summary>
|
/// <summary>Constructs a new GLWidget</summary>
|
||||||
public GLWidget(GraphicsMode graphicsMode, int glVersionMajor, int glVersionMinor, GraphicsContextFlags graphicsContextFlags)
|
public GLWidget(Version apiVersion, bool forwardCompatible)
|
||||||
{
|
{
|
||||||
SingleBuffer = graphicsMode.Buffers == 1;
|
GLVersionMajor = apiVersion.Major;
|
||||||
ColorBPP = graphicsMode.ColorFormat.BitsPerPixel;
|
GLVersionMinor = apiVersion.Minor;
|
||||||
AccumulatorBPP = graphicsMode.AccumulatorFormat.BitsPerPixel;
|
ForwardCompatible = forwardCompatible;
|
||||||
DepthBPP = graphicsMode.Depth;
|
|
||||||
StencilBPP = graphicsMode.Stencil;
|
|
||||||
Samples = graphicsMode.Samples;
|
|
||||||
Stereo = graphicsMode.Stereo;
|
|
||||||
|
|
||||||
GLVersionMajor = glVersionMajor;
|
|
||||||
GLVersionMinor = glVersionMinor;
|
|
||||||
GraphicsContextFlags = graphicsContextFlags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~GLWidget()
|
~GLWidget()
|
||||||
|
@ -139,22 +104,8 @@ namespace OpenTK
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
try
|
|
||||||
{
|
|
||||||
GraphicsContext.MakeCurrent(WindowInfo);
|
|
||||||
}catch(Exception ex)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
OnShuttingDown();
|
OnShuttingDown();
|
||||||
|
|
||||||
if (OpenTK.Graphics.GraphicsContext.ShareContexts && (Interlocked.Decrement(ref _graphicsContextCount) == 0))
|
|
||||||
{
|
|
||||||
OnGraphicsContextShuttingDown();
|
|
||||||
_sharedContextInitialized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsContext.Dispose();
|
GraphicsContext.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,10 +152,7 @@ namespace OpenTK
|
||||||
|
|
||||||
protected virtual void OnRenderFrame()
|
protected virtual void OnRenderFrame()
|
||||||
{
|
{
|
||||||
if (RenderFrame != null)
|
RenderFrame?.Invoke(this, EventArgs.Empty);
|
||||||
{
|
|
||||||
RenderFrame(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when this GLWidget is being Disposed
|
// Called when this GLWidget is being Disposed
|
||||||
|
@ -220,334 +168,113 @@ namespace OpenTK
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
// Called when a widget is realized. (window handles and such are valid)
|
|
||||||
// protected override void OnRealized() { base.OnRealized(); }
|
|
||||||
|
|
||||||
// Called when the widget needs to be (fully or partially) redrawn.
|
// Called when the widget needs to be (fully or partially) redrawn.
|
||||||
|
|
||||||
protected override bool OnDrawn(Cairo.Context cr)
|
protected override bool OnDrawn(Cairo.Context cr)
|
||||||
{
|
{
|
||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
Initialize();
|
Initialize();
|
||||||
else if(!IsRenderHandler)
|
else if (!IsRenderHandler)
|
||||||
GraphicsContext.MakeCurrent(WindowInfo);
|
{
|
||||||
|
MakeCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
cr.SetSourceColor(new Color(0, 0, 0, 1));
|
||||||
|
cr.Paint();
|
||||||
|
|
||||||
|
var scale = this.ScaleFactor;
|
||||||
|
|
||||||
|
Gdk.CairoHelper.DrawFromGl(cr, this.Window, _renderbuffer, (int)ObjectLabelIdentifier.Renderbuffer, scale, 0, 0, AllocatedWidth, AllocatedHeight);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Swapbuffers()
|
||||||
|
{
|
||||||
|
GL.Flush();
|
||||||
|
|
||||||
|
QueueDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MakeCurrent()
|
||||||
|
{
|
||||||
|
GraphicsContext?.MakeCurrent();
|
||||||
|
GL.BindFramebuffer(FramebufferTarget.Framebuffer, _framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearCurrent()
|
||||||
|
{
|
||||||
|
Gdk.GLContext.ClearCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
// Called on Resize
|
// Called on Resize
|
||||||
protected override bool OnConfigureEvent(Gdk.EventConfigure evnt)
|
protected override bool OnConfigureEvent(Gdk.EventConfigure evnt)
|
||||||
{
|
{
|
||||||
if (GraphicsContext != null)
|
if (GraphicsContext != null)
|
||||||
{
|
{
|
||||||
GraphicsContext.Update(WindowInfo);
|
MakeCurrent();
|
||||||
|
|
||||||
|
GraphicsContext.Window.Resize(evnt.X, evnt.Y);
|
||||||
|
|
||||||
|
DeleteBuffers();
|
||||||
|
|
||||||
|
CreateFramebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DeleteBuffers()
|
||||||
|
{
|
||||||
|
if (_framebuffer != 0)
|
||||||
|
{
|
||||||
|
GL.DeleteFramebuffer(_framebuffer);
|
||||||
|
GL.DeleteRenderbuffer(_renderbuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateFramebuffer()
|
||||||
|
{
|
||||||
|
_framebuffer = GL.GenFramebuffer();
|
||||||
|
GL.BindFramebuffer(FramebufferTarget.Framebuffer, _framebuffer);
|
||||||
|
|
||||||
|
_renderbuffer = GL.GenRenderbuffer();
|
||||||
|
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, _renderbuffer);
|
||||||
|
GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.Rgba8, AllocatedWidth, AllocatedHeight);
|
||||||
|
|
||||||
|
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, RenderbufferTarget.Renderbuffer, _renderbuffer);
|
||||||
|
|
||||||
|
_stencilbuffer = GL.GenRenderbuffer();
|
||||||
|
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, _stencilbuffer);
|
||||||
|
GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.Depth24Stencil8, AllocatedWidth, AllocatedHeight);
|
||||||
|
|
||||||
|
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, RenderbufferTarget.Renderbuffer, _stencilbuffer);
|
||||||
|
|
||||||
|
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0);
|
||||||
|
var state = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
|
||||||
// If this looks uninitialized... initialize.
|
|
||||||
if (ColorBPP == 0)
|
|
||||||
{
|
|
||||||
ColorBPP = 32;
|
|
||||||
|
|
||||||
if (DepthBPP == 0)
|
|
||||||
{
|
|
||||||
DepthBPP = 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorFormat colorBufferColorFormat = new ColorFormat(ColorBPP);
|
|
||||||
|
|
||||||
ColorFormat accumulationColorFormat = new ColorFormat(AccumulatorBPP);
|
|
||||||
|
|
||||||
int buffers = 2;
|
|
||||||
if (SingleBuffer)
|
|
||||||
{
|
|
||||||
buffers--;
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsMode graphicsMode = new GraphicsMode(colorBufferColorFormat, DepthBPP, StencilBPP, Samples, accumulationColorFormat, buffers, Stereo);
|
|
||||||
|
|
||||||
this.Window.EnsureNative();
|
this.Window.EnsureNative();
|
||||||
|
|
||||||
// IWindowInfo
|
GraphicsContext = Window.CreateGlContext();
|
||||||
if (OpenTK.Configuration.RunningOnWindows)
|
|
||||||
{
|
|
||||||
WindowInfo = InitializeWindows();
|
|
||||||
}
|
|
||||||
else if (OpenTK.Configuration.RunningOnMacOS)
|
|
||||||
{
|
|
||||||
WindowInfo = InitializeOSX();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WindowInfo = InitializeX(graphicsMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GraphicsContext
|
GraphicsContext.SetRequiredVersion(GLVersionMajor, GLVersionMinor);
|
||||||
GraphicsContext = new GraphicsContext(graphicsMode, WindowInfo, GLVersionMajor, GLVersionMinor, GraphicsContextFlags);
|
|
||||||
GraphicsContext.MakeCurrent(WindowInfo);
|
|
||||||
|
|
||||||
if (OpenTK.Graphics.GraphicsContext.ShareContexts)
|
GraphicsContext.SetUseEs(0);
|
||||||
{
|
|
||||||
Interlocked.Increment(ref _graphicsContextCount);
|
|
||||||
|
|
||||||
if (!_sharedContextInitialized)
|
GraphicsContext.ForwardCompatible = ForwardCompatible;
|
||||||
{
|
|
||||||
_sharedContextInitialized = true;
|
GraphicsContext.Realize();
|
||||||
((IGraphicsContextInternal)GraphicsContext).LoadAll();
|
|
||||||
OnGraphicsContextInitialized();
|
GraphicsContext.MakeCurrent();
|
||||||
}
|
|
||||||
}
|
CreateFramebuffer();
|
||||||
else
|
|
||||||
{
|
|
||||||
((IGraphicsContextInternal)GraphicsContext).LoadAll();
|
|
||||||
OnGraphicsContextInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
OnInitialized();
|
OnInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Windows Specific initalization
|
|
||||||
|
|
||||||
IWindowInfo InitializeWindows()
|
|
||||||
{
|
|
||||||
IntPtr windowHandle = gdk_win32_window_get_handle(this.Window.Handle);
|
|
||||||
return Utilities.CreateWindowsWindowInfo(windowHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
[SuppressUnmanagedCodeSecurity, DllImport("libgdk-3-0.dll")]
|
|
||||||
public static extern IntPtr gdk_win32_window_get_handle(IntPtr d);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region OSX Specific Initialization
|
|
||||||
|
|
||||||
IWindowInfo InitializeOSX()
|
|
||||||
{
|
|
||||||
IntPtr windowHandle = gdk_quartz_window_get_nswindow(this.Window.Handle);
|
|
||||||
//IntPtr viewHandle = gdk_quartz_window_get_nsview(this.GdkWindow.Handle);
|
|
||||||
return Utilities.CreateMacOSWindowInfo(windowHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
[SuppressUnmanagedCodeSecurity, DllImport("libgdk-3.0.dylib")]
|
|
||||||
static extern IntPtr gdk_quartz_window_get_nswindow(IntPtr handle);
|
|
||||||
|
|
||||||
[SuppressUnmanagedCodeSecurity, DllImport("libgdk-3.0.dylib")]
|
|
||||||
static extern IntPtr gdk_quartz_window_get_nsview(IntPtr handle);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region X Specific Initialization
|
|
||||||
|
|
||||||
const string UnixLibGdkName = "libgdk-3.so.0";
|
|
||||||
|
|
||||||
const string UnixLibX11Name = "libX11.so.6";
|
|
||||||
const string UnixLibGLName = "libGL.so.1";
|
|
||||||
|
|
||||||
const int GLX_NONE = 0;
|
|
||||||
const int GLX_USE_GL = 1;
|
|
||||||
const int GLX_BUFFER_SIZE = 2;
|
|
||||||
const int GLX_LEVEL = 3;
|
|
||||||
const int GLX_RGBA = 4;
|
|
||||||
const int GLX_DOUBLEBUFFER = 5;
|
|
||||||
const int GLX_STEREO = 6;
|
|
||||||
const int GLX_AUX_BUFFERS = 7;
|
|
||||||
const int GLX_RED_SIZE = 8;
|
|
||||||
const int GLX_GREEN_SIZE = 9;
|
|
||||||
const int GLX_BLUE_SIZE = 10;
|
|
||||||
const int GLX_ALPHA_SIZE = 11;
|
|
||||||
const int GLX_DEPTH_SIZE = 12;
|
|
||||||
const int GLX_STENCIL_SIZE = 13;
|
|
||||||
const int GLX_ACCUM_RED_SIZE = 14;
|
|
||||||
const int GLX_ACCUM_GREEN_SIZE = 15;
|
|
||||||
const int GLX_ACCUM_BLUE_SIZE = 16;
|
|
||||||
const int GLX_ACCUM_ALPHA_SIZE = 17;
|
|
||||||
|
|
||||||
public enum XVisualClass
|
|
||||||
{
|
|
||||||
StaticGray = 0,
|
|
||||||
GrayScale = 1,
|
|
||||||
StaticColor = 2,
|
|
||||||
PseudoColor = 3,
|
|
||||||
TrueColor = 4,
|
|
||||||
DirectColor = 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
struct XVisualInfo
|
|
||||||
{
|
|
||||||
public IntPtr Visual;
|
|
||||||
public IntPtr VisualID;
|
|
||||||
public int Screen;
|
|
||||||
public int Depth;
|
|
||||||
public XVisualClass Class;
|
|
||||||
public long RedMask;
|
|
||||||
public long GreenMask;
|
|
||||||
public long blueMask;
|
|
||||||
public int ColormapSize;
|
|
||||||
public int BitsPerRgb;
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"id ({VisualID}), screen ({Screen}), depth ({Depth}), class ({Class})";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
internal enum XVisualInfoMask
|
|
||||||
{
|
|
||||||
No = 0x0,
|
|
||||||
ID = 0x1,
|
|
||||||
Screen = 0x2,
|
|
||||||
Depth = 0x4,
|
|
||||||
Class = 0x8,
|
|
||||||
Red = 0x10,
|
|
||||||
Green = 0x20,
|
|
||||||
Blue = 0x40,
|
|
||||||
ColormapSize = 0x80,
|
|
||||||
BitsPerRGB = 0x100,
|
|
||||||
All = 0x1FF,
|
|
||||||
}
|
|
||||||
|
|
||||||
private IWindowInfo InitializeX(GraphicsMode mode)
|
|
||||||
{
|
|
||||||
IntPtr display = gdk_x11_display_get_xdisplay(Display.Handle);
|
|
||||||
int screen = Screen.Number;
|
|
||||||
|
|
||||||
IntPtr windowHandle = gdk_x11_window_get_xid(Window.Handle);
|
|
||||||
IntPtr rootWindow = gdk_x11_window_get_xid(RootWindow.Handle);
|
|
||||||
|
|
||||||
IntPtr visualInfo;
|
|
||||||
|
|
||||||
if (mode.Index.HasValue)
|
|
||||||
{
|
|
||||||
XVisualInfo info = new XVisualInfo();
|
|
||||||
info.VisualID = mode.Index.Value;
|
|
||||||
int dummy;
|
|
||||||
visualInfo = XGetVisualInfo(display, XVisualInfoMask.ID, ref info, out dummy);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
visualInfo = GetVisualInfo(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
IWindowInfo retval = Utilities.CreateX11WindowInfo(display, screen, windowHandle, rootWindow, visualInfo);
|
|
||||||
XFree(visualInfo);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IntPtr XGetVisualInfo(IntPtr display, XVisualInfoMask vinfo_mask, ref XVisualInfo template, out int nitems)
|
|
||||||
{
|
|
||||||
return XGetVisualInfoInternal(display, (IntPtr)(int)vinfo_mask, ref template, out nitems);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IntPtr GetVisualInfo(IntPtr display)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int[] attributes = AttributeList.ToArray();
|
|
||||||
return glXChooseVisual(display, Screen.Number, attributes);
|
|
||||||
}
|
|
||||||
catch (DllNotFoundException e)
|
|
||||||
{
|
|
||||||
throw new DllNotFoundException("OpenGL dll not found!", e);
|
|
||||||
}
|
|
||||||
catch (EntryPointNotFoundException enf)
|
|
||||||
{
|
|
||||||
throw new EntryPointNotFoundException("Glx entry point not found!", enf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<int> AttributeList
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
List<int> attributeList = new List<int>(24);
|
|
||||||
|
|
||||||
attributeList.Add(GLX_RGBA);
|
|
||||||
|
|
||||||
if (!SingleBuffer)
|
|
||||||
attributeList.Add(GLX_DOUBLEBUFFER);
|
|
||||||
|
|
||||||
if (Stereo)
|
|
||||||
attributeList.Add(GLX_STEREO);
|
|
||||||
|
|
||||||
attributeList.Add(GLX_RED_SIZE);
|
|
||||||
attributeList.Add(ColorBPP / 4); // TODO support 16-bit
|
|
||||||
|
|
||||||
attributeList.Add(GLX_GREEN_SIZE);
|
|
||||||
attributeList.Add(ColorBPP / 4); // TODO support 16-bit
|
|
||||||
|
|
||||||
attributeList.Add(GLX_BLUE_SIZE);
|
|
||||||
attributeList.Add(ColorBPP / 4); // TODO support 16-bit
|
|
||||||
|
|
||||||
attributeList.Add(GLX_ALPHA_SIZE);
|
|
||||||
attributeList.Add(ColorBPP / 4); // TODO support 16-bit
|
|
||||||
|
|
||||||
attributeList.Add(GLX_DEPTH_SIZE);
|
|
||||||
attributeList.Add(DepthBPP);
|
|
||||||
|
|
||||||
attributeList.Add(GLX_STENCIL_SIZE);
|
|
||||||
attributeList.Add(StencilBPP);
|
|
||||||
|
|
||||||
attributeList.Add(GLX_ACCUM_RED_SIZE);
|
|
||||||
attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
|
|
||||||
|
|
||||||
attributeList.Add(GLX_ACCUM_GREEN_SIZE);
|
|
||||||
attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
|
|
||||||
|
|
||||||
attributeList.Add(GLX_ACCUM_BLUE_SIZE);
|
|
||||||
attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
|
|
||||||
|
|
||||||
attributeList.Add(GLX_ACCUM_ALPHA_SIZE);
|
|
||||||
attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
|
|
||||||
|
|
||||||
attributeList.Add(GLX_NONE);
|
|
||||||
|
|
||||||
return attributeList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IGraphicsContext GraphicsContext { get => _graphicsContext; set => _graphicsContext = value; }
|
|
||||||
public IWindowInfo WindowInfo { get => _windowInfo; set => _windowInfo = value; }
|
|
||||||
|
|
||||||
[DllImport(UnixLibX11Name, EntryPoint = "XGetVisualInfo")]
|
|
||||||
private static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, out int nitems);
|
|
||||||
|
|
||||||
[SuppressUnmanagedCodeSecurity, DllImport(UnixLibX11Name)]
|
|
||||||
private static extern void XFree(IntPtr handle);
|
|
||||||
|
|
||||||
/// <summary> Returns the X resource (window or pixmap) belonging to a GdkDrawable. </summary>
|
|
||||||
/// <remarks> XID gdk_x11_drawable_get_xid(GdkDrawable *drawable); </remarks>
|
|
||||||
/// <param name="gdkDisplay"> The GdkDrawable. </param>
|
|
||||||
/// <returns> The ID of drawable's X resource. </returns>
|
|
||||||
[SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)]
|
|
||||||
private static extern IntPtr gdk_x11_drawable_get_xid(IntPtr gdkDisplay);
|
|
||||||
|
|
||||||
/// <summary> Returns the X resource (window or pixmap) belonging to a GdkDrawable. </summary>
|
|
||||||
/// <remarks> XID gdk_x11_drawable_get_xid(GdkDrawable *drawable); </remarks>
|
|
||||||
/// <param name="gdkDisplay"> The GdkDrawable. </param>
|
|
||||||
/// <returns> The ID of drawable's X resource. </returns>
|
|
||||||
[SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)]
|
|
||||||
private static extern IntPtr gdk_x11_window_get_xid(IntPtr gdkDisplay);
|
|
||||||
|
|
||||||
/// <summary> Returns the X display of a GdkDisplay. </summary>
|
|
||||||
/// <remarks> Display* gdk_x11_display_get_xdisplay(GdkDisplay *display); </remarks>
|
|
||||||
/// <param name="gdkDisplay"> The GdkDrawable. </param>
|
|
||||||
/// <returns> The X Display of the GdkDisplay. </returns>
|
|
||||||
[SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)]
|
|
||||||
private static extern IntPtr gdk_x11_display_get_xdisplay(IntPtr gdkDisplay);
|
|
||||||
|
|
||||||
[SuppressUnmanagedCodeSecurity, DllImport(UnixLibGLName)]
|
|
||||||
private static extern IntPtr glXChooseVisual(IntPtr display, int screen, int[] attr);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
@ -7,10 +6,9 @@
|
||||||
<Version>1.0.1</Version>
|
<Version>1.0.1</Version>
|
||||||
<RepositoryUrl>https://github.com/Ryujinx/GLWidget</RepositoryUrl>
|
<RepositoryUrl>https://github.com/Ryujinx/GLWidget</RepositoryUrl>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="GtkSharp" Version="3.22.25.56" />
|
<PackageReference Include="GtkSharp" Version="3.22.25.56" />
|
||||||
<PackageReference Include="OpenTK.NetStandard" Version="1.0.5.12" />
|
<PackageReference Include="OpenTK.Graphics" Version="4.0.0-pre9.4" />
|
||||||
|
<PackageReference Include="OpenTK.Windowing.Common" Version="4.0.0-pre9.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
49
GLWidgetTestGTK3/Data/RGB.cs
Normal file
49
GLWidgetTestGTK3/Data/RGB.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// Vertex.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Jarl Gullberg <jarl.gullberg@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Jarl Gullberg
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3.Data
|
||||||
|
{
|
||||||
|
public class RGB
|
||||||
|
{
|
||||||
|
public float R
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float G
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float B
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RGB(float R, float G, float B)
|
||||||
|
{
|
||||||
|
this.R = R;
|
||||||
|
this.G = G;
|
||||||
|
this.B = B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
GLWidgetTestGTK3/Data/Transform.cs
Normal file
61
GLWidgetTestGTK3/Data/Transform.cs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
//
|
||||||
|
// Transform.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Jarl Gullberg <jarl.gullberg@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Jarl Gullberg
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//using System.Net;
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3.Data
|
||||||
|
{
|
||||||
|
public class Transform
|
||||||
|
{
|
||||||
|
public Vector3 Translation
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion Rotation
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 Scale
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transform(Vector3 Translation)
|
||||||
|
: this(Translation, Quaternion.FromAxisAngle(Vector3.UnitX, 0.0f), Vector3.One)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transform(Vector3 Translation, Quaternion Rotation, Vector3 Scale)
|
||||||
|
{
|
||||||
|
this.Translation = Translation;
|
||||||
|
this.Rotation = Rotation;
|
||||||
|
this.Scale = Scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
GLWidgetTestGTK3/Data/UVCoordinate.cs
Normal file
47
GLWidgetTestGTK3/Data/UVCoordinate.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// UVCoordinate.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Jarl Gullberg <jarl.gullberg@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Jarl Gullberg
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3.Data
|
||||||
|
{
|
||||||
|
public sealed class UVCoordinate
|
||||||
|
{
|
||||||
|
public float U
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float V
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UVCoordinate(float U, float V)
|
||||||
|
{
|
||||||
|
this.U = U;
|
||||||
|
this.V = V;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
92
GLWidgetTestGTK3/Data/Vertex.cs
Normal file
92
GLWidgetTestGTK3/Data/Vertex.cs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
//
|
||||||
|
// Vertex.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Jarl Gullberg <jarl.gullberg@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Jarl Gullberg
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3.Data
|
||||||
|
{
|
||||||
|
public sealed class Vertex
|
||||||
|
{
|
||||||
|
public Vector3 Position
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 Normal
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UVCoordinate UVCoordinate
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RGB VertexColour
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vertex(Vector3 Position)
|
||||||
|
:this(Position, Vector3.Zero, new UVCoordinate(0.0f, 0.0f), new RGB(1.0f, 1.0f, 1.0f))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vertex(Vector3 Position, Vector3 Normal)
|
||||||
|
:this(Position, Normal, new UVCoordinate(0.0f, 0.0f), new RGB(1.0f, 1.0f, 1.0f))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Vertex(Vector3 Position, RGB VertexColour)
|
||||||
|
:this(Position, Vector3.Zero, new UVCoordinate(0.0f, 0.0f), VertexColour)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vertex(Vector3 Position, Vector3 Normal, RGB VertexColour)
|
||||||
|
:this(Position, Normal, new UVCoordinate(0.0f, 0.0f), VertexColour)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vertex(Vector3 Position, UVCoordinate UVCoordinate)
|
||||||
|
:this(Position, Vector3.Zero, UVCoordinate, new RGB(1.0f, 1.0f, 1.0f))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vertex(Vector3 Position, Vector3 Normal, UVCoordinate UVCoordinate)
|
||||||
|
:this(Position, Normal, UVCoordinate, new RGB(1.0f, 1.0f, 1.0f))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vertex(Vector3 Position, Vector3 Normal, UVCoordinate UVCoordinate, RGB VertexColour)
|
||||||
|
{
|
||||||
|
this.Position = Position;
|
||||||
|
this.Normal = Normal;
|
||||||
|
this.UVCoordinate = UVCoordinate;
|
||||||
|
this.VertexColour = VertexColour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
GLWidgetTestGTK3/Extensions/ExtensionMethods.cs
Normal file
41
GLWidgetTestGTK3/Extensions/ExtensionMethods.cs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// ExtensionMethods.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Jarl Gullberg <jarl.gullberg@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Jarl Gullberg
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3.Extensions
|
||||||
|
{
|
||||||
|
public static class ExtensionMethods
|
||||||
|
{
|
||||||
|
public static Quaternion QuaternionFromEuler(float Yaw, float Pitch, float Roll)
|
||||||
|
{
|
||||||
|
Quaternion XRotation = Quaternion.FromAxisAngle(Vector3.UnitX, Yaw);
|
||||||
|
Quaternion YRotation = Quaternion.FromAxisAngle(Vector3.UnitY, Pitch);
|
||||||
|
Quaternion ZRotation = Quaternion.FromAxisAngle(Vector3.UnitZ, Roll);
|
||||||
|
|
||||||
|
Quaternion final = Quaternion.Multiply(ZRotation, YRotation);
|
||||||
|
final = Quaternion.Multiply(XRotation, final);
|
||||||
|
|
||||||
|
return final;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
GLWidgetTestGTK3/GLWidgetTestGTK3.csproj
Normal file
39
GLWidgetTestGTK3/GLWidgetTestGTK3.csproj
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<LangVersion>8.0</LangVersion>
|
||||||
|
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<Configurations>Debug;Release</Configurations>
|
||||||
|
<RootNamespace>GLWidgetTestGTK3</RootNamespace>
|
||||||
|
<StartupObject>GLWidgetTestGTK3.MainClass</StartupObject>
|
||||||
|
<AssemblyName>GLWidgetTestGTK3</AssemblyName>
|
||||||
|
<ReleaseVersion>1.1</ReleaseVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="GtkSharp" Version="3.22.25.56"/>
|
||||||
|
<PackageReference Include="OpenTK" Version="4.0.0-pre9.4"/>
|
||||||
|
<PackageReference Include="OpenGL.Net" Version="1.0.304"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="interfaces\MainWindow.glade"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Shaders\FragmentShader.glsl"/>
|
||||||
|
<EmbeddedResource Include="Shaders\VertexShader.glsl"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\GLWidget\GLWidget.csproj"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<MonoDevelop>
|
||||||
|
<Properties>
|
||||||
|
<GtkDesignInfo generateGettext="False"/>
|
||||||
|
</Properties>
|
||||||
|
</MonoDevelop>
|
||||||
|
</ProjectExtensions>
|
||||||
|
</Project>
|
140
GLWidgetTestGTK3/GTKBindingContext.cs
Normal file
140
GLWidgetTestGTK3/GTKBindingContext.cs
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
using System;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenGL;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Khronos;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3
|
||||||
|
{
|
||||||
|
public class GTKBindingContext : IBindingsContext
|
||||||
|
{
|
||||||
|
private static bool _loaded;
|
||||||
|
|
||||||
|
private const string GlxLibrary = "libGL.so.1";
|
||||||
|
private const string WglLibrary = "opengl32.dll";
|
||||||
|
private const string OSXLibrary = "libdl.dylib";
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Currently loaded libraries.
|
||||||
|
/// </summary>
|
||||||
|
private static readonly Dictionary<string, IntPtr> _LibraryHandles = new Dictionary<string, IntPtr>();
|
||||||
|
|
||||||
|
public IntPtr GetProcAddress(string procName)
|
||||||
|
{
|
||||||
|
switch (Platform.CurrentPlatformId)
|
||||||
|
{
|
||||||
|
case Platform.Id.WindowsNT:
|
||||||
|
return GetProcAddressWgl(procName);
|
||||||
|
case Platform.Id.Linux:
|
||||||
|
return GetProcAddressGlx(procName);
|
||||||
|
case Platform.Id.MacOS:
|
||||||
|
return !Glx.IsRequired ? GetProcAddressOSX(procName) : GetProcAddressGlx(procName);
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IntPtr GetProcAddressWgl(string function)
|
||||||
|
{
|
||||||
|
return UnsafeNativeMethods.wglGetProcAddress(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void LoadLibraries()
|
||||||
|
{
|
||||||
|
if (_loaded)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string function = "glXGetProcAddress";
|
||||||
|
|
||||||
|
IntPtr handle = GetLibraryHandle(GlxLibrary, true);
|
||||||
|
|
||||||
|
if (handle == IntPtr.Zero)
|
||||||
|
throw new ArgumentNullException(nameof(handle));
|
||||||
|
|
||||||
|
IntPtr functionPtr = UnsafeNativeMethods.dlsym(handle, function);
|
||||||
|
|
||||||
|
if (functionPtr != IntPtr.Zero)
|
||||||
|
Delegates.pglXGetProcAddress = (Delegates.glXGetProcAddress)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(Delegates.glXGetProcAddress));
|
||||||
|
|
||||||
|
_loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IntPtr GetLibraryHandle(string libraryPath, bool throws)
|
||||||
|
{
|
||||||
|
IntPtr libraryHandle;
|
||||||
|
|
||||||
|
if (_LibraryHandles.TryGetValue(libraryPath, out libraryHandle) == false)
|
||||||
|
{
|
||||||
|
if ((libraryHandle = UnsafeNativeMethods.dlopen(libraryPath, UnsafeNativeMethods.RTLD_LAZY)) == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
if (throws)
|
||||||
|
throw new InvalidOperationException($"unable to load library at {libraryPath}", new InvalidOperationException(UnsafeNativeMethods.dlerror()));
|
||||||
|
}
|
||||||
|
|
||||||
|
_LibraryHandles.Add(libraryPath, libraryHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return libraryHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IntPtr GetProcAddressGlx(string function)
|
||||||
|
{
|
||||||
|
LoadLibraries();
|
||||||
|
|
||||||
|
return Delegates.pglXGetProcAddress != null ? Delegates.pglXGetProcAddress(function) : IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IntPtr GetProcAddressOSX(string function)
|
||||||
|
{
|
||||||
|
string fname = "_" + function;
|
||||||
|
if (!UnsafeNativeMethods.NSIsSymbolNameDefined(fname))
|
||||||
|
return IntPtr.Zero;
|
||||||
|
|
||||||
|
IntPtr symbol = UnsafeNativeMethods.NSLookupAndBindSymbol(fname);
|
||||||
|
|
||||||
|
if (symbol != IntPtr.Zero)
|
||||||
|
symbol = UnsafeNativeMethods.NSAddressOfSymbol(symbol);
|
||||||
|
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class UnsafeNativeMethods
|
||||||
|
{
|
||||||
|
[DllImport(WglLibrary, EntryPoint = "wglGetProcAddress", ExactSpelling = true, SetLastError = true)]
|
||||||
|
public static extern IntPtr wglGetProcAddress(string lpszProc);
|
||||||
|
|
||||||
|
[DllImport(OSXLibrary, EntryPoint = "NSIsSymbolNameDefined")]
|
||||||
|
public static extern bool NSIsSymbolNameDefined(string s);
|
||||||
|
|
||||||
|
[DllImport(OSXLibrary, EntryPoint = "NSLookupAndBindSymbol")]
|
||||||
|
public static extern IntPtr NSLookupAndBindSymbol(string s);
|
||||||
|
|
||||||
|
[DllImport(OSXLibrary, EntryPoint = "NSAddressOfSymbol")]
|
||||||
|
public static extern IntPtr NSAddressOfSymbol(IntPtr symbol);
|
||||||
|
|
||||||
|
public const int RTLD_LAZY = 1;
|
||||||
|
|
||||||
|
public const int RTLD_NOW = 2;
|
||||||
|
|
||||||
|
[DllImport("dl")]
|
||||||
|
public static extern IntPtr dlopen(string filename, int flags);
|
||||||
|
|
||||||
|
[DllImport("dl")]
|
||||||
|
public static extern IntPtr dlsym(IntPtr handle, string symbol);
|
||||||
|
|
||||||
|
[DllImport("dl")]
|
||||||
|
public static extern string dlerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Delegates
|
||||||
|
{
|
||||||
|
public delegate IntPtr glXGetProcAddress(string procName);
|
||||||
|
|
||||||
|
public static glXGetProcAddress pglXGetProcAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
76
GLWidgetTestGTK3/Geometry/Shapes.cs
Normal file
76
GLWidgetTestGTK3/Geometry/Shapes.cs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
//
|
||||||
|
// Mesh.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Jarl Gullberg <jarl.gullberg@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Jarl Gullberg
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3.Debug
|
||||||
|
{
|
||||||
|
public static class Shapes
|
||||||
|
{
|
||||||
|
public static readonly float[] UnindexedTriangle =
|
||||||
|
{
|
||||||
|
-1.0f, -1.0f, 0.0f,
|
||||||
|
1.0f, -1.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly float[] UnindexedCube =
|
||||||
|
{
|
||||||
|
-1.0f,-1.0f,-1.0f,
|
||||||
|
-1.0f,-1.0f, 1.0f,
|
||||||
|
-1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f,-1.0f,
|
||||||
|
-1.0f,-1.0f,-1.0f,
|
||||||
|
-1.0f, 1.0f,-1.0f,
|
||||||
|
1.0f,-1.0f, 1.0f,
|
||||||
|
-1.0f,-1.0f,-1.0f,
|
||||||
|
1.0f,-1.0f,-1.0f,
|
||||||
|
1.0f, 1.0f,-1.0f,
|
||||||
|
1.0f,-1.0f,-1.0f,
|
||||||
|
-1.0f,-1.0f,-1.0f,
|
||||||
|
-1.0f,-1.0f,-1.0f,
|
||||||
|
-1.0f, 1.0f, 1.0f,
|
||||||
|
-1.0f, 1.0f,-1.0f,
|
||||||
|
1.0f,-1.0f, 1.0f,
|
||||||
|
-1.0f,-1.0f, 1.0f,
|
||||||
|
-1.0f,-1.0f,-1.0f,
|
||||||
|
-1.0f, 1.0f, 1.0f,
|
||||||
|
-1.0f,-1.0f, 1.0f,
|
||||||
|
1.0f,-1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f,-1.0f,-1.0f,
|
||||||
|
1.0f, 1.0f,-1.0f,
|
||||||
|
1.0f,-1.0f,-1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f,-1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f,-1.0f,
|
||||||
|
-1.0f, 1.0f,-1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
-1.0f, 1.0f,-1.0f,
|
||||||
|
-1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
-1.0f, 1.0f, 1.0f,
|
||||||
|
1.0f,-1.0f, 1.0f
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
578
GLWidgetTestGTK3/MainWindow.cs
Normal file
578
GLWidgetTestGTK3/MainWindow.cs
Normal file
|
@ -0,0 +1,578 @@
|
||||||
|
//
|
||||||
|
// MainWindow.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Jarl Gullberg <jarl.gullberg@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Jarl Gullberg
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using Gdk;
|
||||||
|
using GLWidgetTestGTK3.Data;
|
||||||
|
using GLWidgetTestGTK3.Debug;
|
||||||
|
using GLWidgetTestGTK3.World;
|
||||||
|
using Gtk;
|
||||||
|
using UI = Gtk.Builder.ObjectAttribute;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
using KeyPressEventArgs = Gtk.KeyPressEventArgs;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3
|
||||||
|
{
|
||||||
|
public partial class MainWindow : Gtk.Window
|
||||||
|
{
|
||||||
|
[UI] readonly Box MainBox;
|
||||||
|
[UI] readonly MenuBar MainMenuBar;
|
||||||
|
|
||||||
|
[UI] readonly Alignment GLWidgetAlignment;
|
||||||
|
[UI] readonly GLWidget MainGLWidget;
|
||||||
|
|
||||||
|
private bool GLInit;
|
||||||
|
|
||||||
|
private Scene Scene;
|
||||||
|
|
||||||
|
private uint VertexArrayID;
|
||||||
|
private uint ColourBufferID;
|
||||||
|
|
||||||
|
private int ShaderProgramID;
|
||||||
|
|
||||||
|
/* Default camera positions */
|
||||||
|
private Vector3 cameraPosition;
|
||||||
|
private Vector3 cameraLookDirection;
|
||||||
|
private Vector3 cameraRightVector;
|
||||||
|
|
||||||
|
private Vector3 cameraUpVector;
|
||||||
|
private float horizontalViewAngle;
|
||||||
|
private float verticalViewAngle;
|
||||||
|
private const float defaultFOV = 45.0f;
|
||||||
|
|
||||||
|
private const float defaultMovementSpeed = 10.0f;
|
||||||
|
private const float defaultCameraSpeed = 0.5f;
|
||||||
|
|
||||||
|
// Other variables
|
||||||
|
private bool wantsToMove = false;
|
||||||
|
private float deltaTime;
|
||||||
|
|
||||||
|
private int mouseXLastFrame;
|
||||||
|
private int mouseYLastFrame;
|
||||||
|
|
||||||
|
private float rightAxis;
|
||||||
|
private float forwardAxis;
|
||||||
|
|
||||||
|
private static readonly float[] cubeColourBufferData =
|
||||||
|
{
|
||||||
|
0.583f, 0.771f, 0.014f,
|
||||||
|
0.609f, 0.115f, 0.436f,
|
||||||
|
0.327f, 0.483f, 0.844f,
|
||||||
|
0.822f, 0.569f, 0.201f,
|
||||||
|
0.435f, 0.602f, 0.223f,
|
||||||
|
0.310f, 0.747f, 0.185f,
|
||||||
|
0.597f, 0.770f, 0.761f,
|
||||||
|
0.559f, 0.436f, 0.730f,
|
||||||
|
0.359f, 0.583f, 0.152f,
|
||||||
|
0.483f, 0.596f, 0.789f,
|
||||||
|
0.559f, 0.861f, 0.639f,
|
||||||
|
0.195f, 0.548f, 0.859f,
|
||||||
|
0.014f, 0.184f, 0.576f,
|
||||||
|
0.771f, 0.328f, 0.970f,
|
||||||
|
0.406f, 0.615f, 0.116f,
|
||||||
|
0.676f, 0.977f, 0.133f,
|
||||||
|
0.971f, 0.572f, 0.833f,
|
||||||
|
0.140f, 0.616f, 0.489f,
|
||||||
|
0.997f, 0.513f, 0.064f,
|
||||||
|
0.945f, 0.719f, 0.592f,
|
||||||
|
0.543f, 0.021f, 0.978f,
|
||||||
|
0.279f, 0.317f, 0.505f,
|
||||||
|
0.167f, 0.620f, 0.077f,
|
||||||
|
0.347f, 0.857f, 0.137f,
|
||||||
|
0.055f, 0.953f, 0.042f,
|
||||||
|
0.714f, 0.505f, 0.345f,
|
||||||
|
0.783f, 0.290f, 0.734f,
|
||||||
|
0.722f, 0.645f, 0.174f,
|
||||||
|
0.302f, 0.455f, 0.848f,
|
||||||
|
0.225f, 0.587f, 0.040f,
|
||||||
|
0.517f, 0.713f, 0.338f,
|
||||||
|
0.053f, 0.959f, 0.120f,
|
||||||
|
0.393f, 0.621f, 0.362f,
|
||||||
|
0.673f, 0.211f, 0.457f,
|
||||||
|
0.820f, 0.883f, 0.371f,
|
||||||
|
0.982f, 0.099f, 0.879f
|
||||||
|
};
|
||||||
|
|
||||||
|
public static MainWindow Create()
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(null, "GLWidgetTestGTK3.interfaces.MainWindow.glade", null);
|
||||||
|
return new MainWindow(builder, builder.GetObject("MainWindow").Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MainWindow(Builder builder, IntPtr handle)
|
||||||
|
: base(handle)
|
||||||
|
{
|
||||||
|
builder.Autoconnect(this);
|
||||||
|
DeleteEvent += OnDeleteEvent;
|
||||||
|
|
||||||
|
this.GLInit = false;
|
||||||
|
ResetCamera();
|
||||||
|
|
||||||
|
this.MainGLWidget = new GLWidget()
|
||||||
|
{
|
||||||
|
GLVersionMajor = 3,
|
||||||
|
GLVersionMinor = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.MainGLWidget.Events |=
|
||||||
|
EventMask.ButtonPressMask |
|
||||||
|
EventMask.ButtonReleaseMask |
|
||||||
|
EventMask.KeyPressMask |
|
||||||
|
EventMask.KeyReleaseMask;
|
||||||
|
|
||||||
|
this.MainGLWidget.Initialized += OnViewportInitialized;
|
||||||
|
this.MainGLWidget.ButtonPressEvent += OnViewportButtonPressed;
|
||||||
|
this.MainGLWidget.ButtonReleaseEvent += OnViewportButtonReleased;
|
||||||
|
this.MainGLWidget.KeyPressEvent += OnViewportKeyPressed;
|
||||||
|
this.MainGLWidget.KeyReleaseEvent += OnViewportKeyReleased;
|
||||||
|
|
||||||
|
// Add the GL widget to the UI
|
||||||
|
this.GLWidgetAlignment.Add(this.MainGLWidget);
|
||||||
|
this.GLWidgetAlignment.ShowAll();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Vertex> FloatArrayToVertexList(float[] vertexPositions)
|
||||||
|
{
|
||||||
|
if ((vertexPositions.Length % 3) != 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The input array must be of a 3-multiple length. Incomplete entries are not allowed.", nameof(vertexPositions));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Vertex> convertedVertices = new List<Vertex>();
|
||||||
|
|
||||||
|
for (int i = 0; i < vertexPositions.Length; i += 3)
|
||||||
|
{
|
||||||
|
Vector3 Position = new Vector3(vertexPositions[i], vertexPositions[i + 1], vertexPositions[i + 2]);
|
||||||
|
Vertex vertex = new Vertex(Position);
|
||||||
|
|
||||||
|
convertedVertices.Add(vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return convertedVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnViewportKeyReleased(object o, KeyReleaseEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Event.Type == EventType.KeyRelease)
|
||||||
|
{
|
||||||
|
if( args.Event.Key == Gdk.Key.w || args.Event.Key == Gdk.Key.W)
|
||||||
|
{
|
||||||
|
forwardAxis = 0.0f;
|
||||||
|
}
|
||||||
|
else if( args.Event.Key == Gdk.Key.s || args.Event.Key == Gdk.Key.S)
|
||||||
|
{
|
||||||
|
forwardAxis = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( args.Event.Key == Gdk.Key.d || args.Event.Key == Gdk.Key.D)
|
||||||
|
{
|
||||||
|
rightAxis = 0.0f;
|
||||||
|
}
|
||||||
|
else if( args.Event.Key == Gdk.Key.a || args.Event.Key == Gdk.Key.A)
|
||||||
|
{
|
||||||
|
rightAxis = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnViewportKeyPressed(object o, KeyPressEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Event.Type == EventType.KeyPress)
|
||||||
|
{
|
||||||
|
if( args.Event.Key == Gdk.Key.w || args.Event.Key == Gdk.Key.W)
|
||||||
|
{
|
||||||
|
forwardAxis = 1.0f;
|
||||||
|
}
|
||||||
|
else if( args.Event.Key == Gdk.Key.s || args.Event.Key == Gdk.Key.S)
|
||||||
|
{
|
||||||
|
forwardAxis = -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( args.Event.Key == Gdk.Key.d || args.Event.Key == Gdk.Key.D)
|
||||||
|
{
|
||||||
|
rightAxis = 1.0f;
|
||||||
|
}
|
||||||
|
else if( args.Event.Key == Gdk.Key.a || args.Event.Key == Gdk.Key.A)
|
||||||
|
{
|
||||||
|
rightAxis = -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( args.Event.Key == Gdk.Key.r || args.Event.Key == Gdk.Key.R)
|
||||||
|
{
|
||||||
|
if (wantsToMove)
|
||||||
|
{
|
||||||
|
ResetCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.Event.Key == Gdk.Key.Escape)
|
||||||
|
{
|
||||||
|
Application.Quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetCamera()
|
||||||
|
{
|
||||||
|
this.cameraPosition = new Vector3(0.0f, 0.0f, 5.0f);
|
||||||
|
this.horizontalViewAngle = MathHelper.DegreesToRadians(180.0f);
|
||||||
|
this.verticalViewAngle = MathHelper.DegreesToRadians(0.0f);
|
||||||
|
|
||||||
|
this.cameraLookDirection = new Vector3(
|
||||||
|
(float)(Math.Cos(this.verticalViewAngle) * Math.Sin(this.horizontalViewAngle)),
|
||||||
|
(float)Math.Sin(this.verticalViewAngle),
|
||||||
|
(float)(Math.Cos(this.verticalViewAngle) * Math.Cos(this.horizontalViewAngle)));
|
||||||
|
|
||||||
|
this.cameraRightVector = new Vector3(
|
||||||
|
(float)Math.Sin(horizontalViewAngle - MathHelper.PiOver2),
|
||||||
|
0,
|
||||||
|
(float)Math.Cos(horizontalViewAngle - MathHelper.PiOver2));
|
||||||
|
|
||||||
|
this.cameraUpVector = Vector3.Cross(cameraRightVector, cameraLookDirection);
|
||||||
|
}
|
||||||
|
|
||||||
|
[GLib.ConnectBefore]
|
||||||
|
private void OnViewportButtonReleased(object o, ButtonReleaseEventArgs args)
|
||||||
|
{
|
||||||
|
// Right click is released
|
||||||
|
if (args.Event.Type == EventType.ButtonRelease && args.Event.Button == 3)
|
||||||
|
{
|
||||||
|
// Return the mouse pointer
|
||||||
|
this.Window.Cursor = new Cursor(CursorType.Arrow);
|
||||||
|
|
||||||
|
this.GrabFocus();
|
||||||
|
this.wantsToMove = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[GLib.ConnectBefore]
|
||||||
|
private void OnViewportButtonPressed(object o, ButtonPressEventArgs args)
|
||||||
|
{
|
||||||
|
// Right click is pressed
|
||||||
|
if (args.Event.Type == EventType.ButtonPress && args.Event.Button == 3)
|
||||||
|
{
|
||||||
|
// Hide the mouse pointer
|
||||||
|
this.Window.Cursor = new Cursor(CursorType.BlankCursor);
|
||||||
|
|
||||||
|
this.MainGLWidget.GrabFocus();
|
||||||
|
this.wantsToMove = true;
|
||||||
|
this.MainGLWidget.GetPointer(out this.mouseXLastFrame, out this.mouseYLastFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnViewportInitialized(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var version = GL.GetString(StringName.Version);
|
||||||
|
|
||||||
|
this.Scene = new Scene();
|
||||||
|
|
||||||
|
// Create the cube actor
|
||||||
|
Actor cubeActor = new Actor(new Mesh(FloatArrayToVertexList(Shapes.UnindexedCube)));
|
||||||
|
Actor cubeActor1 = new Actor(new Mesh(FloatArrayToVertexList(Shapes.UnindexedCube)));
|
||||||
|
Actor cubeActor2 = new Actor(new Mesh(FloatArrayToVertexList(Shapes.UnindexedCube)));
|
||||||
|
Actor cubeActor3 = new Actor(new Mesh(FloatArrayToVertexList(Shapes.UnindexedCube)));
|
||||||
|
|
||||||
|
// Translate the cube actor
|
||||||
|
cubeActor.Transform.Translation = new Vector3(4.0f, 0.0f, 0.0f);
|
||||||
|
cubeActor1.Transform.Translation = new Vector3(0.0f, 4.0f, 0.0f);
|
||||||
|
cubeActor2.Transform.Translation = new Vector3(0.0f, -4.0f, 0.0f);
|
||||||
|
cubeActor3.Transform.Translation = new Vector3(-4.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
Actor triangleActor = new Actor(new Mesh(FloatArrayToVertexList(Shapes.UnindexedTriangle)));
|
||||||
|
|
||||||
|
this.Scene.Actors.Add(cubeActor);
|
||||||
|
this.Scene.Actors.Add(cubeActor1);
|
||||||
|
this.Scene.Actors.Add(cubeActor2);
|
||||||
|
this.Scene.Actors.Add(cubeActor3);
|
||||||
|
this.Scene.Actors.Add(triangleActor);
|
||||||
|
|
||||||
|
// Generate the colour buffer
|
||||||
|
GL.GenBuffers(1, out ColourBufferID);
|
||||||
|
|
||||||
|
// Upload the colour data
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, ColourBufferID);
|
||||||
|
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(cubeColourBufferData.Length * sizeof(float)), cubeColourBufferData, BufferUsageHint.StaticDraw);
|
||||||
|
|
||||||
|
// Make sure we use the depth buffer when drawing
|
||||||
|
GL.Enable(EnableCap.DepthTest);
|
||||||
|
//GL.DepthFunc(DepthFunction.Less);
|
||||||
|
|
||||||
|
// Enable backface culling for performance reasons
|
||||||
|
//GL.Enable(EnableCap.CullFace);
|
||||||
|
|
||||||
|
// Render wireframe
|
||||||
|
//GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
|
||||||
|
|
||||||
|
// Initialize the viewport
|
||||||
|
int widgetWidth = this.GLWidgetAlignment.AllocatedWidth;
|
||||||
|
int widgetHeight = this.GLWidgetAlignment.AllocatedHeight;
|
||||||
|
|
||||||
|
GL.Viewport(0, 0, widgetWidth, widgetHeight);
|
||||||
|
GL.ClearColor(0.522f, 0.573f, 0.678f, 1.0f);
|
||||||
|
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||||
|
|
||||||
|
// Load the shaders
|
||||||
|
ShaderProgramID = LoadShaders();
|
||||||
|
|
||||||
|
// Add idle event handler to process rendering whenever and as long as time is available.
|
||||||
|
GLInit = true;
|
||||||
|
GLib.Idle.Add(OnIdleProcessMain);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void RenderFrame()
|
||||||
|
{
|
||||||
|
MainGLWidget.MakeCurrent();
|
||||||
|
|
||||||
|
// Make sure the viewport is accurate for the current widget size on screen
|
||||||
|
int widgetWidth = this.GLWidgetAlignment.AllocatedWidth;
|
||||||
|
int widgetHeight = this.GLWidgetAlignment.AllocatedHeight;
|
||||||
|
var error = GL.GetError();
|
||||||
|
GL.Viewport(0, 0, widgetWidth, widgetHeight);
|
||||||
|
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||||
|
|
||||||
|
// Activate the shaders
|
||||||
|
GL.UseProgram(ShaderProgramID);
|
||||||
|
|
||||||
|
// See if there's any movement to compute
|
||||||
|
if (wantsToMove)
|
||||||
|
{
|
||||||
|
int mouseX;
|
||||||
|
int mouseY;
|
||||||
|
this.MainGLWidget.GetPointer(out mouseX, out mouseY);
|
||||||
|
|
||||||
|
this.horizontalViewAngle += defaultCameraSpeed * this.deltaTime * (float)(mouseXLastFrame - mouseX);
|
||||||
|
this.verticalViewAngle += defaultCameraSpeed * this.deltaTime * (float)(mouseYLastFrame - mouseY);
|
||||||
|
|
||||||
|
if (verticalViewAngle > MathHelper.DegreesToRadians(90.0f))
|
||||||
|
{
|
||||||
|
verticalViewAngle = MathHelper.DegreesToRadians(90.0f);
|
||||||
|
}
|
||||||
|
else if (verticalViewAngle < MathHelper.DegreesToRadians(-90.0f))
|
||||||
|
{
|
||||||
|
verticalViewAngle = MathHelper.DegreesToRadians(-90.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseXLastFrame = mouseX;
|
||||||
|
mouseYLastFrame = mouseY;
|
||||||
|
|
||||||
|
// Compute the look direction
|
||||||
|
this.cameraLookDirection = new Vector3(
|
||||||
|
(float)(Math.Cos(this.verticalViewAngle) * Math.Sin(this.horizontalViewAngle)),
|
||||||
|
(float)Math.Sin(this.verticalViewAngle),
|
||||||
|
(float)(Math.Cos(this.verticalViewAngle) * Math.Cos(this.horizontalViewAngle)));
|
||||||
|
|
||||||
|
this.cameraRightVector = new Vector3(
|
||||||
|
(float)Math.Sin(this.horizontalViewAngle - MathHelper.PiOver2),
|
||||||
|
0,
|
||||||
|
(float)Math.Cos(this.horizontalViewAngle - MathHelper.PiOver2));
|
||||||
|
|
||||||
|
this.cameraUpVector = Vector3.Cross(this.cameraRightVector, this.cameraLookDirection);
|
||||||
|
|
||||||
|
// Perform any movement
|
||||||
|
if (forwardAxis > 0)
|
||||||
|
{
|
||||||
|
this.cameraPosition += this.cameraLookDirection * deltaTime * defaultMovementSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forwardAxis < 0)
|
||||||
|
{
|
||||||
|
this.cameraPosition -= this.cameraLookDirection * deltaTime * defaultMovementSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rightAxis > 0)
|
||||||
|
{
|
||||||
|
this.cameraPosition += this.cameraRightVector * deltaTime * defaultMovementSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rightAxis < 0)
|
||||||
|
{
|
||||||
|
this.cameraPosition -= this.cameraRightVector * deltaTime * defaultMovementSpeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the relative viewpoint
|
||||||
|
float aspectRatio = (float)widgetWidth / (float)widgetHeight;
|
||||||
|
Matrix4 Projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(defaultFOV), aspectRatio, 0.1f, 1000.0f);
|
||||||
|
Matrix4 View = Matrix4.LookAt(
|
||||||
|
cameraPosition,
|
||||||
|
cameraPosition + cameraLookDirection,
|
||||||
|
cameraUpVector
|
||||||
|
);
|
||||||
|
|
||||||
|
// Enable the colour array
|
||||||
|
GL.EnableVertexAttribArray(1);
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, ColourBufferID);
|
||||||
|
GL.VertexAttribPointer(
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
VertexAttribPointerType.Float,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
// Tick the actors before any rendering is done
|
||||||
|
this.Scene.Tick(deltaTime);
|
||||||
|
|
||||||
|
foreach (Actor actor in this.Scene.Actors)
|
||||||
|
{
|
||||||
|
actor.Render(ShaderProgramID, View, Projection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the arrays
|
||||||
|
GL.DisableVertexAttribArray(1);
|
||||||
|
|
||||||
|
//swap
|
||||||
|
MainGLWidget.Swapbuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool OnIdleProcessMain()
|
||||||
|
{
|
||||||
|
if (!GLInit)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Start deltaTime calculation
|
||||||
|
Stopwatch deltaTimeWatcher = new Stopwatch();
|
||||||
|
deltaTimeWatcher.Start();
|
||||||
|
|
||||||
|
System.Threading.Tasks.Task.Run(RenderFrame).Wait();
|
||||||
|
|
||||||
|
//RenderFrame();
|
||||||
|
|
||||||
|
MainGLWidget.ClearCurrent();
|
||||||
|
|
||||||
|
// End delta time calculation
|
||||||
|
deltaTimeWatcher.Stop();
|
||||||
|
this.deltaTime = (float)(deltaTimeWatcher.ElapsedMilliseconds * 0.001f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int LoadShaders()
|
||||||
|
{
|
||||||
|
int VertexShaderID = GL.CreateShader(ShaderType.VertexShader);
|
||||||
|
int FragmentShaderID = GL.CreateShader(ShaderType.FragmentShader);
|
||||||
|
|
||||||
|
string vertexShaderSourceCode;
|
||||||
|
using (Stream shaderStream =
|
||||||
|
Assembly.GetExecutingAssembly().GetManifestResourceStream("GLWidgetTestGTK3.Shaders.VertexShader.glsl"))
|
||||||
|
{
|
||||||
|
using (StreamReader sr = new StreamReader(shaderStream))
|
||||||
|
{
|
||||||
|
vertexShaderSourceCode = sr.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string fragmentShaderSourceCode;
|
||||||
|
using (Stream shaderStream =
|
||||||
|
Assembly.GetExecutingAssembly().GetManifestResourceStream("GLWidgetTestGTK3.Shaders.FragmentShader.glsl"))
|
||||||
|
{
|
||||||
|
using (StreamReader sr = new StreamReader(shaderStream))
|
||||||
|
{
|
||||||
|
fragmentShaderSourceCode = sr.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
int compilationLogLength;
|
||||||
|
|
||||||
|
Console.WriteLine("Compiling vertex shader...");
|
||||||
|
GL.ShaderSource(VertexShaderID, vertexShaderSourceCode);
|
||||||
|
GL.CompileShader(VertexShaderID);
|
||||||
|
|
||||||
|
GL.GetShader(VertexShaderID, ShaderParameter.CompileStatus, out result);
|
||||||
|
GL.GetShader(VertexShaderID, ShaderParameter.InfoLogLength, out compilationLogLength);
|
||||||
|
|
||||||
|
if (compilationLogLength > 0)
|
||||||
|
{
|
||||||
|
string compilationLog;
|
||||||
|
GL.GetShaderInfoLog(VertexShaderID, out compilationLog);
|
||||||
|
|
||||||
|
Console.WriteLine(compilationLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("Compiling fragment shader...");
|
||||||
|
GL.ShaderSource(FragmentShaderID, fragmentShaderSourceCode);
|
||||||
|
GL.CompileShader(FragmentShaderID);
|
||||||
|
|
||||||
|
GL.GetShader(FragmentShaderID, ShaderParameter.CompileStatus, out result);
|
||||||
|
GL.GetShader(FragmentShaderID, ShaderParameter.InfoLogLength, out compilationLogLength);
|
||||||
|
|
||||||
|
if (compilationLogLength > 0)
|
||||||
|
{
|
||||||
|
string compilationLog;
|
||||||
|
GL.GetShaderInfoLog(FragmentShaderID, out compilationLog);
|
||||||
|
|
||||||
|
Console.WriteLine(compilationLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Console.WriteLine("Linking shader program...");
|
||||||
|
int shaderProgramID = GL.CreateProgram();
|
||||||
|
|
||||||
|
GL.AttachShader(shaderProgramID, VertexShaderID);
|
||||||
|
GL.AttachShader(shaderProgramID, FragmentShaderID);
|
||||||
|
GL.LinkProgram(shaderProgramID);
|
||||||
|
|
||||||
|
GL.GetProgram(shaderProgramID, ProgramParameter.LinkStatus, out result);
|
||||||
|
GL.GetProgram(shaderProgramID, ProgramParameter.InfoLogLength, out compilationLogLength);
|
||||||
|
|
||||||
|
if (compilationLogLength > 0)
|
||||||
|
{
|
||||||
|
string compilationLog;
|
||||||
|
GL.GetProgramInfoLog(shaderProgramID, out compilationLog);
|
||||||
|
|
||||||
|
Console.WriteLine(compilationLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up the shader source code and unlinked object files from graphics memory
|
||||||
|
GL.DetachShader(shaderProgramID, VertexShaderID);
|
||||||
|
GL.DetachShader(shaderProgramID, FragmentShaderID);
|
||||||
|
|
||||||
|
GL.DeleteShader(VertexShaderID);
|
||||||
|
GL.DeleteShader(FragmentShaderID);
|
||||||
|
|
||||||
|
return shaderProgramID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles application shutdown procedures - terminating render threads, cleaning
|
||||||
|
/// up the UI, etc.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">Sender.</param>
|
||||||
|
/// <param name="a">The deletion arguments.</param>
|
||||||
|
protected void OnDeleteEvent(object sender, DeleteEventArgs a)
|
||||||
|
{
|
||||||
|
Application.Quit();
|
||||||
|
a.RetVal = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
61
GLWidgetTestGTK3/Program.cs
Normal file
61
GLWidgetTestGTK3/Program.cs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Gtk;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3
|
||||||
|
{
|
||||||
|
class MainClass
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
InitializeGlBindings();
|
||||||
|
|
||||||
|
// GTK
|
||||||
|
Application.Init();
|
||||||
|
MainWindow win = MainWindow.Create();
|
||||||
|
win.Show();
|
||||||
|
Application.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InitializeGlBindings()
|
||||||
|
{
|
||||||
|
// We don't put a hard dependency on OpenTK.Graphics here.
|
||||||
|
// So we need to use reflection to initialize the GL bindings, so users don't have to.
|
||||||
|
|
||||||
|
// Try to load OpenTK.Graphics assembly.
|
||||||
|
Assembly assembly;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
assembly = Assembly.Load("OpenTK.Graphics");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Failed to load graphics, oh well.
|
||||||
|
// Up to the user I guess?
|
||||||
|
// TODO: Should we expose this load failure to the user better?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var provider = new GTKBindingContext();
|
||||||
|
|
||||||
|
void LoadBindings(string typeNamespace)
|
||||||
|
{
|
||||||
|
var type = assembly.GetType($"OpenTK.Graphics.{typeNamespace}.GL");
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var load = type.GetMethod("LoadBindings");
|
||||||
|
load.Invoke(null, new object[] { provider });
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadBindings("ES11");
|
||||||
|
LoadBindings("ES20");
|
||||||
|
LoadBindings("ES30");
|
||||||
|
LoadBindings("OpenGL");
|
||||||
|
LoadBindings("OpenGL4");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
GLWidgetTestGTK3/Shaders/FragmentShader.glsl
Normal file
12
GLWidgetTestGTK3/Shaders/FragmentShader.glsl
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec3 fragmentColour;
|
||||||
|
|
||||||
|
out vec3 color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//color = vec3(0.18, 0.204, 0.212);
|
||||||
|
color = fragmentColour;
|
||||||
|
//color = vec3(gl_FragCoord.z);
|
||||||
|
}
|
14
GLWidgetTestGTK3/Shaders/VertexShader.glsl
Normal file
14
GLWidgetTestGTK3/Shaders/VertexShader.glsl
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#version 330 core
|
||||||
|
layout(location = 0) in vec3 vertexPosition_modelSpace;
|
||||||
|
layout(location = 1) in vec3 vertexColour;
|
||||||
|
|
||||||
|
uniform mat4 ModelViewProjection;
|
||||||
|
|
||||||
|
out vec3 fragmentColour;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = ModelViewProjection * vec4(vertexPosition_modelSpace, 1.0);
|
||||||
|
|
||||||
|
fragmentColour = vertexColour;
|
||||||
|
}
|
104
GLWidgetTestGTK3/World/Actor.cs
Normal file
104
GLWidgetTestGTK3/World/Actor.cs
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
//
|
||||||
|
// Actor.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Jarl Gullberg <jarl.gullberg@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Jarl Gullberg
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using GLib;
|
||||||
|
using GLWidgetTestGTK3.Data;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3.World
|
||||||
|
{
|
||||||
|
public class Actor
|
||||||
|
{
|
||||||
|
public Transform Transform;
|
||||||
|
private readonly Mesh Mesh;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="Actor"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Mesh">The mesh bound to the actor.</param>
|
||||||
|
public Actor(Mesh Mesh)
|
||||||
|
{
|
||||||
|
this.Mesh = Mesh;
|
||||||
|
this.Transform = new Transform(new Vector3(0.0f, 0.0f, 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs any arbitrary actions needed every frame, such as animations, texture manipulations or state
|
||||||
|
/// updates.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deltaTime">The time (in thousands of a second) taken to render the previous frame.</param>
|
||||||
|
public void Tick(float deltaTime)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Renders this actor within the current OpenGL context.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ShaderProgramID">The ID of the currently active shader.</param>
|
||||||
|
/// <param name="ViewMatrix">The camera view matrix, calulcated from the camera position.</param>
|
||||||
|
/// <param name="ProjectionMatrix">The perspective projection currently in use.</param>
|
||||||
|
public void Render(int ShaderProgramID, Matrix4 ViewMatrix, Matrix4 ProjectionMatrix)
|
||||||
|
{
|
||||||
|
// Enable the mesh vertex array
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, Mesh.VertexBufferID);
|
||||||
|
|
||||||
|
GL.EnableVertexAttribArray(0);
|
||||||
|
GL.VertexAttribPointer(
|
||||||
|
0,
|
||||||
|
3,
|
||||||
|
VertexAttribPointerType.Float,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
// Enable the normal attributes
|
||||||
|
GL.EnableVertexAttribArray(3);
|
||||||
|
GL.VertexAttribPointer(
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
VertexAttribPointerType.Float,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
Matrix4 modelTranslation = Matrix4.CreateTranslation(Transform.Translation);
|
||||||
|
Matrix4 modelScale = Matrix4.CreateScale(Transform.Scale);
|
||||||
|
Matrix4 modelRotation = Matrix4.CreateFromQuaternion(Transform.Rotation);
|
||||||
|
|
||||||
|
Matrix4 modelViewProjection = modelScale * modelRotation * modelTranslation * ViewMatrix * ProjectionMatrix;
|
||||||
|
|
||||||
|
// Send the model matrix to the shader
|
||||||
|
int projectionShaderVariableHandle = GL.GetUniformLocation(ShaderProgramID, "ModelViewProjection");
|
||||||
|
GL.UniformMatrix4(projectionShaderVariableHandle, false, ref modelViewProjection);
|
||||||
|
|
||||||
|
// Draw the model
|
||||||
|
GL.DrawArrays(BeginMode.Triangles, 0, Mesh.GetVertexCount());
|
||||||
|
|
||||||
|
// Release the attribute arrays
|
||||||
|
GL.DisableVertexAttribArray(0);
|
||||||
|
GL.DisableVertexAttribArray(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
135
GLWidgetTestGTK3/World/Mesh.cs
Normal file
135
GLWidgetTestGTK3/World/Mesh.cs
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
//
|
||||||
|
// Mesh.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Jarl Gullberg <jarl.gullberg@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Jarl Gullberg
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using GLWidgetTestGTK3.Data;
|
||||||
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3.World
|
||||||
|
{
|
||||||
|
public class Mesh
|
||||||
|
{
|
||||||
|
private List<Vertex> Vertices;
|
||||||
|
|
||||||
|
private int vertexBufferID = -1;
|
||||||
|
public int VertexBufferID
|
||||||
|
{
|
||||||
|
get { return vertexBufferID; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int normalBufferID = -1;
|
||||||
|
public int NormalBufferID
|
||||||
|
{
|
||||||
|
get { return normalBufferID; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool cullFaces;
|
||||||
|
|
||||||
|
public bool CullFaces
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mesh(List<Vertex> Vertices)
|
||||||
|
{
|
||||||
|
this.Vertices = Vertices;
|
||||||
|
|
||||||
|
this.vertexBufferID = UploadVertexPositions();
|
||||||
|
this.normalBufferID = UploadVertexNormals();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetVertexCount()
|
||||||
|
{
|
||||||
|
return Vertices.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int UploadVertexPositions()
|
||||||
|
{
|
||||||
|
if (vertexBufferID > 0)
|
||||||
|
{
|
||||||
|
return vertexBufferID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a buffer
|
||||||
|
GL.GenBuffers(1, out vertexBufferID);
|
||||||
|
|
||||||
|
// Get the vertex positions
|
||||||
|
float[] vertexPositions = GetVertexPositions();
|
||||||
|
|
||||||
|
// Upload the vertices to the GPU
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBufferID);
|
||||||
|
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexPositions.Length * sizeof(float)), vertexPositions, BufferUsageHint.StaticDraw);
|
||||||
|
|
||||||
|
return vertexBufferID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int UploadVertexNormals()
|
||||||
|
{
|
||||||
|
if (normalBufferID > 0)
|
||||||
|
{
|
||||||
|
return normalBufferID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a buffer
|
||||||
|
GL.GenBuffers(1, out normalBufferID);
|
||||||
|
|
||||||
|
// Get the vertex positions
|
||||||
|
float[] vertexNormals = GetVertexNormals();
|
||||||
|
|
||||||
|
// Upload the vertices to the GPU
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, normalBufferID);
|
||||||
|
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexNormals.Length * sizeof(float)), vertexNormals, BufferUsageHint.StaticDraw);
|
||||||
|
|
||||||
|
return vertexBufferID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float[] GetVertexPositions()
|
||||||
|
{
|
||||||
|
List<float> vertexPositions = new List<float>();
|
||||||
|
|
||||||
|
foreach (Vertex StoredVertex in Vertices)
|
||||||
|
{
|
||||||
|
vertexPositions.Add(StoredVertex.Position.X);
|
||||||
|
vertexPositions.Add(StoredVertex.Position.Y);
|
||||||
|
vertexPositions.Add(StoredVertex.Position.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vertexPositions.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private float[] GetVertexNormals()
|
||||||
|
{
|
||||||
|
List<float> vertexNormals = new List<float>();
|
||||||
|
|
||||||
|
foreach (Vertex StoredVertex in Vertices)
|
||||||
|
{
|
||||||
|
vertexNormals.Add(StoredVertex.Normal.X);
|
||||||
|
vertexNormals.Add(StoredVertex.Normal.Y);
|
||||||
|
vertexNormals.Add(StoredVertex.Normal.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vertexNormals.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
GLWidgetTestGTK3/World/Scene.cs
Normal file
60
GLWidgetTestGTK3/World/Scene.cs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
//
|
||||||
|
// Scene.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Jarl Gullberg <jarl.gullberg@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016 Jarl Gullberg
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
|
||||||
|
namespace GLWidgetTestGTK3.World
|
||||||
|
{
|
||||||
|
public class Scene
|
||||||
|
{
|
||||||
|
public readonly List<Actor> Actors = new List<Actor>();
|
||||||
|
|
||||||
|
private readonly int vertexArrayID = -1;
|
||||||
|
public int VertexArrayID
|
||||||
|
{
|
||||||
|
get { return vertexArrayID; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scene()
|
||||||
|
{
|
||||||
|
// Generate the vertex array
|
||||||
|
GL.GenVertexArrays(1, out vertexArrayID);
|
||||||
|
GL.BindVertexArray(VertexArrayID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the <see cref="Actor.Tick"/> function on all <see cref="Actor"/> instances
|
||||||
|
/// in the scene. Actors can define arbitrary behaviour in their ticks, but in most
|
||||||
|
/// cases it's used for animation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deltaTime">The time (in thousands of a second) taken to render the previous frame.</param>
|
||||||
|
public void Tick(float deltaTime)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Actors.Count; ++i)
|
||||||
|
{
|
||||||
|
Actors[i].Tick(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
194
GLWidgetTestGTK3/interfaces/MainWindow.glade
Normal file
194
GLWidgetTestGTK3/interfaces/MainWindow.glade
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generated with glade 3.16.1 -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.10"/>
|
||||||
|
<object class="GtkWindow" id="MainWindow">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="MainBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkAlignment" id="alignment1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuBar" id="MainMenuBar">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="menuitem1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">_File</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<child type="submenu">
|
||||||
|
<object class="GtkMenu" id="menu1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImageMenuItem" id="imagemenuitem1">
|
||||||
|
<property name="label">gtk-new</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImageMenuItem" id="imagemenuitem2">
|
||||||
|
<property name="label">gtk-open</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImageMenuItem" id="imagemenuitem3">
|
||||||
|
<property name="label">gtk-save</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImageMenuItem" id="imagemenuitem4">
|
||||||
|
<property name="label">gtk-save-as</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImageMenuItem" id="imagemenuitem5">
|
||||||
|
<property name="label">gtk-quit</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="menuitem2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">_Edit</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<child type="submenu">
|
||||||
|
<object class="GtkMenu" id="menu2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImageMenuItem" id="imagemenuitem6">
|
||||||
|
<property name="label">gtk-cut</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImageMenuItem" id="imagemenuitem7">
|
||||||
|
<property name="label">gtk-copy</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImageMenuItem" id="imagemenuitem8">
|
||||||
|
<property name="label">gtk-paste</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImageMenuItem" id="imagemenuitem9">
|
||||||
|
<property name="label">gtk-delete</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="menuitem3">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">_View</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="menuitem4">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">_Help</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<child type="submenu">
|
||||||
|
<object class="GtkMenu" id="menu3">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImageMenuItem" id="imagemenuitem10">
|
||||||
|
<property name="label">gtk-about</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkAlignment" id="GLWidgetAlignment">
|
||||||
|
<property name="width_request">500</property>
|
||||||
|
<property name="height_request">400</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
Loading…
Reference in a new issue