| 1 |
<html lang="en"> |
|---|
| 2 |
<head> |
|---|
| 3 |
<title>DerelictGL</title> |
|---|
| 4 |
<link rel="stylesheet" type="text/css" href="styles.css"> |
|---|
| 5 |
</head> |
|---|
| 6 |
<body> |
|---|
| 7 |
<hr> |
|---|
| 8 |
<hr> |
|---|
| 9 |
<h2 align="center">DerelictGL</h2> |
|---|
| 10 |
<hr> |
|---|
| 11 |
<hr> |
|---|
| 12 |
<h3>Introduction</h3> |
|---|
| 13 |
DerelictGL is a D binding to the <a href="http://www.opengl.org/">OpenGL</a> |
|---|
| 14 |
library. Currently, DerelictGL exposes all core OpenGL functions up to version 2.1. However, |
|---|
| 15 |
in order to use features available in OpenGL versions greater than 1.1, you must load them |
|---|
| 16 |
separately after creating an OpenGL context. See below. |
|---|
| 17 |
|
|---|
| 18 |
<h3>Using</h3> |
|---|
| 19 |
<ol> |
|---|
| 20 |
<li>Always make sure the DerelictGL source modules are available on your import |
|---|
| 21 |
path.</li> |
|---|
| 22 |
<li>In modules that make use of DerelictGL, you will need to import the derelict.opengl.gl |
|---|
| 23 |
module.</li> |
|---|
| 24 |
<li>Before calling any OpenGL functions, you need to make a call to <tt>DerelictGL.load()</tt>. |
|---|
| 25 |
This will load the shared library and all core OpenGL 1.0 and 1.1 functions.</li> |
|---|
| 26 |
</ol> |
|---|
| 27 |
|
|---|
| 28 |
<p> |
|---|
| 29 |
The following is a complete program that loads DerelictGL: |
|---|
| 30 |
</p> |
|---|
| 31 |
|
|---|
| 32 |
<pre> |
|---|
| 33 |
import derelict.opengl.gl; |
|---|
| 34 |
|
|---|
| 35 |
void main() |
|---|
| 36 |
{ |
|---|
| 37 |
DerelictGL.load(); |
|---|
| 38 |
|
|---|
| 39 |
// now you can call OpenGL functions |
|---|
| 40 |
} |
|---|
| 41 |
</pre> |
|---|
| 42 |
|
|---|
| 43 |
<div class="note">Return values and parameters of type <tt>GLubyte*</tt>, when |
|---|
| 44 |
intended to represent a string, have been declared in DerelictGL as <tt>char*</tt> |
|---|
| 45 |
instead.</div> |
|---|
| 46 |
|
|---|
| 47 |
<p> |
|---|
| 48 |
As with other Derelict packages, DerelictGL will throw an exception if an error |
|---|
| 49 |
occurs while loading the shared library. For more information on Derelict |
|---|
| 50 |
exceptions, see the documentation for |
|---|
| 51 |
<a href="loading.html">Loading/Unloading Shared Libraries</a>. |
|---|
| 52 |
</p><p> |
|---|
| 53 |
Finally, the method <tt>DerelictGL.unload()</tt> is provided for convenience. In normal |
|---|
| 54 |
practice you do not need to call this function, as Derelict will unload the library |
|---|
| 55 |
automatically when the app exits. You generally should only use this function if |
|---|
| 56 |
you need to unload DerelictGL while the application is running. |
|---|
| 57 |
</p> |
|---|
| 58 |
|
|---|
| 59 |
<h3>Loading OpenGL Versions 1.2 and Later</h3> |
|---|
| 60 |
|
|---|
| 61 |
OpenGL poses a few issues beyond other libraries that Derelict binds to and |
|---|
| 62 |
therefore requires special-case handling. One problem is the variety of graphics |
|---|
| 63 |
cards and OpenGL versions available on end user systems. If you are developing |
|---|
| 64 |
an OpenGL application for general public consumption, there is no way to guarantee |
|---|
| 65 |
which version of the API will be available on any user's system until the |
|---|
| 66 |
application is actually run on that system. |
|---|
| 67 |
</p><p> |
|---|
| 68 |
Another issue is presented by Windows operating systems. The default opengl32.dll |
|---|
| 69 |
on Windows systems prior to Vista only provides exports for OpenGL 1.1. It has |
|---|
| 70 |
not been updated since it was first realeased on Windows 95. Furthermore, this |
|---|
| 71 |
DLL is a (rather poor) software implementation. Vista ships with the software |
|---|
| 72 |
implementation, but also includes an OpenGL DLL that supports up to core OpenGL |
|---|
| 73 |
1.4 and is implemented on top of Direct3D. This DLL provides hardware acceleration, |
|---|
| 74 |
but all of the calls first go through a translation layer to convert them to D3D |
|---|
| 75 |
calls. The system can load the implementation provided by the graphics card |
|---|
| 76 |
driver, but there is no way to know which implementation the application is |
|---|
| 77 |
actually using, or which version a graphics card driver supports, until the |
|---|
| 78 |
context is created. |
|---|
| 79 |
</p><p> |
|---|
| 80 |
Derelict's dynamic loading mechanism helps to work around the first issue. If not |
|---|
| 81 |
for the Windows problem, loading OpenGL version 1.2 and later could be accomplished |
|---|
| 82 |
via the single call to <span class="bold">DerelictGL.load</span>. However, in |
|---|
| 83 |
order to maintain a consistent interface across all platforms, DerelictGL includes |
|---|
| 84 |
some additional methods and constants to load and manage different OpenGL versions. |
|---|
| 85 |
</p><p> |
|---|
| 86 |
<tt>GLVersion</tt><br /> |
|---|
| 87 |
This enum defines all OpenGL versions currently loadable by Derelict. At the |
|---|
| 88 |
time of this writing, these are the values GLVersion defines: |
|---|
| 89 |
</p> |
|---|
| 90 |
<ul> |
|---|
| 91 |
<li>GLVersion.VersionNone</li> |
|---|
| 92 |
<li>GLVersion.Version11</li> |
|---|
| 93 |
<li>GLVersion.Version12</li> |
|---|
| 94 |
<li>GLVersion.Version13</li> |
|---|
| 95 |
<li>GLVersion.Version14</li> |
|---|
| 96 |
<li>GLVersion.Version15</li> |
|---|
| 97 |
<li>GLVersion.Version20</li> |
|---|
| 98 |
<li>GLVersion.Version21</li> |
|---|
| 99 |
</ul> |
|---|
| 100 |
|
|---|
| 101 |
<p> |
|---|
| 102 |
<tt>void DerelictGL.loadVersions(GLVersion minVersion)</tt><br /> |
|---|
| 103 |
This method will attempt to load a specific verision of OpenGL. If any version |
|---|
| 104 |
of OpenGL up to and including the version requested fails to load successfully, |
|---|
| 105 |
then this method throws a <span class="bold">SharedLibProcLoadException</span>. |
|---|
| 106 |
</p> |
|---|
| 107 |
<p> |
|---|
| 108 |
Before attempting to load any functions, two checks are made. The first check is |
|---|
| 109 |
to determine if an OpenGL context has been made current. If not, this method |
|---|
| 110 |
will throw an <span class="bold">Exception/span>. The method next determines |
|---|
| 111 |
if a check has been made internally for the latest available version supported |
|---|
| 112 |
by the driver. If not, that check is made. Only then are the functions loaded. |
|---|
| 113 |
</p><p> |
|---|
| 114 |
When this function returns successfully, a call to |
|---|
| 115 |
<span class="bold">DerelictGL.availableVersion</span> will return either a value |
|---|
| 116 |
greater than or equal to the version you requested to load. If an exception is |
|---|
| 117 |
thrown, you can still check the highest version loaded, which will be lower than |
|---|
| 118 |
that which you requested. |
|---|
| 119 |
</p> |
|---|
| 120 |
|
|---|
| 121 |
<p> |
|---|
| 122 |
<tt>GLVersion DerelictGL.availableVersion()</tt><br /> |
|---|
| 123 |
When this method is called, it first checks to determine if the available |
|---|
| 124 |
version has already been set. If not, it will query the driver for the highest |
|---|
| 125 |
version supported and <span class="bold">then will attempt to load each supported |
|---|
| 126 |
version</span>. A successful load will result in a return value that indicates |
|---|
| 127 |
the highest loaded version. A failure will result in an |
|---|
| 128 |
<span class="bold">Exception</span> if no context is current, or a |
|---|
| 129 |
<span class="bold">SharedLibProcLoadException</span> if any function failed to |
|---|
| 130 |
load. Successive calls will always return the latest loaded version as long |
|---|
| 131 |
as a context is valid. |
|---|
| 132 |
</p> |
|---|
| 133 |
|
|---|
| 134 |
<p> |
|---|
| 135 |
<tt>char[] DerelictGL.versionString(GLVersion glv)</tt><br /> |
|---|
| 136 |
Returns the string form of the given version. The format of the string is "Version X.X". |
|---|
| 137 |
</p> |
|---|
| 138 |
|
|---|
| 139 |
<p> |
|---|
| 140 |
<tt>bool DerelictGL.hasValidContext()</tt><br /> |
|---|
| 141 |
Returns true if a context has been made current. This is used internally before |
|---|
| 142 |
attempting any loads that require an active context, but is also publicly |
|---|
| 143 |
available. You may find this useful if you have an application that manages |
|---|
| 144 |
multiple OpenGL contexts. |
|---|
| 145 |
</p> |
|---|
| 146 |
|
|---|
| 147 |
<p> |
|---|
| 148 |
<span class="bold">Examples</span><br /> |
|---|
| 149 |
Generally, if you want to load a specific version of OpenGL, you should use |
|---|
| 150 |
<span class="bold">DerelictGL.loadVersions</span>. Otherwise, you can use |
|---|
| 151 |
<span class="bold">DerelictGL.availableVersion</span> to load the latest version |
|---|
| 152 |
available. Following are examples of both: |
|---|
| 153 |
</p> |
|---|
| 154 |
<pre> |
|---|
| 155 |
// Example 1: Requesting a specific version. |
|---|
| 156 |
import derelict.opengl.gl; |
|---|
| 157 |
import derelict.util.exception; |
|---|
| 158 |
|
|---|
| 159 |
void main() |
|---|
| 160 |
{ |
|---|
| 161 |
// load OpenGL 1.1 |
|---|
| 162 |
DerelictGL.load(); |
|---|
| 163 |
|
|---|
| 164 |
// attempt to load every version up to OpenGL 1.5 |
|---|
| 165 |
try |
|---|
| 166 |
{ |
|---|
| 167 |
DerelictGL.loadVersions(GLVersion.Version15); |
|---|
| 168 |
} |
|---|
| 169 |
catch(SharedLibProcLoadException slple) |
|---|
| 170 |
{ |
|---|
| 171 |
// Here, you can check which is the highest version that actually loaded. |
|---|
| 172 |
|
|---|
| 173 |
/* Do Something Here */ |
|---|
| 174 |
} |
|---|
| 175 |
} |
|---|
| 176 |
</pre> |
|---|
| 177 |
|
|---|
| 178 |
<pre> |
|---|
| 179 |
// Example 2: Loading the highest available version. |
|---|
| 180 |
import derelict.opengl.gl; |
|---|
| 181 |
import derelict.util.exception; |
|---|
| 182 |
|
|---|
| 183 |
void main() |
|---|
| 184 |
{ |
|---|
| 185 |
// load OpenGL 1.1 |
|---|
| 186 |
DerelictGL.load(); |
|---|
| 187 |
|
|---|
| 188 |
// attempt to load the higest GL version supported by the driver |
|---|
| 189 |
GLVersion glv; |
|---|
| 190 |
try |
|---|
| 191 |
{ |
|---|
| 192 |
glv = DerelictGL.getAvailableVersion(); |
|---|
| 193 |
} |
|---|
| 194 |
catch(SharedLibProcLoadException slple) |
|---|
| 195 |
{ |
|---|
| 196 |
// You might want to abort here if you are worried about a corrupt |
|---|
| 197 |
// shared library. Otherwise, you'll want to determine what was |
|---|
| 198 |
// actually loaded. |
|---|
| 199 |
glv = DerelictGL.getAvailableVersion(); |
|---|
| 200 |
} |
|---|
| 201 |
|
|---|
| 202 |
switch(glv) |
|---|
| 203 |
{ |
|---|
| 204 |
... |
|---|
| 205 |
} |
|---|
| 206 |
|
|---|
| 207 |
} |
|---|
| 208 |
</pre> |
|---|
| 209 |
|
|---|
| 210 |
<div class="note"> |
|---|
| 211 |
It should be noted that Derelict's <a href="selective.html">selective loading |
|---|
| 212 |
mechanism</a> may be used when loading versions later than 1.2. However, it is |
|---|
| 213 |
not recommended you do so unless there is a very compelling |
|---|
| 214 |
reason. |
|---|
| 215 |
</div> |
|---|
| 216 |
|
|---|
| 217 |
<h3>Loading OpenGL Extensions</h3> |
|---|
| 218 |
|
|---|
| 219 |
As an added convenience, DerelictGL includes support for the easy detection and |
|---|
| 220 |
loading of several OpenGL extensions. In the <tt>derelict.opengl.extension</tt> |
|---|
| 221 |
package are several subpackages. Each subpackage contains loaders for a group |
|---|
| 222 |
of extensions. For example, loaders for <span class='bold'>GL_EXT</span> |
|---|
| 223 |
extensions are found in <tt>derelict.opengl.extension.ext</tt>, loaders for |
|---|
| 224 |
<span class='bold'>GL_ARB</span> extensions in <tt>derelict.opengl.extension.arb</tt>, |
|---|
| 225 |
loaders for <span class='bold'GL_NV extensions in</span> |
|---|
| 226 |
<tt>derelict.opengl.extension.nv</tt>, and so on. |
|---|
| 227 |
|
|---|
| 228 |
<h4>Naming Conventions</h4> |
|---|
| 229 |
It's important to understand the difference between extension |
|---|
| 230 |
<span class='emph'>names</span> and <span class='emph'>name strings</span>. |
|---|
| 231 |
A name string is an extension name prefixed with <span class='bold'>GL_</span> |
|---|
| 232 |
(for core OpenGL extensions), or a platform-specific prefix (such as |
|---|
| 233 |
<span class='bold'>WGL_</span> on Windows and <span class='bold'>GLX_</span> on |
|---|
| 234 |
Linux) for platform-specific extensions. For example, <span class='bold'>ARB_shadow |
|---|
| 235 |
</span> is an extension name and <span class='bold'>GL_ARB_shadow</span> is a |
|---|
| 236 |
name string. |
|---|
| 237 |
<p> |
|---|
| 238 |
In DerelictGL, each supported extension has its own loader. The name of the |
|---|
| 239 |
loader's module is identical to the extension name, minus the prefix. The prefix |
|---|
| 240 |
is the name of the package in which the module can be found. For example, the |
|---|
| 241 |
loader for the extension <span class='bold'>ARB_shadow_objects</span> resides in |
|---|
| 242 |
the module <tt>derelict.opengl.extension.arb.shadow_objects</tt></span>. |
|---|
| 243 |
</p> |
|---|
| 244 |
<div class='note'> |
|---|
| 245 |
The one exception to this rule is the extension |
|---|
| 246 |
<span class='bold'>EXT_422_pixels</span>. In D, module names cannot begin with |
|---|
| 247 |
a number. For this extension, the module is |
|---|
| 248 |
<tt>derelict.opengl.extension.ext.four22_pixels</tt>. However, the name of the |
|---|
| 249 |
loader for this extension follows the convention outlined below. |
|---|
| 250 |
</div> |
|---|
| 251 |
|
|---|
| 252 |
<p> |
|---|
| 253 |
The name of each loader is a modified form of the extension name. Essentially, |
|---|
| 254 |
each lowercase word separated by an underscore is capitalized and the underscores |
|---|
| 255 |
removed, resulting in a camel-case name. Here are some examples: |
|---|
| 256 |
</p> |
|---|
| 257 |
<ul> |
|---|
| 258 |
<li>ARB_shadow => ARBShadow</li> |
|---|
| 259 |
<li>NV_float_buffer => NVFloatBuffer</li> |
|---|
| 260 |
<li>EXT_bgra => EXTBgra</li> |
|---|
| 261 |
<li>EXT_422_pixels =>EXT422Pixels</li> |
|---|
| 262 |
<li>ATI_texture_compression_3dc => ATITextureCompression3dc</li> |
|---|
| 263 |
</ul> |
|---|
| 264 |
<p> |
|---|
| 265 |
Take special notice of EXTBgra. It's tempting to write EXTBGRA instead, but in any |
|---|
| 266 |
case where acronyms are part of an extension name, the name of the loader |
|---|
| 267 |
will only capitalize the first letter of the acronym. |
|---|
| 268 |
</p> |
|---|
| 269 |
|
|---|
| 270 |
<h4>Loading Extensions</h4> |
|---|
| 271 |
|
|---|
| 272 |
On some operating systems, it may be possible to load extensions without first |
|---|
| 273 |
creating an OpenGL context. Unfortunately, on Windows, this is not the case. |
|---|
| 274 |
As such, in order to maintain a consistent interface DerelictGL requires that |
|---|
| 275 |
a valid OpenGL context exist before extensions can be loaded. Any attempt to |
|---|
| 276 |
load extensions when no context has been created will cause an exception to |
|---|
| 277 |
be thrown. |
|---|
| 278 |
|
|---|
| 279 |
<p> |
|---|
| 280 |
Once DerelictGL has been loaded and a context created, you can load all extensions |
|---|
| 281 |
used by your application with one method call: <tt>DerelictGL.loadExtensions</tt>. |
|---|
| 282 |
Extensions not used by your application will not be loaded. Internally, DerelictGL |
|---|
| 283 |
uses module constructors to track which extensions need to be loaded. So all you |
|---|
| 284 |
need do is to import the extension loader modules you intend you use. There is |
|---|
| 285 |
no requirement that you import them in the same module in which you load them -- |
|---|
| 286 |
you can import them anywhere in your application: |
|---|
| 287 |
</p> |
|---|
| 288 |
<pre> |
|---|
| 289 |
// render.d |
|---|
| 290 |
module myapp.render; |
|---|
| 291 |
|
|---|
| 292 |
import derelict.opengl.extension.arb.point_sprite; |
|---|
| 293 |
import derelict.opengl.extension.nv.texture_rectangle; |
|---|
| 294 |
|
|---|
| 295 |
... |
|---|
| 296 |
|
|---|
| 297 |
// init.d |
|---|
| 298 |
module myapp.init |
|---|
| 299 |
|
|---|
| 300 |
void loadOpenGL() |
|---|
| 301 |
{ |
|---|
| 302 |
// load DerelictGL |
|---|
| 303 |
DerelictGL.load(); |
|---|
| 304 |
|
|---|
| 305 |
// create the OpenGL context here (via SDL, Win32, or some other API) |
|---|
| 306 |
... |
|---|
| 307 |
|
|---|
| 308 |
// load all of the extensions you use (in this case ARB_point_sprite and NV_texture_rectangle) |
|---|
| 309 |
DerelictGL.loadExtensions(); |
|---|
| 310 |
} |
|---|
| 311 |
</pre> |
|---|
| 312 |
<p> |
|---|
| 313 |
This is a fine compromise between the two techniques often used in the C world: |
|---|
| 314 |
loading each extension individually, or using a third-party library that loads |
|---|
| 315 |
all available extensions. |
|---|
| 316 |
</p><p> |
|---|
| 317 |
The <tt>load</tt> method of each extension loader is publicly exposed, so you |
|---|
| 318 |
can call it directly if you prefer. It's much simpler, however, to use the |
|---|
| 319 |
<tt>loadExtensions</tt> method of DerelictGL instead. |
|---|
| 320 |
</p> |
|---|
| 321 |
|
|---|
| 322 |
<h4>Using Extensions</h4> |
|---|
| 323 |
|
|---|
| 324 |
Because all extensions used by the application are loaded at once, and because |
|---|
| 325 |
failure to load an extension rarely indicates that an application should terminate, |
|---|
| 326 |
no exceptions are thrown when an extension is not present or fails to load. It |
|---|
| 327 |
would have been possible to use Derelict's selective loading mechanism with |
|---|
| 328 |
extension loading, but the decision was made not to do so simply because it is |
|---|
| 329 |
not an exceptional circumstance for an extension to be unavailable on a user's |
|---|
| 330 |
machine. In fact, it is often expected that some extensions will not be present. |
|---|
| 331 |
Therefore, before attempting to use an extension it is important to check |
|---|
| 332 |
whether or not the extension is available. |
|---|
| 333 |
<p> |
|---|
| 334 |
Alternate code paths are the norm in OpenGL programming. Typically, developers |
|---|
| 335 |
determine a mimimal OpenGL version and/or extension set to support. If the minimum |
|---|
| 336 |
is not available on the user's machine, the application aborts. Many OpenGL |
|---|
| 337 |
applications also support more advanced features if they are available. For example, |
|---|
| 338 |
some advanced lighting technniques can be implemented with GLSL shaders, but |
|---|
| 339 |
when GLSL is unavailable the application can fall back to a different technique |
|---|
| 340 |
using the fixed-function pipeline for a degraded effect. Some applications may |
|---|
| 341 |
provide for three or four different ways of achieving a single effect. |
|---|
| 342 |
</p><p> |
|---|
| 343 |
With this in mind, each extension loader in Derelict exposes the following |
|---|
| 344 |
method: <tt>bool isEnabled()</tt>. You can call this method to determine if |
|---|
| 345 |
an extension is available and take appropriate action if it is not. Here is |
|---|
| 346 |
an example: |
|---|
| 347 |
</p> |
|---|
| 348 |
<pre> |
|---|
| 349 |
import derelict.extension.arb.vertex_shader; |
|---|
| 350 |
|
|---|
| 351 |
void doSomethingWithVertexShaderExtension |
|---|
| 352 |
{ |
|---|
| 353 |
if(ARBVertexShader.isEnabled()) |
|---|
| 354 |
{ |
|---|
| 355 |
// use extension here |
|---|
| 356 |
} |
|---|
| 357 |
else |
|---|
| 358 |
{ |
|---|
| 359 |
// use fallback, exit program, or whatever you need to do |
|---|
| 360 |
} |
|---|
| 361 |
} |
|---|
| 362 |
</pre> |
|---|
| 363 |
|
|---|
| 364 |
|
|---|
| 365 |
<h3>Dependencies</h3> |
|---|
| 366 |
<a href="util.html">DerelictUtil</a> |
|---|
| 367 |
|
|---|
| 368 |
</body> |
|---|
| 369 |
</html> |
|---|