<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>OpenGL on dwmkerr.com</title><link>https://dwmkerr.com/categories/opengl/</link><description>Recent content in OpenGL on dwmkerr.com</description><generator>Hugo -- gohugo.io</generator><language>en-uk</language><managingEditor>Dave Kerr</managingEditor><copyright>Copright &amp;copy; Dave Kerr</copyright><lastBuildDate>Sat, 24 Sep 2011 06:57:00 +0000</lastBuildDate><atom:link href="https://dwmkerr.com/categories/opengl/index.xml" rel="self" type="application/rss+xml"/><item><title>Importing OpenGL Extensions Functions with wglGetProcAddress</title><link>https://dwmkerr.com/importing-opengl-extensions-functions-with-wglgetprocaddress/</link><pubDate>Sat, 24 Sep 2011 06:57:00 +0000</pubDate><guid>https://dwmkerr.com/importing-opengl-extensions-functions-with-wglgetprocaddress/</guid><description>&lt;p&gt;There are only a small set of the core OpenGL functions that can be imported via p/invoke - the majority of OpenGL functions are actually extension functions which are supported only on specific video cards. OpenGL offers a function called&amp;nbsp;wglGetProcAddress which can return the address of a named function - but how do we deal with this in the managed world?&lt;/p&gt;
&lt;p&gt;Here's a brief description of how it's handled in SharpGL. As of this morning, SharpGL's latest version contains &lt;strong&gt;all &lt;/strong&gt;core functions up to OpenGL 4.2 and &lt;strong&gt;all &lt;/strong&gt;standard extensions up to OpenGL 4.2. This takes the support for OpenGL to the latest version - August 2011.&lt;/p&gt;
&lt;p&gt;First we must import the wglGetProcAddress function:&lt;/p&gt;
&lt;pre class="brush: c-sharp;"&gt;[DllImport("opengl32.dll")]
public static extern IntPtr wglGetProcAddress(string name);&lt;/pre&gt;
&lt;p&gt;This is the correect p/invoke method of importing this function, however it returns an IntPtr, which we cannot call as a function. We could change the return type to a delegate but this function can return essentially any type of delegate - so where do we go from here?&lt;/p&gt;
&lt;p&gt;Well the next step is to define the delegates we want to use - they must have exactly the same name as the OpenGL functions and use the correct parameters for marshalling. Here are a couple of delegates for OpenGL 1.4:&lt;/p&gt;
&lt;pre class="brush: c-sharp;"&gt;private delegate void glBlendFuncSeparate (uint sfactorRGB, uint dfactorRGB, uint sfactorAlpha, uint dfactorAlpha);
&lt;p&gt;private delegate void glMultiDrawArrays (uint mode, int[] first, int[] count, int primcount);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now we must create a function which will turn an IntPtr into a delegate and invoke it:&lt;/p&gt;
&lt;pre class="brush: c-sharp;"&gt;/// &amp;lt;summary&amp;gt;
/// The set of extension functions.
/// &amp;lt;/summary&amp;gt;
private Dictionary&amp;lt;string, Delegate&amp;gt; extensionFunctions = new Dictionary&amp;lt;string, Delegate&amp;gt;();
&lt;p&gt;/// &amp;lt;summary&amp;gt;
/// Invokes an extension function.
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;typeparam name=&amp;ldquo;T&amp;rdquo;&amp;gt;The extension delegate type.&amp;lt;/typeparam&amp;gt;
/// &amp;lt;param name=&amp;ldquo;args&amp;rdquo;&amp;gt;The arguments to the pass to the function.&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;The return value of the extension function.&amp;lt;/returns&amp;gt;
private object InvokeExtensionFunction&amp;lt;T&amp;gt;(params object[] args)
{
// Get the type of the extension function.
Type delegateType = typeof(T);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Get the name of the extension function.
string name = delegateType.Name;
// Does the dictionary contain our extension function?
Delegate del = null;
if (extensionFunctions.ContainsKey(name) == false)
{
// We haven't loaded it yet. Load it now.
IntPtr proc = Win32.wglGetProcAddress(name);
if (proc == IntPtr.Zero)
throw new Exception(&amp;quot;Extension function &amp;quot; + name + &amp;quot; not supported&amp;quot;);
// Get the delegate for the function pointer.
del = Marshal.GetDelegateForFunctionPointer(proc, delegateType);
if (del == null)
throw new Exception(&amp;quot;Extension function &amp;quot; + name + &amp;quot; not supported&amp;quot;);
// Add to the dictionary.
extensionFunctions.Add(name, del);
}
// Get the delegate.
del = extensionFunctions[name];
// Try and invoke it.
object result = null;
try
{
result = del.DynamicInvoke(args);
}
catch
{
throw new Exception(&amp;quot;Cannot invoke extension function &amp;quot; + name);
}
return result;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;We now have a generalised way to invoke an extension function. The loaded functions are stored in a dictionary keyed by name so that the heavy lifting is only done the first time we try to invoke the function. &amp;nbsp;We can finally add the functions to the class as below:&lt;/p&gt;
&lt;pre class="brush: c-sharp;"&gt;public void BlendFuncSeparate(uint sfactorRGB, uint dfactorRGB, uint sfactorAlpha, uint dfactorAlpha)
{
InvokeExtensionFunction&amp;lt;glBlendFuncSeparate&amp;gt;(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
}
&lt;p&gt;public void MultiDrawArrays(uint mode, int[] first, int[] count, int primcount)
{
InvokeExtensionFunction&amp;lt;glMultiDrawArrays&amp;gt;(mode, first, count, primcount);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This is pretty cool - we can invoke any extension function as long as we have defined a delegate for it. What's more, by making the InvokeExtensionFunction function public we can allow other developers to provide their own delegates and invoke other extension functions.&lt;/p&gt;
&lt;p&gt;This is the technique used in SharpGL 2.0 to import extension functions - the Core/OpenGLExtensions.cs file contains thousands of lines of functions defined like this, however knowing how to invoke any kind of delegate is a useful skill in the managed world, so this trick could be used in other places.&lt;/p&gt;
&lt;p&gt;The version of SharpGL this post relates to is at:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sharpgl.codeplex.com/SourceControl/changeset/view/4474"&gt;http://sharpgl.codeplex.com/SourceControl/changeset/view/4474&lt;/a&gt;&lt;/p&gt;</description><category>CodeProject</category></item><item><title>SharpGL 2.0: Hardware Acceleration</title><link>https://dwmkerr.com/sharpgl-2-0-hardware-acceleration/</link><pubDate>Tue, 13 Sep 2011 07:33:00 +0000</pubDate><guid>https://dwmkerr.com/sharpgl-2-0-hardware-acceleration/</guid><description>&lt;p&gt;It took a bit of working out, but finally SharpGL can support hardware acceleration. Previously, all rendering in SharpGL was done to a DIB Section, the result of this would be blitted to the screen. Much playing around has shown that in fact this is problematic - rendering to DIB sections can &lt;em&gt;never&lt;/em&gt; be hardware accelerated.&lt;/p&gt;
&lt;p&gt;To hardware accelerate rendering, the rendering must be to a window or a pixel buffer. This has introduced an architectural change to SharpGL - the handling of a render context and any supporting objects (DIB sections, windows etc) is handled by a class that implements the IRenderContextProvider interface. This interface specifies that render context providers must be able to Create, Destroy, Resize and Blit.&lt;/p&gt;
&lt;p&gt;SharpGL 2.0 now has two render context providers, DIBSectionRenderContext provider which uses a DIB Section as previously and HiddenWindowRenderContextProvider which renders to a hidden window. The hidden window render context provider allows full hardware acceleration.&lt;/p&gt;
&lt;p&gt;I will be adding a new example application to the solution which shows rendering with the two providers side by side.&lt;/p&gt;
&lt;p&gt;So don't forget: DIB Sections can't be accelerated.&lt;/p&gt;</description><category>CodeProject</category></item></channel></rss>