OpenGL Programming on Mac OS X

This text is intended to be useful as both a programming guide and a reference manual.

Robert P. Kuehne, J. D. Sullivan

365 Pages

21368 Reads



PDF Format

3.61 MB

Game Development

Download PDF format

  • Robert P. Kuehne, J. D. Sullivan   
  • 365 Pages   
  • 19 Feb 2015
  • Page - 1

    read more..

  • Page - 2

    read more..

  • Page - 3

    read more..

  • Page - 4

    read more..

  • Page - 5

    read more..

  • Page - 6

    read more..

  • Page - 7

    read more..

  • Page - 8

    read more..

  • Page - 9

    read more..

  • Page - 10

    read more..

  • Page - 11

    read more..

  • Page - 12

    read more..

  • Page - 13

    read more..

  • Page - 14

    read more..

  • Page - 15

    read more..

  • Page - 16

    read more..

  • Page - 17

    read more..

  • Page - 18

    read more..

  • Page - 19

    read more..

  • Page - 20

    read more..

  • Page - 21

    read more..

  • Page - 22

    read more..

  • Page - 23

    read more..

  • Page - 24

    read more..

  • Page - 25

    read more..

  • Page - 26

    read more..

  • Page - 27

    read more..

  • Page - 28

    read more..

  • Page - 29

    read more..

  • Page - 30

    Acknowledgments The first edition of this book owes many thanks to many people, beginning with Bob’s good friend, Dave Shreiner. Dave and Bob have taught numerous SIGGRAPH courses together over the years and worked together at SGI. Dave encouraged Bob to take on this project with Addison-Wesley and was instru- mental in getting it off the ground and providing advice, reviews, read more..

  • Page - 31

    This page intentionally left blank read more..

  • Page - 32

    About the Authors Bob Kuehne is a graphics consultant and entrepreneur and currently works as the head of a graphics consultancy, Blue Newt Software. Blue Newt works with clients around the world to enhance their 3D graphics applications. Blue Newt helps clients move from fixed-function programming to shader appli- cations, from single- to multi-pipe, multi-display systems, and from read more..

  • Page - 33

    on medical and GIS imaging. He was one of the original four designers and implementers of SGI’s Volumizer API, and he earned a design patent for high performance modulation of 3D textures. He then moved to SGI’s Consumer Products Division, where he worked as part of the OpenGL software team dur- ing the bring-up of both the Cobalt and Krypton graphics chipsets. Since SGI, read more..

  • Page - 34

    Chapter 1 Mac OpenGL Introduction Welcome to OpenGL on Mac OS X! This book is designed to be your one-stop resource for all things OpenGL on the Mac. We wrote this book for Mac OpenGL developers such as you. We wrote it for ourselves, too—let us explain. We have always cherished having a comprehensive programming guide in hand that provides the continuity and context of read more..

  • Page - 35

    Whatever type of developer you are, whatever the age of your code, and no matter how you arrived at this title, we welcome you and hope you find our book useful. Why the Mac? For those of you who are new to the Mac platform, we’d like to spend a moment explaining a few of the reasons why the Mac makes a great platform on which to develop your applications. read more..

  • Page - 36

    such as XCode, Shark, and the various OpenGL debuggers and analyzers, bring a sense of efficiency, fun, continuity, and style to today’s Mac developers. So, back to the question of this section: Why the Mac? The authors of this book have developed applications for numerous platforms over the years— from Windows boxes, to generic Unix boxes, to SGI machines, Apple IIs, read more..

  • Page - 37

    you have visions of developing for multiple platforms, OpenGL is really your only option. Don’t feel too bad about that mandate, though, because once you start working with OpenGL, you’ll see that its performance is as good as any API out there. In fact, from your perspective as a developer, one of the key strengths of OpenGL is the way in which you can learn core read more..

  • Page - 38

    a sensibility and a practicality to all of our discussions—not trying to explain everything there is in all APIs, examples, and tools, but just what’s necessary and useful. We approach this entire topic from the perspective of an application developer who is trying to get a high-performance, great application developed on the Mac. OpenGL on the Mac is a large domain, but read more..

  • Page - 39

    This page intentionally left blank read more..

  • Page - 40

    Chapter 2 OpenGL Architecture on OS X Overview The Mac hardware platform has historically varied widely with regard to CPU, I/O devices, data busses, and graphics cards. The transition to Intel processors brings yet another step in this evolution to developers, who now have ano- ther Mac platform to consider with many different specifications. Despite the fact that the underlying read more..

  • Page - 41

    a logical evolution from its predecessor, IrisGL—named in accordance with the graphics hardware for which it was built. IrisGL was initially released by SGI in 1983. It included all of the necessary API entry points that, unlike OpenGL, han- dled windowing system tasks unrelated to actual graphics pipeline rendering. SGI soon realized that to grow its graphics workstation market read more..

  • Page - 42

    IrisGL Introduced OpenGL 1.0 OpenGL 1.1 OpenGL 1.2 OpenGL 1.3 OpenGL 1.4 OpenGL 1.5 OpenGL 2.0 OpenGL 2.1 1983 1992 1995 1998 2001 2002 2003 2004 2007 Figure 2-1 OpenGL Version History Timeline as an EXT extension by other vendors before being promoted to the core specification. Each of these stages of the extension process allows for indus- try “soak time” to expose the read more..

  • Page - 43

    Table 2-1 Versions of OpenGL in Which Extensions Were Promoted to Core OpenGL (Continued) OpenGL Version Extension Texture objects GL EXT texture object Vertex arrays GL EXT vertex array 1.2.1 ARB extensions introduced to promotion process 1.3 BGRA pixel format GL EXT bgra Range-bounded vertex draw elements GL EXT draw range elements Multisampling GL ARB multisample Multitexturing GL ARB read more..

  • Page - 44

    OpenGL Version Extension Texture crossbar environment mode GL ARB texture env crossbar Texture LOD bias GL EXT texture lod bias Texture mirrored repeat GL ARB texture mirrored repeat Window raster position GL ARB window pos 1.5 Buffer objects GL ARB vertex buffer object Occlusion queries GL ARB occlusion query Shadow functions GL EXT shadow funcs 2.0 Programmable shading GL ARB shader objects read more..

  • Page - 45

    Table 2-2 Mac OS Hardware Renderer Support for Versions of OpenGL Mac OS Version OpenGL Version Renderer 10.2.8 Jaguar 1.3 Radeon 9600/9700/9800 Radeon 9000/9200 Radeon 8500 Radeon 7000/7200/7500 Geforce FX Geforce 4 Ti Geforce 3 1.1 Apple Generic Renderer Geforce 2 MX/4 MX Rage 128 10.3.9 Panther 1.5 Geforce 6800 Geforce FX Radeon X800 Radeon 9600/9700/9800 1.3 Radeon 9200 Radeon 9000 Radeon 8500 read more..

  • Page - 46

    Table 2-2 Mac OS Hardware Renderer Support for Versions of OpenGL (Continued) Mac OS Version OpenGL Version Renderer 10.5 Leopard 2.1+ Apple Float Renderer 2.0+ Radeon HD 2400/HD 2600 Radon X1600/X1900 Radeon X800 Radeon 9600/9700/9800 Geforce 8800/8600M Geforce Quadro FX 4500 Geforce 6600/6800 Geforce FX 1.3 Radeon 9200 Radeon 9000 Radeon 8500 Radeon 7000/7200/7500 Geforce 4 Ti Geforce 3 1.2 GMA 950 read more..

  • Page - 47

    As you can see in Table 2-2, no particular version of OpenGL is standard across all hardware in a particular release of Mac OS. Care must be taken when writing an OpenGL application to always ensure that your baseline OpenGL implemen- tation version requirements are met independently of the Mac OS version. Note that only the last minor release version of each major release read more..

  • Page - 48

    vendor. Fortunately, the additional burden of communicating with different de- vices is largely shouldered by the implementation of OpenGL on the Mac OS. At the same time, the decision to tailor an application for peak performance or the cutting edge frequently requires reliance on features of specific graphics cards. The choice to specialize is a decision that lies in the hands read more..

  • Page - 49

    • Core Graphics • CGL (Core OpenGL) • AGL (Apple OpenGL) • AppKit (or Cocoa) Of these, only Core Graphics is not an OpenGL-specific interface. Of the OpenGL-specific windowing (or surface)-related interfaces, CGL is the lowest logical layer. It provides the most control when managing the interface between OpenGL and the windowing system. GLUT is the highest-level and easiest read more..

  • Page - 50

    The Mac OS OpenGL Plug-In Architecture One important thing that the engineers at Apple responsible for the OpenGL im- plementation realized early in development was that the computing landscape is constantly under change. Consider just the six major versions of Mac OS X that have emerged since 2001 (Table 2-3). Whether it’s market conditions, tech- nical capabilities, costs, or read more..

  • Page - 51

    OpenGL Application Mac OS OpenGL Implementation Dispatch Table GL Engine Plug-ins Driver Plug-ins glWindowPos3sv GL Engine N glAlphaFunc glAccum glBegin GL Engine 0 GL Engine 1 Software Renderer ATI Renderer NVidia Renderer Figure 2-3 The Mac OS OpenGL Plug-in Architecture layers, for two reasons: • Plug-ins are selectable directly by the application at pixel format selection time. • Plug-ins are read more..

  • Page - 52

    Earlier we discussed the very capable software renderer—a purely software path for rendering OpenGL commands. Hardware renderers are associated with specific hardware devices and accordingly have the graphics process- ing capabilities of those devices. One of the more notable capabilities of to- day’s graphics cards is their ability to drive multiple physical displays. Accord- ingly, read more..

  • Page - 53

    Whenever an application crosses a virtual screen boundary, it must make a call to synchronize its OpenGL context across the two different renderers. In other words, the context should be synchronized whenever your application win- dows are moved. This is due to the fact that in addition to the OpenGL context that you manage, every OpenGL application has a context that is read more..

  • Page - 54

    virtual screens as long as your application’s OpenGL rendering area resides entirely within one of them. Choosing a renderer is the first logical step in creating an OpenGL application for Mac OS. Several APIs are available to set up renderers on Mac OS, including GLUT, CGL and AGL, and you can also use the OpenGL-capable Cocoa View classes defined in AppKit. These methods read more..

  • Page - 55

    This page intentionally left blank read more..

  • Page - 56

    Chapter 3 Mac Hardware Architecture Overview We’ll now step back from the software side of things and look at hardware. Most modern personal computers have at least two large processors in them; a central processing unit (CPU) and a graphics processing unit (GPU—a term coined in the late 1990s). In 2001, the number of transistors in GPUs caught up with and surpassed the read more..

  • Page - 57

    Northbridge Memory CPU Front-side Bus Memory Bus PCIe Link PCIe Links ATA Bus GPU Southbridge PCle Card 0 PCle Card 1 PCle Card n Serial ATA Drive Figure 3-1 Prototypical System Architecture Diagram pathway to the memory controller and memory. The southbridge is the pathway to all other devices installed in the system, including PCI, AGP, and PCI Express (Peripheral Component Interconnect) read more..

  • Page - 58

    discuss some macro-level concepts of graphics software performance consid- erations here in the hardware architecture chapter. Our intention is to identify some of the general classes of performance problems that graphics applications face and to suggest how well (or badly) the available hardware solves these problems. Specifically, it’s necessary to understand the fundamental limits of read more..

  • Page - 59

    We have now described the various forms of bottlenecks that can arise in getting your data from the disk to the graphics. To review, the main data flow bottle- necks your application will face from the system perspective are as follows: • Disk I/O • Memory I/O • CPU I/O • GPU I/O Modern graphics cards internally look a lot like the host CPU architecture. That is, read more..

  • Page - 60

    27Hz, or 34Hz, or 19Hz—only integer multiples. This is due to an effect called “frame rate quantization,” which we’ll explore briefly in Chapter 11. Problem Domains Each domain from which a graphics application originates tends to have its own points of early saturation limits for general-purpose graphics hardware like the Mac. Here are some examples: • Gaming: CPU bound read more..

  • Page - 61

    be most concerned about. This section explores some of these baselines and ex- plains their implications for your application. CPU and Clock Rate Consider this minimum configuration example with regard to CPU and clock rate: On Mac OS 10.3 (also known as Panther), the minimum required CPU is a 300MHz G3 processor, 128MB of RAM, and no explicit requirements on VRAM of the read more..

  • Page - 62

    Memory The physical data path between main memory, the CPU, and other subsystems is known as the memory bus. The memory bus is the primary path over which data flows when it is being loaded to and from a disk, a network, or graphics. Memory bus speeds are implicitly related to the performance of the CPU, so knowing one gives insight into the other. Historically, there read more..

  • Page - 63

    Table 3-1 Processor Type and Graphics Bus Pairing CPU Bus Bandwidth (MB/s) G3 AGP 1X 256 G4 AGP 4X 1024 G5 AGP 8X 2048 G5 16-lane PCI Express 4096 CoreDuo/Core2Duo 16-lane PCI Express 4096 Xeon 16-lane PCI Express 4096 the realizable data bandwidth throughput to these devices is approximately 2.2GB/s on modern hardware. Despite the copious amounts of bandwidth available on modern hardware, the read more..

  • Page - 64

    systems, let alone subsystems like graphics. Even so, these large buffers are used for lots of tasks, including not just display of resultant images but also storage of various graphics data, from textures to geometry to the framebuffer itself. We’ll explore some of the issues you should consider about VRAM from a hardware perspective in this section. Why does Mac OS 10.2 read more..

  • Page - 65

    system memory in a minimally configured and quiescent Mac using the util- ity application Activity Monitor or Big Top can give you a basis for determining how much free memory you can reasonably expect to have available. Doing so early in your development cycle may help you later diagnose memory-related performance headaches. Summary Graphics application writers should have a solid read more..

  • Page - 66

    Chapter 4 Application Programming on OS X Overview The OS X revolution of the Mac operating system began in 2001. Darwin, the open-source core of OS X, is derived from Berkeley Systems Division (BSD) Unix. The introduction of a Unix core has had a profound—and arguably positive—effect on software developers for the platform. Along with the time- tested and industry standardized read more..

  • Page - 67

    Table 4-1 Mac OS X Versions and Code Names Version Number Code Name 10.0 Cheetah 10.1 Puma 10.2 Jaguar 10.3 Panther 10.4 Tiger 10.5 Leopard 10.6 Ocelot? Manx? Margay? Serval? dear reader. So, for your viewing, edification, and entertainment, we present in Table 4-1 a list of the Mac OS version numbers and release names current as of this publishing. For fun, we’ve added some speculative read more..

  • Page - 68

    For symmetry, it is easiest to consider power-on events as wake-up events. Sometimes, these events may be misunderstood to mean the system has pow- ered up from an off state, based on the naming conventions used. In reality, a wake-up event means that the system is coming out of a low-power mode and is notifying your application of that state change. So now that we have read more..

  • Page - 69

    case kIOMessageServiceIsRequestingClose: printf("ServiceIsRequestingClose\n"); break; case kIOMessageServiceIsAttemptingOpen: printf("ServiceIsAttemptingOpen\n"); break; case kIOMessageServiceWasClosed: printf("ServiceWasClosed\n"); break; case kIOMessageServiceBusyStateChange: printf("ServiceBusyStateChange\n"); break; case kIOMessageServicePropertyChange: printf("ServicePropertyStateChange\n"); break; case read more..

  • Page - 70

    } int main(int argc, char **argv) { IONotificationPortRef notify; io_object_t anIterator; float x = 5.81; root_port = IORegisterForSystemPower (&x,&notify,callback,&anIterator); if ( root_port == 0 ) { printf("IORegisterForSystemPower failed\n"); return 1; } CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notify), kCFRunLoopDefaultMode); printf("waiting...\n\n"); CFRunLoopRun(); read more..

  • Page - 71

    this message, your application can cancel the power state change with a call to IOCancelPowerChange . In other words, if the user asks the system to sleep from the Apple menu, calling IOCancelPowerChange will have no effect. In fact, for an active sleep request on the part of the user, your application will not receive a kIOMessageCanSystemSleep message as an event. You can, read more..

  • Page - 72

    Finding, Verifying, and Filing Bugs Occasionally, while writing or porting your OpenGL application to OS X, you may suspect you’ve found a bug in the OpenGL implementation or other parts of the Mac OS. One great thing about the Apple OpenGL team is that they want to help you succeed with your application on the Mac. With a collaborative effort, you’ll get great results. read more..

  • Page - 73

    Perhaps even more common than bugs filed where applications rely on unde- fined behavior are bugs filed that state “Application X runs on OS 10.x.y, but not on OS 10.x.z,” where z is a later revision than y. From a developer’s perspective, this can feel like a certainty that there is a bug in OS 10.x.z. This may well be the case, but consider this: The Mac read more..

  • Page - 74

    to create a small application with the offending OpenGL state that produces the problem. Don’t hesitate to ask Apple for template applications that can be augmented to create a test application. The company has templates that use all of the windowing system interfaces to OpenGL on Mac OS X: CGL, AGL, and Cocoa. With a smart and informative title, some coverage testing as read more..

  • Page - 75

    NSThreads pthreads Mach Threads Carbon Thread mgr Figure 4-1 Threading Layer Cake: Thread Packages, on Top of POSIX, on Top of Mach Threads For OpenGL applications on OS X, only a single thread may generate OpenGL commands for a given OpenGL context at one time. This, with some consider- ation, is somewhat self-evident. Consider the rendering output you would get if you interleaved read more..

  • Page - 76

    instructions are vector instructions that allow the application of the same op- eration to multiple data elements, in parallel. In some cases, if the data elements are large enough, the instructions may operate on a single data element or even a portion of a data element. AltiVec units have a set of burly registers that are 128 bits in size. For the math- adept among us, read more..

  • Page - 77

    Apple provides two good references if you’re interested in learning the details behind SSE. First, the performance analysis tool Shark, as described in Chapter 11, is a good way to see what’s going on in your code and find hints about what might be candidates for vectorization. Shark also contains a very nice SSE reference, containing all of the commands, their arguments, read more..

  • Page - 78

    Chapter 5 OpenGL Configuration and Integration This chapter explores in detail how to configure the necessary infrastructure to begin drawing with OpenGL. Specifically, it describes use of the various Macin- tosh APIs to window systems and off-screen render areas, and it examines how to configure each API for the type of OpenGL data you plan to render. If you’ve jumped to this read more..

  • Page - 79

    API Introductions and Overview The Mac has a rich history of 2D and 3D graphics, and the sheer number of API choices for drawing bears this out. Despite the many choices available, these APIs differ both in design and implementation, so it’s not too difficult to determine which is right for you. This section discusses each API specif- ically with the idea in mind that read more..

  • Page - 80

    In short, this API provides the functionality needed for your OpenGL applica- tion to communicate with the Macintosh Quartz Window Server. Core OpenGL CGL is the foundation layer of the Quartz windowing system interface to the OpenGL API. As with most foundation-layer APIs, CGL allows the greatest amount of flexibility and control over how your OpenGL application is con- figured, read more..

  • Page - 81

    complex application up and running quickly. Cocoa offers other benefits as well, but it’s the most modern of the user-interface choices on the Mac, with all the associated object-oriented benefits you’d expect. Interestingly, many of the Mac APIs for many other things start as lower-level APIs and are later incorporated into high-level Cocoa classes that do a lot of the read more..

  • Page - 82

    X11 The last major API set for graphics on the Mac is an old standby, X11. X11 APIs for windowing and OpenGL have existed for many years, and Apple fully sup- ports a set of them through its X11 SDK. If you’re bringing an application from another Unix platform to the Mac, it’s likely that the application uses X11 at its core. Apple has taken great effort with read more..

  • Page - 83

    Core Graphics CGL NSGL AGL Figure 5-1 OpenGL Configuration API Dependencies Even these calls may be unnecessary because Carbon and AppKit provide an abstraction for all of the window–server integration your API will likely need. Exceptions to this rule may arise when you are controlling the event stream directly or when you are requesting or setting windowing system-wide parame- ters read more..

  • Page - 84

    Sharing OpenGL Data Between Contexts To conserve VRAM and bandwidth throughout the system, it is a good idea to share data across contexts whenever possible. Sharing resources across contexts is one of the most commonly discussed topics in the OpenGL ARB, and with good reason. Sharing falls under the purview of the windowing system inter- face to OpenGL. These shared resources read more..

  • Page - 85

    The Apple OpenGL implementation maintains a reference count for shared objects. For most shared objects, this count is kept according to bind calls to those objects. In the vertex array object and framebuffer object cases, the ref- erence counts are kept according to the attachment state of these objects. For display lists, the reference count is maintained with respect to the read more..

  • Page - 86

    the integrity of shared objects across contexts. This is not a surprising requirement as this situation is completely analogous to critical regions when doing multithreaded programming. The GLX specification has more information regarding this popular topic among ARB members if you’re interested. Framebuffers When an OpenGL application performs its rendering, the output of that ren- dering read more..

  • Page - 87

    Width Color 24 Depth 24 Total Fragment Size Height Figure 5-2 Framebuffer Strata Framebuffers are a core resource for OpenGL. They, along with texture ob- jects, vertex array objects, shader objects, and other OpenGL resources, must be created, managed, and destroyed. To allocate, configure, and size them, their attributes must be described. The set of attributes that describe a framebuffer read more..

  • Page - 88

    Chapter 6 The CGL API for OpenGL Configuration Overview Since the transition from IrisGL to OpenGL, this graphics API has been indepen- dent of the windowing system of the operating system on which it runs. This aspect of the API was the primary redesign requirement of IrisGL to make it an open standard and multiplatform, rather than running on just the Iris worksta- tions on read more..

  • Page - 89

    OpenGL Application CGL GLEngine0 GLEngine1 GLEngine0 NV Driver SW Renderer ATI Driver ATI Hardware NV Hardware Figure 6-1 CGL Renderer Selection Because CGL lies beneath both AGL and the Cocoa interface to OpenGL, you can freely use CGL in combination with either an AGL application or a Co- coa application. CGL may also be freely used with GLUT applications be- cause the OS X GLUT read more..

  • Page - 90

    headers are found in the Headers directory of the OpenGL.framework direc- tory. Commonly used CGL headers include CGLTypes.h , CGLRenderers.h , and CGLMacros.h . We’ll talk more about these headers in this chapter. Error Handling CGL error handling is based on the values returned from each of the CGL func- tions. All CGL functions return 0 when successful. Upon failure, a number of read more..

  • Page - 91

    such as CGL provide a selection mechanism that attempts to match a set of re- quested attributes as closely as the underlying renderer can support. The CGL pixel format API consists of three entry points for creating, querying, and destroying pixels: CGLChoosePixelFormat CGLDescribePixelFormat CGLDestroyPixelFormat CGLChoosePixelFormat CGLChoosePixelFormat creates a pixel format using a NULL read more..

  • Page - 92

    than having a value of true or false explicitly listed for Boolean attributes, they are simply specified when true and not specified when false. The design of Apple’s pixel format API is subtractive in nature. That is, you can think of your attribute array as a set of constraints for the list of possible pixel formats that will match, rather than trying to build up a read more..

  • Page - 93

    The minimum policy sets the low bar for acceptance, but there is another asymmetry here: kCGLPFAMaximumPolicy doesn’t set the high bar for ac- ceptance. Instead, it means that if kCGLPFAColorSize , kCGLPFADepthSize , or kCGLPFAAccumSize is specified with a non-zero value, then the largest possible corresponding buffer size will be chosen for your pixel format object. kCGLPFAClosestPolicy is read more..

  • Page - 94

    Finally, if you wish to restrict the renderer list to only those renderers that can render on screen in a window, specify the kCGLPFAWindow attribute in your format array. Multisampling If multisampling is desired, set the kCGLPFASampleBuffers attribute to 1 to indicate a preference for a multisample buffer. Set the kCGLPFASamples attribute to the number of samples desired for each read more..

  • Page - 95

    kCGLRendererGeForce3ID kCGLRendererGeForceFXID kCGLRendererVTBladeXP2ID kCGLRendererIntel900ID kCGLRendererMesa3DFXID The star of this show is the Apple software renderer, which was released as part of Tiger. If you wish to use or test certain functionality that your hard- ware doesn’t support, you can use this renderer. The new software renderer is specified using kCGLRendererGenericFloatID . You read more..

  • Page - 96

    kCGLRendererAppleSWID Arguably, this renderer ID should not be published. It serves as a placeholder (and a questionable one at that) for graphics driver writers for OS X. kCGLRendererATIRage128ID kCGLRendererATIRadeonID kCGLRendererATIRageProID kCGLRendererATIRadeon8500ID kCGLRendererATIRadeon9700ID kCGLRendererATIRadeonX1000ID kCGLRendererGeForce2MXID kCGLRendererGeForce3ID kCGLRendererGeForceFXID kCGLRendererGeForce8XXXID read more..

  • Page - 97

    Specifying GL ALL ATTRIB BITS for your state mask will yield as close as pos- sible to a duplicate of your source context. The faithful reproduction of the copy is limited only by the scope of state encapsulated by the glPushAttrib/ glPopAttrib state management API within OpenGL. Various OpenGL state elements, such as feedback or selection settings, cannot be pushed and popped. read more..

  • Page - 98

    kCGLCPSurfaceOpacity = 236, /* 1 param. 1: surface is opaque (default), 0: non-opaque */ kCGLCPSurfaceBackingSize = 304, /* 2 params. Width/height of surface backing size */ kCGLCPSurfaceSurfaceVolatile = 306, /* 1 param. Surface volatile state */ kCGLCPReclaimResources = 308, /* 0 params. */ kCGLCPCurrentRendererID = 309, /* 1 param. Retrieves the current renderer ID */ kCGLCPGPUVertexProcessing = read more..

  • Page - 99

    Read/Write Parameters kCGLCPSwapRectangle If your application occupies much more screen space (whether the full screen or windowed) than you are typically drawing to, a kCGLCPSwapRectangle may be specified as an optimization hint for OpenGL. When a swap rectangle is defined, the Mac OpenGL implementation may be able to optimize your ap- plication by only swapping the back to the read more..

  • Page - 100

    and glutSurfaceTexture , respectively. The Mac OpenGL surface texturing API requires a surface ID. If you’re intent on using CGL only in your appli- cation (recommended solely as an academic exercise, and not for production code), your surface texturing will be limited to using pbuffers as the drawable source of the surface texture itself. There are no other surface IDs read more..

  • Page - 101

    Read-Only Parameters kCGLCPDispatchTableSize Used internally by OS X and tools for memory allocation. kCGLCPSurfaceBackingSize Used to retrieve the amount of memory allocated to support the drawable attached to the current context. kCGLCPSurfaceSurfaceVolatile Used internally by OS X for efficient surface management. kCGLCPCurrentRendererID Use as an argument to CGLGetParameter to retrieve the ID of read more..

  • Page - 102

    int main(int argc, char **argv) { // Grab the display mask for the main display // using kCGDirectMainDisplay // (steps1&2of4) CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask( kCGDirectMainDisplay ) ; CGLPixelFormatAttribute attribs[] = { kCGLPFAFullScreen, kCGLPFADisplayMask, displayMask, 0 }; CGLPixelFormatObj pixelFormatObj ; CGLContextObj contextObj ; CGLRendererInfoObj rendererInfoObj; long i, read more..

  • Page - 103

    Step 1: Obtaining Display IDs The first step is to obtain the display ID associated with the renderer you’re interested in inspecting. The Quartz Services API provides several routines for obtaining display IDs: • CGMainDisplayID • CGGetOnlineDisplayList • CGGetActiveDisplayList • CGGetDisplaysWithPoint • CGGetDisplaysWithRect CGMainDisplayID is the simplest of these calls. Its prototype read more..

  • Page - 104

    CGGetOnlineDisplayList will return active displays, mirrored displays, and sleeping displays. To distinguish this function from CGGetActiveDis- playList , mirrored displays may or may not be drawable and sleeping displays are not drawable. Display IDs can also be obtained based on spatial parameters: CGGetDisplaysWithPoint( CGPoint point, CGDisplayCount displayArraySize, CGDirectDisplayID *displayArray, read more..

  • Page - 105

    The displayMask parameter is a 32-bit quantity. To obtain renderer informa- tion about all renderers in the system, set all bits in displayMask to 1, or 0xFFFFFFFF. Step 4: Probing the Renderer Information Object for Information The CGLRendererInfoObj data type is an opaque pointer to a structure. To extract information from this structure, use CGLError CGLDescribeRenderer( CGLRendererInfoObj read more..

  • Page - 106

    kCGLRPFullScreen Boolean indicating whether the renderer supports full-screen rendering. kCGLRPRendererID The renderer ID being “described” by CGLDescribeRenderer . kCGLRPAccelerated Boolean indicating whether the renderer is hardware accelerated. kCGLRPRobust In the event that your current renderer is a hardware renderer, kCGLRobust indicates whether it can fall back to software in the event that read more..

  • Page - 107

    kCGLRPDisplayMask The display mask describing the physical displays to which the renderer is capa- ble of rendering. Display masks are managed by the Direct Display API, which is part of the Core Graphics API. See Steps 1 and 2 in Renderer Information earlier in this chapter (pages 70–71) for information on display masks. kCGLRPBufferModes The bitwise OR of buffer mode bits for read more..

  • Page - 108

    kCGLARGB12121212Bit 0x00200000 /* 48 argb bit/pixel, A=47:36, R=35:24, G=23:12, B=11:0 */ kCGLRGB161616Bit 0x00400000 /* 64 rgb bit/pixel, R=63:48, G=47:32, B=31:16 */ kCGLRGBA16161616Bit 0x00800000 /* 64 argb bit/pixel, R=63:48, G=47:32, B=31:16, A=15:0 */ kCGLRGBFloat64Bit 0x01000000 /* 64 rgb bit/pixel, half float */ kCGLRGBAFloat64Bit 0x02000000 /* 64 argb bit/pixel, half float */ kCGLRGBFloat128Bit 0x04000000 read more..

  • Page - 109

    kCGLRPMaxAuxBuffers The maximum number of auxiliary buffers supported by the renderer. kCGLRPMaxSampleBuffers The maximum number of independent sample buffers supported by the ren- derer. This renderer property generally reduces to a Boolean value. If a multi- sample buffer exists for the renderer, kCGLRPMaxSampleBuffers will be set to 1; otherwise, it is set to 0. kCGLRPMaxSamples For read more..

  • Page - 110

    CGLCreateContext also has an external definition in OpenGL.h of the OpenGL.framework . To successfully share data across contexts, the contexts must share the same renderer. Another way of expressing this requirement is to say that the contexts must have the same virtual screen list. A virtual screen is defined as the pairing of one renderer and its associated set of physical read more..

  • Page - 111

    CGLError CGLFlushDrawable(CGLContextObj ctx); CGLFlushDrawable causes an implicit flush of the OpenGL command stream. The results of all previously submitted OpenGL commands are then executed and reflected in the back buffer prior to it being copied to the front buffer. As with most OpenGL implementations, performing complex application logic immediately following a call to swap buffers is read more..

  • Page - 112

    Table 6-1 CGL Pbuffer Functions Function Description CGLCreatePBuffer Creates an AGL pixel buffer for use with an OpenGL texture type CGLDestroyPBuffer Destroys an AGL pixel buffer CGLDescribePBuffer Gathers information about an AGL pixel buffer CGLGetPBuffer Queries a context for the pixel buffer attached to it CGLSetPBuffer Sets the pixel buffer to be the target for the specified context read more..

  • Page - 113

    debugging that another CGL call has altered the configuration of the pbuffer. Again, only a NULL pbuffer object parameter will cause CGLDescribePBuffer to return its single possible error condition: kCGLBadAddress . To associate a pbuffer with a CGL context for rendering, call CGLError CGLSetPBuffer(CGLContextObj ctx, CGLPBufferObj pbuffer, unsigned long face, long mipmapLevel, long read more..

  • Page - 114

    Texturing with Pixel Buffers as the Source If you wish to specify that your pbuffer is to be used as the current texture, call CGLError CGLTexImagePBuffer(CGLContextObj ctx, CGLPBufferObj pbuffer, unsigned long sourceBuffer); The semantics for this call are the undisputed champion of complexity of all calls in CGL, and with good reason. CGLTexImagePBuffer is most similar to one of the read more..

  • Page - 115

    Off-Screen Drawables Off-screen drawables are simply a block of host memory that is used as a desti- nation for rendering. This block of memory must be allocated by your applica- tion and submitted to CGL through a call to CGLError CGLSetOffScreen(CGLContextObj ctx, long width, long height, long rowBytes, void *buffer); You must allocate a buffer that is at least rowBytes * height read more..

  • Page - 116

    if(pixelFormat == NULL) { // kCGLRendererGeForce3ID does NOT support full screen rendering } else { // kCGLRendererGeForce3ID supports full screen rendering } Example 6-3 is rigged because we know that kCGLRendererGeForce3ID sup- ports full-screen rendering, so this test should never fail. Of course, you could substitute your renderer of interest in this example. Testing for support of any read more..

  • Page - 117

    Explicit virtual screen changes are done with CGLError CGLSetVirtualScreen(CGLContextObj ctx, long virtualScreen); Such explicit virtual screen changes are a much less common occurrence than implicit changes. Consider what happens when you force a virtual screen change in your application. First, you’re changing the renderer from one hard- ware renderer to another without regard to the read more..

  • Page - 118

    CGLSetOption is used to set a global CGL option. Its function prototype is CGLError CGLSetOption(CGLGlobalOption globalOption, long\break optionValue); For retrieving global options, use CGLError CGLGetOption(CGLGlobalOption globalOption, long optionValue); The global options for CGL are as follows: typedef enum _CGLGlobalOption { kCGLGOFormatCacheSize = 501, kCGLGOClearFormatCache = 502, kCGLGORetainRenderers = read more..

  • Page - 119

    another “action” constant, CGLGetOption will return false when queried with this option. Using CGL Macros With OS X, Apple engineers came up with a way to avoid the cost of deter- mining the CGL context from the current thread. The cost of this lookup is significant because it must be done for every entry point in the OpenGL API. Cumulatively speaking, this context read more..

  • Page - 120

    For example, try reading the AGL reference guide segment on aglChoosePix- elFormat and then reading the CGL reference guide segment on CGL- ChoosePixelFormat . You may or may not find additional information on your topic, but it’s a good information path to keep in mind. We hope we’ve disuaded you from using either the surface texturing or pbuffer methods of rendering to read more..

  • Page - 121

    This page intentionally left blank read more..

  • Page - 122

    Chapter 7 The AGL API for OpenGL Configuration Overview OS X has both Carbon and Cocoa windowing interfaces to OpenGL. AGL, or “Apple OpenGL” is the Carbon windowing interface to OpenGL. Like CGL and Cocoa, the AGL interface provides a set of routines for managing pixel formats, OpenGL contexts, and drawables (a.k.a surfaces). As far as Apple technologies are concerned, AGL is read more..

  • Page - 123

    a porting strategy from windowing interfaces of other platforms such as GLX or WGL is relatively simple. To make the Cocoa versus AGL decision even more complex, the Carbon event model, in the humble opinion of the authors, is more complicated than the event model used by Cocoa. One of the most redeeming aspects of AGL is its clear and apparent similarity to CGL. It has read more..

  • Page - 124

    Table 7-1 Locations of AGL Headers and Frameworks Framework path /System/Library/Frameworks/AGL.framework Build flag -framework AGL Header #include<AGL/agl.h> With the fundamentals of AGL now described, and the locations in which to fully explore the framework identified, let’s move directly into pixel format and context configuration. Pixel Format and Context As we’ve discussed in earlier read more..

  • Page - 125

    management and plumbing are well beyond our scope. But without further ado, let’s begin the construction of our application. Full-Screen Application We will begin by creating a full-screen AGL application, so we must create a new XCode project and configure it to depend on the key libraries neces- sary for OpenGL and AGL on the Mac—that is, the AGL.framework and OpenGL.framework read more..

  • Page - 126

    pixel format that we use elsewhere, too. That’s all there is to our initialization and draw methods; they’re pretty much boilerplate OpenGL. Let’s now look at the entirety of our example application main method and see how a pixel format is declared, described, and initialized. Example 7-3 AGL Full-Screen Application main Method int main(int argc, char **argv) { // create read more..

  • Page - 127

    return an opaque handle that describes one or many pixel formats supported by the devices-and-attribute combination in the call. If this were production code, you’d want to ensure that the returned pixel format results were valid and, if they were not, check for other pixel formats that would better meet your needs. If a variety of pixel formats met the criteria you read more..

  • Page - 128

    Table 7-2 Pixel Format Specifiers for Use with aglChoosePixelFormat Token Description AGL ALL RENDERERS Choose from all available renderers. This can include non-OpenGL-compliant renderers. Usually better to specify. Type: Boolean n/a Default: n/a Policy: n/a AGL BUFFER SIZE Number of bits per color buffer. If AGL RGBA is specified, this value is the sum of all components. If a color index read more..

  • Page - 129

    Table 7-2 Pixel Format Specifiers for Use with aglChoosePixelFormat (Continued) Token Description AGL AUX BUFFERS Number of aux buffers. Type: Unsigned integer 0 specifies no aux buffers. Default: n/a Policy: Greater than or equal to value. AGL RED SIZE Number of red component bits. Type: Unsigned integer 0if AGL RGBA is GL FALSE . Default: n/a Policy: Closest. AGL GREEN SIZE Number of read more..

  • Page - 130

    Token Description AGL ACCUM GREEN SIZE Number of green accum bits. Type: Unsigned integer n/a Default: n/a Policy: Closest. AGL ACCUM BLUE SIZE Number of blue accum bits. Type: Unsigned integer n/a Default: n/a Policy: Closest. AGL ACCUM ALPHA SIZE Number of alpha accum bits. Type: Unsigned integer Value Default: Default Policy: AGL CLOSEST POLICY AGL PIXEL SIZE Framebuffer bits per pixel, read more..

  • Page - 131

    Table 7-2 Pixel Format Specifiers for Use with aglChoosePixelFormat (Continued) Token Description AGL OFFSCREEN Choose an off-screen renderer. Type: Token n/a Default: n/a Policy: Closest match. AGL FULLSCREEN Choose a full-screen renderer. Type: Token n/a Default: n/a Policy: n/a AGL SAMPLE BUFFERS ARB Number of multisample buffers. Type: Unsigned integer n/a Default: n/a Policy: n/a AGL SAMPLES ARB read more..

  • Page - 132

    Token Description AGL SAMPLE ALPHA Request alpha filtering Type: n/a n/a Default: n/a Policy: n/a AGL RENDERER ID Choose renderer by a specific ID. Type: Unsigned integer One of AGL RENDERER * ID tokens Default: n/a Policy: Exact. AGL SINGLE RENDERER Choose a single renderer for all screens. Type: Boolean GL TRUE Default: n/a Policy: n/a AGL NO RECOVERY Disable all failure recovery systems. read more..

  • Page - 133

    Table 7-2 Pixel Format Specifiers for Use with aglChoosePixelFormat (Continued) Token Description AGL ROBUST Choose a renderer that doesn’t have a hardware failure mode due to lack of graphics resources. Type: Boolean GL TRUE : Search renderers with no hardware failure modes as described. Default: GL FALSE Policy: Exact. AGL BACKING STORE Specify that only renderers with a back buffer that read more..

  • Page - 134

    Token Description AGL REMOTE PBUFFER Specifies that the renderer can render to an off-line pixel buffer. Type: Boolean n/a Default: n/a Policy: n/a AGL NONE Token to signal the end of the pixel format parameter array. Every pixel format attribute list for AGL must end with this token. Type: n/a n/a Default: n/a Policy: n/a The final piece of code we perform, after our main loop read more..

  • Page - 135

    Figure 7-2 AGL Full-Screen Example Results WindowRef window; GLint attribs[] = { AGL_DOUBLEBUFFER, AGL_ACCELERATED, AGL_NO_RECOVERY, AGL_RGBA, AGL_NONE }; // Context creation pixelFormat = aglChoosePixelFormat( &display, 1, attribs ); context = aglCreateContext( pixelFormat, NULL ); aglDestroyPixelFormat( pixelFormat ); aglSetCurrentContext( context ); // Window creation CreateNewWindow( kDocumentWindowClass, read more..

  • Page - 136

    SetWindowTitleWithCFString( window, CFSTR( "AGL Window" ) ); ShowWindow(window); aglSetDrawable( context, GetWindowPort( window ) ); aglUpdateContext( context ); // opengl setup and render initGLstate(); draw(); // mainloop while( !done ) { processEvent(); } // cleanup aglSetCurrentContext( NULL ); aglDestroyContext( context ); return( 0 ); } The first section of code performs some Carbon window read more..

  • Page - 137

    full-screen example. Window creation, the next step, is just the standard Car- bon window creation and is beyond the scope of this book. However, the necessity of having our window setup is visible in the final step in this section, in which we bind the AGL context to the AGL drawable. In our full-screen example, we did this create-and-bind operation in a single step read more..

  • Page - 138

    Figure 7-3 AGL Window Example Results your renderer supports. You can query the renderer information independently of any OpenGL context, and then you can use this discovered renderer informa- tion with your AGL pixel format to customize it to your needs. We now present some example code to search the list of renderers through AGL, and query some properties in Example 7-5. read more..

  • Page - 139

    << "id:"<<id<<"" << "hardware: " << accel <<""<< endl; cout << "\t" << "vram (Mb): " << vram/mm << " " << "tram (Mb): " << tram/mm << endl; ri = aglNextRendererInfo( ri ); ii++; } } else { GLenum error = aglGetError(); cout << "error: " read more..

  • Page - 140

    Table 7-3 Tokens for Use with aglDescribeRenderer Token Description AGL FULLSCREEN Supports full-screen applications AGL RENDERER ID Renderer ID value AGL ACCELERATED Supports hardware acceleration AGL ROBUST Has no failure mode for lack of resources AGL BACKING STORE Has copy-on-swap back buffer AGL WINDOW Supports render-to-window AGL MULTISCREEN Can support multiple screens with the same AGL context read more..

  • Page - 141

    Context sharing is typically requested when a new OpenGL context is created, and the context with which it will be sharing has been created and its sharable resources have been initialized. The context with items you wish to access is passed to some form of initialization for your new context, usually along with a pixel format. For two contexts to be compatible, their pixel read more..

  • Page - 142

    source context, the destination context, and the attribute mask describing which pieces of state to copy. Specifically, the mask and constants are the same ones that the glPushAttrib() call uses. For our example, we’d write code as in Example 7-7. Example 7-7 Copying the Context State Between Two Contexts in AGL aglCopyContext( context, otherContext, GL_ALL_ATTRIB_BITS ); One last note read more..

  • Page - 143

    Creation and use of off-screen surfaces begins with specification of the GL AGL OFFSCREEN token when constructing a pixel format. Only an AGLContext that has been successfully created with a pixel format using this token can be used to perform true off-screen rendering. After creation of a con- text, the next steps are to bind this off-screen render area, to make it active read more..

  • Page - 144

    Example 7-8 Pbuffer and Windowed Context Creation in AGL int main(int argc, char **argv) { // setup the pixelformat GLint attribs[] = { AGL_RGBA, AGL_DOUBLEBUFFER, AGL_ACCELERATED, AGL_NO_RECOVERY, AGL_DEPTH_SIZE, 16, AGL_NONE }; const int width = 451; const int height = 123; AGLPixelFormat pixelFormat; AGLPbuffer pbuffer; AGLContext context, pbContext; long virtualScreen; GDHandle display2 = read more..

  • Page - 145

    SetWindowTitleWithCFString( window, CFSTR("AGL PBuffer Texture") ); ActivateWindow(window, true); ShowWindow(window); // bind context to window aglSetDrawable( context, GetWindowPort(window) ); aglUpdateContext( context ); // initialize window context & draw window GLuint texid; init( context, pbuffer, &texid ); drawWindow( context, texid ); // stub event loop sleep( 4.0 ); // cleanup and read more..

  • Page - 146

    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); // Specify the pbuffer as the source for our texture data // This acts as a substitute for a glTexImage2D call. aglTexImagePBuffer( context, read more..

  • Page - 147

    Render-to/Copy-to-Texture In this section we describe a very common and widely available technique known as render-to-texture. Render-to-texture is as simple as it sounds: You simply render your intermediate scene, copy it to a texture, and then later use that texture in your final render. The method is simple and concise, with the only downside being the “copy of pixels” phase. read more..

  • Page - 148

    gluBuild2DMipmaps( GL_TEXTURE_2D, // 0, GL_RGB, texdim, texdim, // 0, GL_RGB, GL_UNSIGNED_BYTE, data ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glBindTexture( GL_TEXTURE_2D, 0 ); // unbind texture } void drawTexture() { glClearColor( 1.0, 1.0, 0.0, 1.0 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glBindTexture( GL_TEXTURE_2D, textureID ); glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, read more..

  • Page - 149

    Figure 7-5 AGL Render-to-Texture Example Results One quick note: We must invoke this code in this order if we want to achieve the proper results. This is a key step, and perhaps obvious, but Example 7-11 makes clear that you must first set up the texture, then draw contents into it, and finally draw the main scene. Example 7-11 AGL Copy-Texture Render Call Sequence // read more..

  • Page - 150

    performance limitations based on the underlying OpenGL operations. This technique is a capable fallback for when framebuffer objects are not available. Framebuffer Objects In this section we describe a modern and widely available technique for in- termediate renders using framebuffer objects. The interfaces to framebuffer objects were designed to closely resemble texture objects, provide a read more..

  • Page - 151

    glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); glClearColor( 0.0, 0.5, 0.8, 1.0 ); // enable, generate, and bind our texture objects glEnable( GL_TEXTURE_2D ); glGenTextures( (GLsizei) 1, &textureID ); glBindTexture( GL_TEXTURE_2D, textureID ); const unsigned int texdim = 64; const unsigned int nbytes = 3; char data[ texdim * texdim * nbytes ]; memset( data, 0xff, texdim * texdim * nbytes read more..

  • Page - 152

    Figure 7-6 Results of Rendering to a Framebuffer Object and Texturing a Quad with That Result in AGL Before we leave the topic of framebuffer objects, we’d like to point out a few reasons why they are superior to other forms of indirect rendering. First, framebuffer objects consist of memory allocated on the graphics card itself that is directly usable in its target read more..

  • Page - 153

    Summary In this chapter, we explored how to create and configure AGL-based OpenGL rendering areas for on-screen and full-screen windows and for various interme- diate render targets. We also saw how to create custom pixel formats, explored some of the common flags that these pixel formats take, and demonstrated how to configure and initialize contexts and pixel formats. In read more..

  • Page - 154

    Chapter 8 The Cocoa API for OpenGL Configuration Cocoa, also known as AppKit, is the Objective-C API for writing modern Mac OS X applications. Cocoa provides a high-level, object-oriented set of classes and interfaces for the OpenGL subsystem and for user–interface interaction. Cocoa is the modern successor to the NextStep API from NeXT Computer; the company’s initials explain the read more..

  • Page - 155

    CoreGraphics CGL NSGL AGL Figure 8-1 AppKit API and Framework in Overall OpenGL Infrastructure on the Mac and relevant images, workflow, and text for Mac OS X 10.5. If you’re looking for Mac OS X 10.4 content, read on, but if you’re looking for the same version of this chapter, addressing Leopard-specific changes, and with a Leopard look- and-feel, please read Appendix C. read more..

  • Page - 156

    Figure 8-2 Subclassing NSOpenGLView in Interface Builder Open the Resources folder, and double-click on the MainMenu.nib icon. This will open the nib file for this project in Interface Builder. Now switch to Interface Builder. In the MainMenu.nib window, click on the Classes tab, and navigate through the three-pane system until you finally click on NSOpenGLView . The panes should look read more..

  • Page - 157

    Figure 8-3 Subclassed NSOpenGLView in Interface Builder instance of this class in the nib, and the interface will update to return you to the Instances tab in the MainMenu.nib window. You should see something like Figure 8-4. Now let’s create the actual headers and code. In the MainMenu.nib win- dow, click on the Classes tab. If you’re lucky, MyOpenGLView will still be selected, read more..

  • Page - 158

    Figure 8-5 Custom View Palette in Interface Builder At this point, we’ve created the necessary infrastructure, but we still have to place our view in our window. As with most Interface Builder tasks, we accom- plish this by dragging and dropping and by applying a little customization. We begin by dragging a Custom View into the window named Window .Gotothe Cocoa-Interfaces window read more..

  • Page - 159

    Figure 8-7 Binding a Custom View to the NSOpenGLView Subclass Object the Tools menu and Show Info item) and click on the CustomView you just dragged into place. Choose the Custom Class pop-up menu entry in the Inspector window, and navigate and choose MyOpenGLView from the list. You should see results like those shown in Figure 8-7. We could have handled all of this setup, read more..

  • Page - 160

    Table 8-2 Selection Policies and Behaviors Policy Description Match Choose only from the set of pixel formats that match exactly. Closest Choose a match closest to the size specified, but not necessarily an exact match. Minimum Require a match of at least this size. Can choose larger sizes. Maximum Require a match of at most this size. Prefers larger sizes. “But wait,” you say, read more..

  • Page - 161

    #include <math.h> #import "MyOpenGLView.h" @implementation MyOpenGLView - (id) initWithFrame: (NSRect) frame { time = 0; angle = 0; GLuint attributes[] = { NSOpenGLPFAWindow, // choose among pixelformats capable of rendering to windows NSOpenGLPFAAccelerated, // require hardware-accelerated pixelformat NSOpenGLPFADoubleBuffer, // require double-buffered pixelformat NSOpenGLPFAColorSize, 24, // require 24 read more..

  • Page - 162

    Table 8-3 Common Pixel Format Qualifiers for Use with NSOpenGLPixelFormat Token Description NSOpenGLPFAAllRenderers Look in entire set of renderers to find a match. Type: Boolean YES: Search entire set of available renderers, including those that are potentially non-OpenGL compliant. Default: YES Policy: Any NSOpenGLPFADoubleBuffer Double buffer requirements. Type: Boolean YES: Search only for a read more..

  • Page - 163

    Table 8-3 Common Pixel Format Qualifiers for Use with NSOpenGLPixelFormat (Continued) Token Description NSOpenGLPFADepthSize Unsigned integer: The value specified is the number of depth buffer bits required. Default: If no value is specified, pixel formats discovered may or may not have a depth buffer. Selection policy: Pixel formats that most closely match this size are preferred. read more..

  • Page - 164

    Token Description NSOpenGLPFASamples Unsigned integer: The value specified is the number of samples for each multisample buffer required. NSOpenGLPFAColorFloat YES: Consider only renderers capable of using floating-point pixels. NSOpenGLPFAColorSize should also be set to 64 or 128 for half- or full-precision floating-point pixels (Mac OS 10.4). NSOpenGLPFAMultisample YES: Consider only renderers capable read more..

  • Page - 165

    Figure 8-8 Teapot Rendered with NSOpenGLView Subclass The first of these methods, which is named prepareOpenGL , is defined to be the first opportunity that your class will have to make some OpenGL calls. prepareOpenGL will be called once a valid pixel format, context, and draw- able are all available, so you can go ahead and call anything you’d like there. Keep in mind read more..

  • Page - 166

    glClearColor( 0, .5, .8, 0 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0, 0, -1 ); GLfloat green[4]={0,1,0,0}; glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green ); glutSolidTeapot( .5 ); [ [ self openGLContext ] flushBuffer ]; } @end If you see a teapot—success! In this section, we’ve explored one of the ways to read more..

  • Page - 167

    3. Create an instance of this class in MainMenu.nib . 4. Write code in XCode to create a custom pixel format and context. 5. Write code to create the teapot and handle the OpenGL initialization. We won’t say any more about how to accomplish the XCode project setup and configuration at this point, but rather will leave you to try to figure it out on your own. The read more..

  • Page - 168

    Figure 8-10 Subclassed NSOpenGLView in Interface Builder create files for both the header and the source for this view. Accept the defaults, and we’ll begin laying out the view in a window. We now need to place our view in our window, and designate it to be our MyView object. Drag a Custom View into the window named Window .Goto the Cocoa-Interfaces window as before, and read more..

  • Page - 169

    With that configuration out of the way, we move straight into the code phase. Save your MainMenu.nib , and switch to XCode. As before with the NSOpenGLView -derived project, we’ll do many of the same things, includ- ing creating a pixel format and creating a subclassed version of drawRect . We’ll also mimic some of the infrastructure automatically provided in NSOpenGLView , so read more..

  • Page - 170

    { NSLog( @"myView::initWithFrame" ); if ((self = [super initWithFrame:frameRect]) != nil) { GLuint attributes[] = { NSOpenGLPFAWindow, NSOpenGLPFAAccelerated, NSOpenGLPFADoubleBuffer, NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, NSOpenGLPFADepthSize, 24, NSOpenGLPFAMinimumPolicy, // select a pixelformat which meets or // exceeds these requirements 0 }; _pixelformat=[[ NSOpenGLPixelFormat alloc ] read more..

  • Page - 171

    2 -proceed without a shared context */ } } return( _context ); } - (void) lockFocus { NSLog( @"myView::lockFocus" ); // ensure we are ready to draw [ super lockFocus ]; // get our context NSOpenGLContext *cxt = [ self openGLContext ]; // ensure we are pointing to ourself as the Drawable if ( [ cxt view ] != self ) { [ cxt setView: self ]; } // make us the read more..

  • Page - 172

    [ [ self openGLContext ] flushBuffer ]; } @end In our MyView.m file, we start by looking at our initWithFrame overloaded method. This method is called when our object is getting constructed, with the desired layout of this particular view. As with our MyNSOpenGLView class, this method is where we set up our pixel format and prepare the rest of our class for subsequent use. In read more..

  • Page - 173

    this is known as “making your context current.” lockFocus is the place in the Cocoa framework where your view is made current, and where you can then make your context current. If we now look at our code, we can see that we need to overload this method to do the usual lockFocus work when we call our superclasses lockFocus . We then do work to get our OpenGL read more..

  • Page - 174

    texture path here. The Red Book [22] has lots of details on the imaging pipeline, if you’d like more information on that. Any pixel data that you might want to render in an OpenGL scene, you can handle through textures. To do so, you would download that image as a texture using glTexImage[123]D calls. Let’s provide an overview of this process and then translate it into read more..

  • Page - 175

    So we’ve covered the how and why of sharing a context, but what, exactly, is shared when context sharing is enabled? Interestingly enough, most OpenGL objects are shared, but the overall context state is not. That’s not entirely intu- itive, but it correlates well with what people usually want to do. You save valu- able card memory by reusing heavyweight objects in read more..

  • Page - 176

    Figure 8-12 Context Sharing: Two Windows and Two Custom NSOpenGLView s in Interface Builder Additional T opics 143 read more..

  • Page - 177

    Figure 8-13 Context Sharing: Two Custom NSOpenGLView s in XCode present it here and then discuss a bit more after presentation. The header code lives in Example C-5 and the source code is found in Example C-6. Example 8-5 Singleton Class Declaration for Managing a Shared Context #import <Cocoa/Cocoa.h> @interface SharedContext : NSObject { NSOpenGLPixelFormat* _pixelformat; NSOpenGLContext read more..

  • Page - 178

    Figure 8-14 Context Sharing: Set Visible on Launch for Second Window @implementation SharedContext - (id) init { if (self = [super init]) { _pixelformat = nil; _context = nil; GLuint attributes[] = { NSOpenGLPFAWindow, // windowed pixelformats NSOpenGLPFAAccelerated, // hw-accel pixelformat NSOpenGLPFADoubleBuffer, // double-buffered pixelformat NSOpenGLPFAColorSize, 24, // 24 bits for color-channels read more..

  • Page - 179

    NSOpenGLPFAMinimumPolicy, // meets or exceed reqs 0 }; _pixelformat=[[ NSOpenGLPixelFormat alloc ] initWithAttributes: (NSOpenGLPixelFormatAttribute*) attributes ]; if ( _pixelformat == nil ) { NSLog( @"SharedContext: No valid OpenGL pixel" \ @"format matching attributes specified" ); // at this point, we’d want to try different // sets of pixelformat attributes until we // got a read more..

  • Page - 180

    as we’ve written code similar to it earlier in this book. The only caveat when writing context-sharing code of your own is to keep in mind that any context that is meant to be shared must be compatible with the other contexts. Compat- ibility implies many things, but chiefly that the destination pixel depth, color depth, and other factors are similar. We work around read more..

  • Page - 181

    if ( _context == nil ) { NSLog( @"No valid OpenGL context can be" \ "created with that pixelformat" ); /* we can fail a few ways: 1 - bogus parameters: nil pixelformat, invalid sharecontext, etc. 2 - share context uses a different Renderer than the specified pixelformat recovery techniques: 1 - choose a different pixelformat 2 - proceed without a shared context */ read more..

  • Page - 182

    Remember that the OS X OpenGL implementation follows the conventions es- tablished in the GLX specification. Applications are responsible for synchroniz- ing the state of objects between contexts. This implies that multithreaded ap- plications with shared context establish mutex locks between the threads, use glFlush to flush pending commands that modify object state, and call glBind to read more..

  • Page - 183

    display capture is a very easy task, but entails strict ordering of the tasks. Essen- tially, the process proceeds as follows: 1. Capture the display. 2. Configure and display a full-screen window. 3. Handle events. 4. Release the display. It’s important to ensure that both event handling and teardown (or display release) occur. If they do not, you’ll probably get into a read more..

  • Page - 184

    For simplicity, we use the global form of display capture—that is, the form in which all displays are captured. You may have a need or a preference to control which display you capture more precisely. For those circumstances, Apple pro- vides CGDisplayCapture and CGDisplayRelease to specify a particular display. And that’s really all there is for display capture as it relates read more..

  • Page - 185

    case NSKeyDown: { unichar cc = [ [ event charactersIgnoringModifiers ] characterAtIndex:0 ]; switch ( cc ) { case 27: // escape key stayInFullScreenMode = NO; break; default: break; } } break; default: break; } } The basic idea is that while in full-screen mode, no external UI controls (Cocoa or other) exist that have natural event-handling mechanisms, so you need to do whatever your read more..

  • Page - 186

    the images to be reflected. This would be the image that we’d render in our intermediate buffer. In another example, we might want to render the same view of the street scene, but perhaps after the viewer hit his or her head on something—a painful simula- tion, to be sure! Perhaps your character was jogging and ran into a signpost. We want to render the scene read more..

  • Page - 187

    Previous extensions that enabled rendering to a texture have been much more complicated. One example is the combination of GL ARB pbuffer and GL ARB render texture , both of which are window-system extensions. This combination requires calling glxMakeCurrent , an expensive operation used to switch between the window and the pbuffer drawables. An application must cre- ate one pbuffer per read more..

  • Page - 188

    { GLuint fboID; GLuint textureID; float time; float angle; } - (void) angleUpdate: (NSTimer*) tt; - (void) reshape; @end We next look at the code in our prepareOpenGL method. As before, this is the place where we create and initialize things that we need to set up once per context. We look at the entire prepareOpenGL method in Example 8-11, so es- sentially we see the first read more..

  • Page - 189

    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboID ); glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureID, 0 ); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // unbind fbo // add a timer to oscillate the modelview NSTimeInterval ti = .1; [ NSTimer scheduledTimerWithTimeInterval: ti target: self selector: read more..

  • Page - 190

    glLoadIdentity(); glTranslatef( 0, 0, 1 ); glColor3f( 0, 1, 1 ); glBegin( GL_QUADS ); float ww = .9; float hh = .9; float zz = 0.0; glDisable( GL_TEXTURE_2D ); glVertex3f( -ww, -hh, zz ); glVertex3f( ww, -hh, zz ); glVertex3f( ww, hh, zz ); glVertex3f( -ww, hh, zz ); glEnd(); } - (void) drawFinalContents { glClearColor( 0, .5, .8, 1 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT read more..

  • Page - 191

    Figure 8-16 Results of Rendering to an FBO and Texturing a Quad with That Result (Texture Courtesy of NASA’s Earth Observatory) You can do a lot more with FBOs, including capturing other rendering results such as depth, stencil, and other render targets, but this kind of advanced usage is beyond the scope of this book. We refer you to the OpenGL framebuffer object extension read more..

  • Page - 192

    You simply render your intermediate scene, copy it to a texture, and then use that texture in your final render. Elegant, simple, and concise. There are, of course, details to deal with concerning how you target the texture into which you want to render and, in some cases, how you move pixels around the sys- tem into your final texture. Nevertheless, the process is read more..

  • Page - 193

    glOrtho(-1,1,-1,1,-1,100); glMatrixMode( GL_MODELVIEW ); // enable, generate, and bind our texture objects glEnable( GL_TEXTURE_2D ); glGenTextures( (GLsizei) 1, &textureID ); glBindTexture( GL_TEXTURE_2D, textureID ); const unsigned int texdim = 64; const unsigned int nbytes = 3; unsigned char data[ texdim * texdim * nbytes ]; memset( data, 0, texdim * texdim * nbytes ); unsigned int ii; read more..

  • Page - 194

    [ [ self openGLContext ] flushBuffer ]; } Notice two things in Example 8-16. First, our draw routines are the same as the FBO example, so we won’t present them again. The first method draws the stuff to be used as a texture, and the second draws the scene using the texture gen- erated from the first method. Second, there is no binding or other redirection of where read more..

  • Page - 195

    rendering into textures. Though many other choices are possible, we faced a difficult decision when writing this book—either to cover them all or to cover only a subset. To free up some weekends, we chose the latter option. To be fair, since we began this project, the FBO extension has really come of age, and we would recommend it without hesitation for those cases when read more..

  • Page - 196

    Chapter 9 The GLUT API for OpenGL Configuration GLUT is an older, tried-and-true, cross-platform API for quick and dirty ac- cess to OpenGL application infrastructure. GLUT provides a very simple and straightforward CAPI to create windows, manage device input, monitor win- dowing events, handle a run loop, and so on. It also provides low-level prim- itive construction elements such as read more..

  • Page - 197

    CoreGraphics CGL GLUT AppKit AGL Figure 9-1 GLUT API and Framework in the Overall OpenGL Infrastructure on the Mac Overview The GLUT API is part of the overall Apple OpenGL infrastructure. It leverages AppKit for its windowing and event requirements. Figure 9-1 shows where the GLUT API and framework reside relative to other API layers. The GLUT API lives in your particular SDK read more..

  • Page - 198

    Configuration and Setup Configuring and using GLUT is pretty straightforward, and given what we’ve covered in prior chapters, it should all feel somewhat familiar. We’ll waste no time in this section; we’ll just jump right into a code example and cover the only Mac-specific change you’ll need to be aware of for GLUT applications on the Mac. Begin by going to XCode and read more..

  • Page - 199

    Figure 9-3 Adding a Framework to This Project Figure 9-4 Resultant GLUT Project Showing Framework and Sample Code 166 Chapter 9: The GLUT API for OpenGL Configuration read more..

  • Page - 200

    live in the GL directory), so some wrangling is necessary to ensure that your compiler can find the header file. The code in Example 9-1 performs this operation to include the glut.h header using a preprocessor check to deter- mine whether we’re building on the Mac and, if so, to adjust where we find GLUT to use the framework-resolved path. Those are really the only read more..

  • Page - 201

    simple animated shape, but doesn’t do much else. The results of Example 9-2 are seen in Figure 9-5. Example 9-2 Basic GLUT Sample Application void prepareOpenGL() { myAngle = 0; myTime = 0; } void draw() { glClearColor( 0, .5, .8, 1 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glRotatef( myAngle, 0, 0, 1 ); glTranslatef( 0, 0, 1 read more..

  • Page - 202

    // this is comparable to glutInitDisplayMode with the // tokens below, and achieves a similar effect // glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); glutInitWindowSize( 450, 300 ); glutCreateWindow( "GLUT Configuration Example" ); // initialize our opengl (context is now valid) prepareOpenGL(); // register callback functions int delay = 50; glutTimerFunc( delay, angleUpdate, read more..

  • Page - 203

    a limited form of this capability through a complementary function called glutInitDisplayString . In no way is the GLUT process nearly as complete as the CGL, AGL, or Cocoa methods, but it does allow you to exert a fair degree of control. Among the capabilities exposed through this method, a caller can specify the number of bits in various color or depth channels, the read more..

  • Page - 204

    Figure 9-6 GLUT Project Results Showing Visual Selection and Rendered Object for Anti-Aliased Pixel Format to Example 9-2 are subtle, because the only differences involve the addition of the stencil and anti-aliasing. The results of the anti-aliasing are visible in Figure 9-6. For a much more verbose description of these flags, ways to use this initialization call, and more, check read more..

  • Page - 205

    This page intentionally left blank read more..

  • Page - 206

    Chapter 10 API Interoperability Overview This chapter will cover a variety of topics related to using some of the powerful (and cool) APIs on the Mac with your OpenGL application. You might be won- dering what we really mean when we say “interoperability” in the chapter title. Perhaps a better term might be “interfacing.” We’re going to explore how you get data from read more..

  • Page - 207

    OpenGL, in this chapter we’ll focus solely on the most actively developed and most modern of Apple’s APIs: Cocoa. All examples will be in Cocoa, and we won’t be shy about using Cocoa to its fullest benefit to get our job done with the least amount of extra coding. We begin by looking at images in Cocoa and considering how to populate and use them with OpenGL. read more..

  • Page - 208

    per frame, so it fits well in prepareOpenGL . Let’s add two NSImages , one based on a URL and another based on a file (Example 10-2). Example 10-2 Initialize NSImages - (void) prepareOpenGL { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho(-1,1,-1,1,-1,100); NSURL *url = [ NSURL URLWithString: @"" ]; NSImage *url_image=[[ NSImage alloc ] read more..

  • Page - 209

    NSImage to OpenGL Assuming we’ve got a valid NSImage from some source—either from initializ- ing one from a file or URL, or from another Cocoa API somewhere—we poten- tially need to do some data massaging and conversion to transform the image data into a form that is compatible with OpenGL. The major phases of this pro- cess are as follows: 1. Determine the basic read more..

  • Page - 210

    The final technique—resizing the data to be a power of two—is the most space- efficient in terms of the hardware, but at the cost of some image quality loss. However, this technique is the one most easily implemented, so we’ll explain it here. Resizing an NSImage to a Power of Two Our goal in this section is to take an arbitrarily sized NSImage and resize it to read more..

  • Page - 211

    Figure 10-1 NSImage Rendered Before setFlipped (left), and After setFlipped (right). lockFocus method. lockFocus (and its counterpart unlockFocus ) are ele- ments of how Quartz rendering works, and not really something we’ll explore in detail. The Apple documentation has lots of details on Quartz rendering, so check there if you are interested in other things you can do with Quartz. We read more..

  • Page - 212

    Table 10-1 NSBitmapImageRep Accessors for OpenGL Texture Data Accessor Description - (int)bitsPerPixel Number of bits per image pixel - (int)bytesPerPlane Number of bytes in each image plane (R, G, B, A, etc.) - (int)bytesPerRow Number of bytes in an image pixel row - (unsigned char *)bitmapData Pointer to contiguous buffer containing all pixel data Example 10-4 Extracting a Bitmap from an read more..

  • Page - 213

    NSImage *file_image = [ [ NSImage alloc ] initWithContentsOfFile: @"/System/Library/Screen Savers/Cosmos.slideSaver/" \ @"Contents/Resources/Cosmos07.jpg" ]; // resize our image to a power of 2 NSImage *file_image_resized = [ self transformImage: url_image toSize: NSMakeSize( 512, 512 ) ]; // download an image as a texture [ self downloadImageAsTexture: file_image_resized ]; // configure read more..

  • Page - 214

    { case 4: texformat = GL_RGBA; break; case 3: texformat = GL_RGB; break; case 2: texformat = GL_LUMINANCE_ALPHA; break; case 1: texformat = GL_LUMINANCE; break; default: break; } // generate a texture object glGenTextures( 1, (GLuint*)&tid ); glBindTexture( GL_TEXTURE_2D, tid ); // download the pixels gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, [ imgBitmap pixelsWide ], [ imgBitmap pixelsHigh ], read more..

  • Page - 215

    graphics hardware. These fundamental techniques will be used again and again as we look at other methods of manipulating images and video on the Mac. OpenGL to NSImage In the previous section, we saw how to create an OpenGL downloadable ob- ject from an incoming NSImage . Of course, you might want to do the con- verse as well. That is, you might want to extract an read more..

  • Page - 216

    // ask the gl for the pixels, storing them in our bitmap image glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); unsigned char *bmdata = [ bitmap bitmapData ]; NSLog( @"bmd: %d %d\n", imageArea.size.width, imageArea.size.height ); glReadPixels( 0, 0, imageArea.size.width, imageArea.size.height, GL_RGB, GL_UNSIGNED_BYTE, bmdata ); [ self writeBitmapImageRep: bitmap toFile: @"/tmp/test_bitmap.png" ]; read more..

  • Page - 217

    manipulations, we end up with a lovely NSImage that we can use in another part of a Cocoa application that takes an image. QuickTime In this section we’ll explore another way of integrating native Mac technol- ogy with your OpenGL application. Specifically, we’ll look at how to integrate video content using the QuickTime API. Although there are lots of image-based techniques read more..

  • Page - 218

    QuickTime to OpenGL As with other interoperability topics, we’ll try to focus on the most modern tech- niques and the highest-level languages available to developers in our present discussion. In this case, we’ll focus on Cocoa, but because of QuickTime’s his- tory, we’ll make a brief diversion to explore how the legacy QuickTime routines behave, too. This section will unfold read more..

  • Page - 219

    accomplishes our goal of rendering to OpenGL as efficiently as possible in terms of both performance and overall amount of code. Our plan of attack to integrate your QuickTime content in OpenGL is simple. We’ll use similar baseline code as we included in our NSImage example but take advantage of the fancy media-handling capabilities within QuickTime to decide which frame we read more..

  • Page - 220

    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glEnable( GL_TEXTURE_2D ); // add a timer to oscillate the modelview NSTimeInterval ti = .1; [ NSTimer scheduledTimerWithTimeInterval: ti target: self selector: @selector(angleUpdate:) userInfo: nil repeats: YES ]; } QTMovie is an API with a lot of entry points. There are dozens of ways to use this API. Consider yourself lucky, read more..

  • Page - 221

    // flip texture glMatrixMode( GL_TEXTURE ); glLoadIdentity(); glScalef( 1, -1, 1 ); // grab the next frame from the movie // and download it as a texture if ( movie != nil ) { [movie play]; [ self downloadImageAsTexture: [ movie currentFrameImage ] ]; } // configure the view matrix and draw a textured quad glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glRotatef( angle, 0, 0, 1 ); read more..

  • Page - 222

    Figure 10-2 First Frame of the Movie we can improve this program’s performance significantly, but we’ll save that for Chapter 11. Check there for all the optimizations we can make to streamline this streaming media download. For now, we’re focusing on functionality, not trying to prematurely optimize the application. What do we see if we replace our prepareOpenGL and drawRect read more..

  • Page - 223

    Figure 10-3 Subsequent Frames of the Movie NeXT was cranking away on Objective-C2 and a lot of really interesting ideas for user interface libraries, which would (much later) become the Cocoa API for Mac OS X. However, the mainline Mac world was still focused on Pascal and, in some measure, C. At that time the Mac was known for many things but none of them was ease of read more..

  • Page - 224

    Figure 10-4 Final Frame of the Movie OpenGL to QuickTime In the previous section we learned how to integrate a movie into an OpenGL application as a texture, which is then usable with any object. Now we’ll learn how to take our rendered OpenGL data and configure it into a movie. Although this task has little to do with OpenGL per se, it does build on our prior read more..

  • Page - 225

    contents of a movie are a simple sequence of images. We already know how to read a frame from OpenGL into an NSImage , so we’re almost completely done even before we’ve looked at the code. Let’s update that list with the code frag- ments to do the actual work, and we’ll leave it as an exercise for you to assemble and insert these bits and pieces in the read more..

  • Page - 226

    Summary In this chapter, we saw how to read and write QuickTime movies, interfac- ing their content with OpenGL. To do so, we relied on previously introduced techniques for downloading textures, manipulating NSImage s, and perform- ing basic OpenGL configuration. You should now have a solid idea about how to use any form of video content accessible via QuickTime with your OpenGL read more..

  • Page - 227

    This page intentionally left blank read more..

  • Page - 228

    Chapter 11 Performance Overview Performance-tuning your OpenGL application for OS X may well be the most satisfying part of your project. No other platform can compare with OS X’s great set of performance tools, especially for OpenGL-based applications. Because OpenGL is a first-class citizen on OS X, the implementation and tools have been given years of scrutiny and improvements to read more..

  • Page - 229

    Axioms for Designing High-Performance OpenGL Applications Before describing the individual “blessed” logical paths in OpenGL, we thought it best to put down, in black and white, some mantras you may want to repeat to keep yourself on the straight and narrow. Wandering into the weeds can cost you a lot of frame rate. For any of these performance awareness axioms, you may read more..

  • Page - 230

    the system and all the synchronization overhead inherent in bringing this state up-to-date. Consider also that deferral of updates is often a good strategy for any synchro- nization task in a system. You may, therefore, be introducing costs into the equa- tion that are realized at a later—and sometimes unpredictable—time. For exam- ple, often the cost of a state change is not read more..

  • Page - 231

    glBegin(GL_POLYGONS); for(i = 0; i < 10; i++) glVertex2fv(v+i*2); glEnd(); } Now consider the OpenGL efficiency of instantiating this leaf class 1000 times for a small oak tree in your scene. First, it calls glColor3f() 1000 times, when it needed to be called only once. Second, this code submits 10 vertices at a time, when it could have submitted 10,000. As contrived as this read more..

  • Page - 232

    With immediate mode rendering, data are downloaded from host memory to VRAM for every frame of rendering, whether its vertices between a glBegin() –glEnd() pair, textures, images, or shaders. This redundant data transfer limits your potential rendering performance to the bandwidth of the graphics bus and, in some cases, the performance of the CPU and the host memory system, as it read more..

  • Page - 233

    graphics device as close to the theoretical bandwidth as is achievable. To keep this stream of data flowing and going in one direction, it is important not to issue any unnecessary queries or reads from the OpenGL implementation. The rule of thumb here is that any OpenGL call that has a return value will likely stall the rendering pipeline. You may be wondering why said read more..

  • Page - 234

    Shader Instruction Limits At present, we’re still relatively early in the shader evolutionary chain. Much of the graphics hardware in circulation places limits on the number of shader instructions supported. If those limits are exceeded, your application could very unpleasantly find itself on a software rendering path. Mac OS X has CGL parameters available to allow you to query read more..

  • Page - 235

    submit that data for rendering. Consider, as a simple example, what happens when glVertex3f() is called between a glBegin() –glEnd() pair. Until glEnd() is called, the vertex data must be retained by OpenGL until needed for rendering. This simple example can be extended to textures as well. Thus, if you consider how large textures can be and how many vertices you typically read more..

  • Page - 236

    By minimizing the time needed to return control to the application, the threaded OpenGL engine in the Mac OS allows more processing cycles for the application logic. The threaded OpenGL engine fundamentally does more work than the stan- dard serial engine. It relies on an additional processor to handle this extra work. The good news is that you don’t have to detect the read more..

  • Page - 237

    don’t have to specify a parameter at context creation time to enable it. Rather, you can turn the threaded engine on and off as often as you wish. That said, turning the multithreaded engine on or off should be done judi- ciously. Consider all of the state management, thread management, and mutex management that accompanies a switch from rendering on a single-threaded basis read more..

  • Page - 238

    asynchronous programming is a bit more difficult because data doesn’t move in the system without you telling it to do so. The pattern is this: modify some data, do some other stuff, check whether the data is ready for use, and then use the data. The flipside of this peril is that this additional control allows your application to apply “smarts” about how its data read more..

  • Page - 239

    Here’s an example of using Apple Flush Buffer Range to do partial flushing on a buffer object. In Example 11-3, we arbitrarily chose to work with pixel buffer objects. Vertex buffer objects work in exactly the same manner, albeit with some simple substitutions of the type of data created and the target parameter of the buffer object OpenGL calls (i.e., GL ARRAY BUFFER or read more..

  • Page - 240

    // Flush the modified region to VRAM glFlushMappedBufferRangeAPPLE(GL_PIXEL_PACK_BUFFER, 0, width * height); // Unmap and unbind glUnmapBuffer(GL_PIXEL_PACK_BUFFER); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); Apple Fence Extension Fences are tokens in the OpenGL command stream that act like tracer bullets; they tell you where you are. Fencing is a key concept because it bridges the world of the read more..

  • Page - 241

    Table 11-1 Pixel Format Buffer Selection Mode API Double Buffer Single Buffer CGL kCGLPFADoubleBuffer, GL TRUE kCGLPFADoubleBuffer, GL FALSE AGL AGL DOUBLEBUFFER, GL TRUE AGL DOUBLEBUFFER, GL FALSE Cocoa NSOpenGLPFADoubleBuffer, YES NSOpenGLPFADoubleBuffer, NO GLUT GLUT DOUBLE GLUT SINGLE Further, if your application is vertical blank synchronized your frame rate will be quantized by the refresh rate of read more..

  • Page - 242

    Throughput Throughput is another metric of performance that is related to frame rate but is not dependent upon it. Throughput measures the data transfer rate that your application achieves for a particular form of data. It is limited by the bandwidth of the bus through which the data transfers. Some baseline transfer rates for the main memory to graphics card path were read more..

  • Page - 243

    The answer to each of these questions is “It depends.” But the important com- mon thread is that a copy of the data is made. In many cases, if it makes sense, multiple copies of the data are made. There may be a copy in the OpenGL frame- work, one in the driver, and one in VRAM. All told, that’s four potential copies of large data buffers. The moral to read more..

  • Page - 244

    such that the cost of handling the begin/end tokens in the OpenGL command stream is relatively high when compared to the few triangles drawn to amortize that cost. A simple improvement in efficiency for this example is to replace the primi- tive type GL TRIANGLES with the type GL TRIANGLE STRIP . This eliminates a great deal of the submission of redundant shared vertices. read more..

  • Page - 245

    glEnd(); glEndList(); // Now, as often as you wish, draw the list glCallList(listID); glFlush(); For static models, display lists yield an enormous performance gain because they effectively eliminate the transfer of data between the host CPU and the GPU. They also eliminate all of the internal copies and data management re- quired for immediate mode vertex submission. Their drawbacks read more..

  • Page - 246

    glBufferData(GL_ARRAY_BUFFER, VERTEX_CT, vertexBuffer, GL_STATIC_DRAW); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, (char *) NULL); ... // Now the VBO is initialized, when we’re ready to draw // Bind the VBO for drawing glBindBuffer(GL_ARRAY_BUFFER, bufID); // Draw triangle strip using ’n’ vertices from the VBO // starting at index 0 glDrawArrays(GL_TRIANGLE_STRIP, 0, n); read more..

  • Page - 247

    Apple’s Methods of Vertex Submission, Past and Present If you’re starting a new application, or if you’re porting a relatively modern and well-written OpenGL application, there’s a good chance that you can just learn the nuances of good VBO etiquette and forget about the now fairly complex history of submitting vertices using Apple’s OpenGL implementation. You may have read more..

  • Page - 248

    state such that it can be simply recalled when needed to draw various objects in a scene, as in Example 11-8. Example 11-8 Using Vertex Array Objects // Create and bind your VAO glGenVertexArraysAPPLE(1, &tortoiseVAO_ID); glBindVertexArrayAPPLE(tortoiseVAO_ID); // Set up tortoise pointers glVertexPointer(); glNormalPointer(); glTexCoordPointer(); // Do the same init sequence for the hare model read more..

  • Page - 249

    Example 11-9 Using Vertex Array Range // Standard vertex array setup glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, stride, vertexBuffer); // Tell OpenGL data is mostly static so hang on to it in VRAM glVertexArrayParameteriAPPLE( GL_VERTEX_ARRAY_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE ); // Set up the VAR glVertexArrayRangeApple(arrayLength, vertexBuffer); // Tell OpenGL the data has read more..

  • Page - 250

    for(i = 0; i < vtxCt; i += stripCt) glDrawArrays(GL_TRIANGLE_STRIP, i, stripCt); // Set a fence here so that when we modify the // data later, we can verify that drawing with this // data has completed. glSetFenceAPPLE(drawCompleteFence); } void modifyData() { glFinishFenceAPPLE(drawCompleteFence); // Modify all or some portion of the data knowing // that there are no pending drawing read more..

  • Page - 251

    #define VERTICES 1024 // Define number of bytes for vertex data in our // hypothetical model. // // GLint MODEL_BYTES = vertex_count * 3 (one for x, y, & z) * // sizeof(GLfloat); #define MODEL_BYTES (VERTICES*3* sizeof(GLfloat)); // Pointer to our vertex data buffer GLfloat *vertexData; // Drawing fence for coherency GLuint drawingFence1, drawingFence2; // Typical init routine for read more..

  • Page - 252

    void UpdateBuffer(GLuint fence, GLint first, GLint length, GLfloat *currentVertexBuffer) { int i; // Insure that we’re through drawing with the memory holding // the vertices we’re about to update. glFinishFenceAPPLE(fence); for(i = 0; i < length; i++) // Modify contents of currentVertexBuffer here // Mark our updated region as modified so OpenGL knows how to // establish coherency read more..

  • Page - 253

    This example shows a natural usage of the VAR extension. We’ve written pseu- docode for this example because, like many of the other snippets, it describes the way things used to be done on OS X. With the introduction of VBOs and the APPLE flush buffer range extension, this same strategy can be employed using the more modern and OpenGL standard VBO interface. Using VBOs read more..

  • Page - 254

    Again, this doubling-up strategy increases the asynchronicity between the CPU modifying vertex data and the GPU drawing it. We’ve prepared an extensive example that you can use to experiment with some of the different modalities of updating and drawing with VBOs in our source examples folder. Unlike most of the examples included with this book, the vertex submission example contains read more..

  • Page - 255

    Figure 11-1 Vertex Submission Example Application that works natively with the pixel format. The video acquisition of YCBCR- formatted data is a good example. Another is high-fidelity single-component pixel data used for medical imaging. In Mac OS X, there are about two dozen pixel types; more than a dozen pixel formats can be specified for OpenGL. Consider the architecture of read more..

  • Page - 256

    Depending on your application’s performance needs, this can be a very expen- sive operation indeed! Imagine that you’re uploading a stream of pixel data to the graphics card, but instead of free flowing at close to PCI-express limits be- tween system memory and graphics device, it stops to perform a format/type transformation on the way there. At best, you’ve introduced a read more..

  • Page - 257

    will very likely suffer simply because these states are rarely used and, therefore, are not represented in the silicon of the graphics hardware installed on the sys- tems. As a result, these stages take the pixel upload off the fast path and require modification by the CPU. Alignment Considerations It is quite important on any modern CPU architecture to pay attention to pixel read more..

  • Page - 258

    this non-aligned, ragged, 27-byte-aligned right side of each scanline of the im- age will require special (in not so politically correct terms, “slow”) handling. Textures More than 5400 valid combinations of texture formats, types, and internal for- mats can be specified via glTexImage() calls of OpenGL on the Mac OS. A great deal of engineering has been done to increase the read more..

  • Page - 259

    downside, texturing can aggravate the alignment problem when you are doing glTexSubImage() calls. By its very nature, glTexSubImage() replaces an arbitrary region of pixels within the texture. The curse word in the previous sentence is “arbitrary” when it comes to alignment concerns. In short, you should try to subtexture such that the replacement of texels falls on natural alignment read more..

  • Page - 260

    System Tools Shark Shark, formerly known as Shakiri, is a system performance characterization tool. Shark allows numerous types of statistical sampling of virtually anything running on your system. If your binaries have not had their symbols stripped away and your source files are available, Shark profiles can correlate perfor- mance sampling values at the source and assembly levels. read more..

  • Page - 261

    Quartz Debug Quartz Debug allows for configuration and debugging of settings for the Quartz window server. Some of the more interesting features you’ll want to check out are the Window List tool and the User Interface Resolution tool. The User Interface Resolution tool allows you to emulate displays having different resolutions. As resolution independence is a standard feature of read more..

  • Page - 262

    Figure 11-2 OpenGL Profiler Main Window with Launch Settings Open from the launchable list is done using the plus and minus icons. If you select the “Attach to application” option, the launchable application list will switch to a list of currently running processes that are candidates for being attached to. Now, let’s go through the Views menu in Profiler, which is where read more..

  • Page - 263

    Figure 11-3 OpenGL Profiler Breakpoints View The next most useful thing in the authors’ opinion is the ability to delimit frames of rendering with breakpoints. Most OpenGL applications follow a cycle in making GL state changes that starts at the beginning of a rendered frame and ends at the end of the rendered frame. Very often, all state changes that need to be evaluated read more..

  • Page - 264

    frame. You may be surprised at how often you see state changes that you hadn’t anticipated. Now we leave the raw utility class of operations in the Breakpoints view and get to the “it’s just plain cool” functionality. Specifically, the Breakpoints view allows you to execute a script before or after each invocation of a specified GL function. Generally speaking, there’s read more..

  • Page - 265

    Figure 11-4 OpenGL Profiler Statistics View worth of tracing data. The key difference regarding what the Trace view can pro- vide you relative to what the Statistics view can deliver is the order of OpenGL calls, which, of course, can make all the difference when it comes to performance tuning. Figure 11-5 OpenGL Profiler Trace View 232 Chapter 11: Performance read more..

  • Page - 266

    Resources View The Resources view allows inspection of textures and vertex or fragment pro- grams that have been submitted to the GL API (Figure 11-6). The ability to in- spect these resources can be immensely valuable in debugging. If, for instance, a texture image has been procedurally generated and has never been viewed prior to being applied as a texture, you can evaluate read more..

  • Page - 267

    Figure 11-7 OpenGL Pixel Format View Pixel Format View The Pixel Format view is a nice time saver. It shows a comprehensive list of pixel format attributes for each context of the currently attached or launched application (Figure 11-7). Buffer View The Buffer view allows inspection of the various planes that constitute a GL framebuffer (Figure 11-8). At present these include the read more..

  • Page - 268

    Figure 11-8 OpenGL Profiler Buffer View OpenGL Driver Monitor The OpenGL Driver Monitor is used to monitor various parameters of the graphics devices available on your Mac (Figure 11-10). To use this tool, first choose a driver from the Monitors menu, Driver Monitors submenu. Next, click Figure 11-9 OpenGL Profiler Scripts View Graphics Tools 235 read more..

  • Page - 269

    Figure 11-10 OpenGL Driver Monitor the “Parameters” button at the bottom-right corner of the main window. You’ll see a long list of anything you could want to know about data traffic, resource allocations, and various other parameters of the driver. One parameter of partic- ular interest is “CPU Wait for GPU,” which tells you whether your application is GPU bound and read more..

  • Page - 270

    Figure 11-11 Pixie Putting It All Together In this section, the rubber meets the road. We’re going to guide you through a performance-tuning example that incorporates many of the tuning techniques introduced in this chapter. The example is called please tune me , and you will find it in the examples folder that accompanies this book. In this folder are six source files, read more..

  • Page - 271

    triangle to the screen, we’re hoping to guide you through an environment that is a closer match to real-world performance tuning. Please Tune Me goes heavy on texturing and geometry to give it some real- world weight. Here’s some pseudocode describing this application: • Create a color gradient texture for the textured quad mesh referenced below. • Clear the entire read more..

  • Page - 272

    Figure 11-12 Performance-Tuning Exercise Application: Please Tune Me the graphics hardware. In ptm1.c ’s case, this texture type is GL UNSIGNED SHORT 4 4 4 4 . Often OpenGL programmers will use packed types such as this because they don’t require the fidelity of 8 bits per component and wish to save space. However, because this type is not native to the hard- ware, a read more..

  • Page - 273

    Figure 11-14 ptm2 OpenGL Statistics Please Tune Me 2 Moving on to ptm2.c , we’ve remedied the texture type problem by replacing GL UNSIGNED SHORT 4 4 4 4 with GL UNSIGNED BYTE . Again, we have twice the storage requirements but the type is hardware native. Running ptm2 on our test system, we see more than one frame per second: Not earth-shattering, but a 200 percent read more..

  • Page - 274

    Figure 11-15 ptm3 OpenGL Statistics our list now: glVertex2f() accounts for more than 55 percent of the time spent in OpenGL. Perhaps we can apply a retained mode technique for the glVertex2f() problem as well. Please Tune Me 4 Please Tune Me 4 takes a huge stride forward relative to ptm3 . By encapsulat- ing the huge number of mesh vertices in a display list, we’ve read more..

  • Page - 275

    Figure 11-16 ptm4 OpenGL Statistics retained mode containers of pixel or texture data, which can then be sourced for rendering by texturing calls or glDrawPixels() . In this case we’ve established the PBO as a container for reading the contents of the left side of the application window for later use as a texture on the teapot. Because this is a VRAM-managed resource, the read more..

  • Page - 276

    Figure 11-17 ptm5 OpenGL Statistics Please Tune Me 6 The final installment in our quest for ultimate performance is ptm6 , which in- volves an architectural change. Sticking with the glReadPixels() track and considering some of the earlier performance tips, is there any way we can avoid reading this data back and touching it with the CPU altogether? The answer is yes, and a read more..

  • Page - 277

    changes, using retained mode rendering, and including other OpenGL “best practices” are platform-agnostic. To these known axioms, the Mac OS X OpenGL implementation is an industry leader with its plethora of asynchronous data submission interfaces and multithreaded OpenGL engine. Adding these capa- bilities to the great OpenGL diagnostic, performance, and debugging tools on OS X makes read more..

  • Page - 278

    Chapter 12 Mac Platform Compatibility Mac OS Versions Mac OS X has evolved significantly over its life span, but OS X has featured OpenGL as a key piece of its foundation since day 1. As Mac OS X evolved, the operating system itself has assumed increasingly more heavy usage of the OpenGL layer, and the performance, features, and quality of the graphics sub- system have read more..

  • Page - 279

    versions. They served their purpose well at the time and we appreciate their efforts, but time marches on, and so do we. 10.2 (Jaguar) Jaguar was released in August 2002 and proved to be a really solid, fast, and finally almost complete version of Mac OS X. In the span of a little more than a year and a half, Mac OS X had improved from a fast but new operating read more..

  • Page - 280

    acceleration of all elements of the UI through a technology known as Quartz 2D Extreme. Aside from the obvious performance benefits the later trend can provide to user experiences through the windowing system, it raises an inter- esting point for your application to consider: You are not alone. What we mean by this statement is that your application and the window system read more..

  • Page - 281

    chip—the possibility exists that an application may be running on either chip. Developers must account for this possibility because it affects many things, among them endianness, vector code acceleration, and inline-assembly tweaks. Primarily, however, it impacts performance. 10.5 and Beyond Apple has announced its next revision in the Mac OS X sequence, 10.5, also known as Leopard. We read more..

  • Page - 282

    Table 12-1 glGetString Tokens Token Information GL VENDOR The company responsible for this OpenGL implementation. Technically, despite what this string reports (frequently ATI or NVIDIA), Apple maintains the OpenGL driver and is the key contact for any questions or problems. This string can provide a useful hint in determining the underlying hardware used by this context. GL RENDERER A read more..

  • Page - 283

    lot of aspects of your running Mac system, but we’ll use it for just the version number here. That Carbon call is Gestalt . It has been said that brevity is the soul of wit, so we may therefore assume that the documentation of what the Gestalt method does is among the wittiest on the Mac. The documentation pages say that Gestalt “obtains information about the operating read more..

  • Page - 284

    its overall runtime goodness) for inquiring as to whether a particular object or class responds to a particular method. These respondsToSelector and instancesRespondToSelector methods are thoroughly documented within Apple’s developer documentation. Summary In this chapter we saw some of the differences between the various versions of Mac OS X, and we learned how to identify both the read more..

  • Page - 285

    This page intentionally left blank read more..

  • Page - 286

    Chapter 13 OpenGL Extensions Overview In this chapter we’ll discuss a design feature of OpenGL known as OpenGL extensions. We’ll describe how these extensions work, how to discover which ones are available, and how to determine exactly how extensions operate. We’ll also describe a few libraries for working with extensions that make your life as a developer easier. But first, read more..

  • Page - 287

    and a compatibility path with older code. Thanks to a lot of really good up-front design in the OpenGL specification, OpenGL doesn’t cause a major compatibil- ity headache for the developer with each version1 and, in fact, it handles growth and change in a very elegant and evolutionary fashion. The OpenGL mecha- nism for adding new features and evolving the API is known read more..

  • Page - 288

    takes once-bleeding-edge features and, over time, migrates them so that they become part of the OpenGL standard. Thus your application that uses extensions to OpenGL today may in the future be able to satisfy its needs us- ing a particular version of core OpenGL. But let’s back up a step and describe how the core OpenGL specification evolves. There are many paths to adding read more..

  • Page - 289

    for its future. Even when an extension grows up, moving from an EXT to an ARB (sometimes from vendor straight to ARB) and finally into the specification itself, the older ways of identifying it will still exist. Specifically, the OpenGL specification says this on extension promotion: ARB extensions can be promoted to required core features in later revisions of OpenGL. When read more..

  • Page - 290

    Identification, Selection, Query, and Usage Deciding which extension to use can warrant entire books by itself. The sheer number and similarity of the many extensions in existence makes this a daunt- ing process. In this section we’ll explain how you determine which extensions are available and how you decide which one is preferred in your particular case. Though there’s no read more..

  • Page - 291

    these features on only some platforms, and in extension form. In this case, we recommend you choose extensions based on the OpenGL Architecture Review Board extension evolution process. By this, we mean that the OpenGL ARB extension process defines the evolution of an extension, from concept to core OpenGL. To be explicit, in a cross-platform or even a cross-Mac application, the read more..

  • Page - 292

    Thus our alternative path will be OpenGL 1.3 plus the required extensions for shading, GL ARB shading language 100 , GL ARB program objects , GL ARB vertex shader , and GL ARB fragment shader . For simplicity, we will handle only this alternative rendering path in our appli- cation. Handling OpenGL 2.0 and OpenGL 1.3 requires a fair bit of API man- agement, as the entry read more..

  • Page - 293

    Table 13-1 Preprocessor Tokens for Extension Usage Path OpenGL Token Extension Token Preferred GL VERSION 2 0 None Alternative GL VERSION 1 3 GL ARB shading language 100 , GL ARB program objects , GL ARB vertex shader , GL ARB fragment shader Fallback Any None But in code, how do we wrap things? Well, anywhere code uses either tokens or API entry points specified by these read more..

  • Page - 294

    Finally, an else clause performs our preprocessing checks. We took this tack because if we fail to compile this code, no shader code will ever be executed—even on platforms that support it! Our preprocessing checks really just validate that we know how to build our application so that it can move on to the next step—runtime checking for these extensions, which we look at read more..

  • Page - 295

    glLinkProgramARB( programObject ); glUseProgramObjectARB( programObject ); #else #error "NO shading will be available." #endif } // add a timer to oscillate the modelview NSTimeInterval ti = .1; [ NSTimer scheduledTimerWithTimeInterval: ti target: self selector: @selector(angleUpdate:) userInfo: nil repeats: YES ]; } Utilization and Binding An astute reader will notice that in the prior section read more..

  • Page - 296

    Figure 13-1 Shader Extension Application Results if Successful (Texture cour- tesy of NASA’s Earth Observatory.) extensions implies a combination of tokens, API entry points, and functionality.3 This code first builds a list of OpenGL extensions, queried by the call glGet- String( GL EXTENSIONS ) , and then wrangles this list into a dictionary, as shown in Example 13-4. We simply read more..

  • Page - 297

    Figure 13-2 Shader Extension Application Results if Unsuccessful float versionfloat = [ self openGLVersionNumber ]; if ( versionfloat >= 1.21 ) { NSDictionary *extdict = createExtensionDictionary(); BOOL has_vs = [ extdict objectForKey: @"GL_ARB_vertex_shader" ] != nil; BOOL has_fs = [ extdict objectForKey: @"GL_ARB_fragment_shader" ] != nil; BOOL has_so = [ extdict objectForKey: read more..

  • Page - 298

    One final note about extensions that export API entries: What happens at run- time? We’ve seen how we check for the validity of a particular extension at com- pile, link, and runtimes, but where are the symbols defined on the platform on which we’re now running? What guarantees do we have about symbol defini- tions being valid? On the Mac, there’s an implicit read more..

  • Page - 299

    The second note on these calls relates to the symbol names. Function names within libraries are changed (or, in compiler terms, mangled) into another form stored within those libraries. The mangling scheme is usually something you can learn about and figure out, but the dl* calls are designed to work with the human-readable versions of these names. For example, in one cur- rent read more..

  • Page - 300

    - (BOOL) resolveShaderSymbols; - (BOOL) hasExtension: (NSString*) ext inExtensions: (NSArray*) exts; - (BOOL) hasShaderExtensions; - (float) openGLVersionNumber; - (void) angleUpdate: (NSTimer*) tt; - (void) reshape; @end Example 13-6 Opening a Segment for Symbol Lookup void * resolveSymbol( char * symname ) { void *lib = dlopen( (const char *)0L, RTLD_LAZY | RTLD_GLOBAL ); void *sym = dlsym( read more..

  • Page - 301

    glLoadIdentity(); glOrtho(-1,1,-1,1,-1,100); // do we have shading extensions? if( ( TRUE == [ self hasShaderExtensions])&& ( TRUE == [ self resolveShaderSymbols])) { // load shader from disk (bundle) NSBundle *res = [ NSBundle mainBundle ]; NSString *fragfile = [ res pathForResource:@"test" ofType:@"frag" ]; NSString *vertfile = [ res pathForResource:@"test" read more..

  • Page - 302

    userInfo: nil repeats: YES ]; } We’ve now seen how to determine which extensions to use; when they’re ap- propriate; when you should use the baseline OpenGL versus extensions; which checks to perform for compile-, link-, and run-time correctness; and how to dy- namically bind symbols. In essence, we’ve taken the complete tour of OpenGL extension selection and usage and shown read more..

  • Page - 303

    feature management toolkits tend to perform the same basic functions, so at the time of this writing, GLEW will be our preferred toolkit due to its comprehen- sive nature and modernity. Now, if you’re roped into thinking, “Man, ‘insert- extension-management-API-name-here’ stinks (GLEW, for example); I guess I’ll just have to rewrite my own toolkit from the ground up,” we read more..

  • Page - 304

    To use GLEW in an application, there are several ways of accomplishing the same tasks. We’ll look at one approach that’s a close analog of the way we pre- viously investigated shader support in an earlier example. The basic process is this: 1. Initialize the library: glewInit() . 2. Query for a particular extension: if(GL TRUE == GL ARB shader objects) . 3. Use that read more..

  • Page - 305

    // do we have shading extensions? NSLog( @"Has OpenGL Shader: %d\n", [ self hasShaderExtensions ] ); if( TRUE == [ self hasShaderExtensions ] ) { NSBundle *res = [ NSBundle mainBundle ]; NSString *fragsource = [ NSString stringWithContentsOfFile: [ res pathForResource:@"test" ofType:@"frag" ] ]; NSString *vertsource = [ NSString stringWithContentsOfFile: [ res read more..

  • Page - 306

    The method hasShaderExtensions doesn’t really do anything conceptually different from the action of our prior example, but the methodology is slightly different. We first check our version number, but we don’t create an extension dictionary; GLEW has already done that for us, and we can directly use the code it provides. Thus we can directly check for the GLEW analog read more..

  • Page - 307

    If the complexity of GLEW isn’t something you need, and writing GL-level man- agement isn’t your bag either, these tools may be just what you’re looking for. In Example 13-12, we present C code for checking the OpenGL version number, as a component of our example shading extension tests adapted for GLUT. In Example 13-13, we reimplement our Cocoa shader test using the read more..

  • Page - 308

    end up linking in GLUT as an additional framework. Your memory footprint may increase, as might your load times. The dlopen/dlsym route is prefer- able, given that Apple probably does something like this internally in its imple- mentation of this function. Although various implementations of GLUT exist in source form, all of them indicate that glutGetProcAddress works only for Windows read more..

  • Page - 309

    This page intentionally left blank read more..

  • Page - 310

    Appendix A X11 APIs for OpenGL Configuration X11 (X Window System, Version 11) is a network-transparent window system that is widely used on Unix-based workstations. It is a client/server-based win- dowing environment where a single server services multiple “client” windows of applications written for X11. The first windowing system on which OpenGL was supported was X11. This read more..

  • Page - 311

    • 256MB RAM • 200MB of available hard disk space • A built-in display or a display connected to an Apple-supplied video card When the installation is complete, X11 is launched using the /Applications/ Utilities/ application. In the Application menu, you’ll find the fa- miliar “xterm” application. Xterm will set up the X11 execution environment for you and makes it read more..

  • Page - 312

    g++ -g -Wall -I/usr/OpenMotif/include \ -I/usr/X11R6/include -c $< -o $@ # Link oglMotif: $(CXXOBJS) g++ -g -o $@ $(CXXOBJS) -L/usr/X11R6/lib \ -L/usr/OpenMotif/lib -lGL -lGLw -lXm -lXt -lX11 clean: rm -f *.o oglMotif Note the -I and -L options of the compile and link lines, respectively. They refer to the default installation directories for both X11 and OpenMotif. Also note the lack read more..

  • Page - 313

    This page intentionally left blank read more..

  • Page - 314

    Appendix B Glossary API Acronym for application programming interface. An API is a set of func- tions, classes, and tokens used to define a particular set of software tools. OpenGL is an API for graphics. ARB See OpenGL Architecture Review Board. Context sharing Reusing resources from one OpenGL context in another OpenGL context. Deferred validation The caching or postponement of data read more..

  • Page - 315

    Immediate mode rendering Rendering with objects passed from the host to the GPU on a per-frame basis. Compared to retained mode rendering, imme- diate mode rendering implies more function-calling overhead in each render- ing frame in addition to more bus bandwidth used with each frame. OpenGL Architecture Review Board The standards body that defines which features, functionality, and read more..

  • Page - 316

    Appendix C The Cocoa API for OpenGL Configuration in Leopard, Mac OS X 10.5 Cocoa, also known as AppKit, is the Objective-C API for writing modern Mac OS X applications. Cocoa provides a high-level, object-oriented set of classes and interfaces for the OpenGL subsystem and for user–interface interaction. Cocoa is the modern successor to the NextStep API from NeXT Computer; the read more..

  • Page - 317

    CoreGraphics CGL NSGL AGL Figure C-1 AppKit API and Framework in Overall OpenGL Infrastructure on the Mac Overview The AppKit OpenGL API is part of the overall Apple OpenGL infrastructure. It constitutes a layer above CGL but also has the ability to reach down into both CGL and lower layers. Figure C-1 shows where the AppKit (also known as Cocoa or NSGL) API and framework read more..

  • Page - 318

    Figure C-2 Window and NIB Ready to be Edited in Leopard Interface Builder. In the MainMenu.nib window, double-click on the Window icon, and you’ll see the window that will be your application window open. Position and scale it as you like, and you should end up with something like Figure C-2 when finished. Next bring up the Library and Inspector tools, both available in the read more..

  • Page - 319

    Figure C-3 Selection, Layout, and Specialization of a CustomView in Interface Builder our behalf. Drag that out and into the MainMenu window. Select the blue cube, and look in the Inspector window. Type in the Class entry the name of our custom view, MyOpenGLView . This creates a custom object, of our custom view type in the NIB, and will recreate that when the NIB gets read more..

  • Page - 320

    Figure C-4 Create and Bind an Instance of our CustomView Figure C-5 Custom View Derivation and Project Files in XCode 3.0 NSOpenGLView 287 read more..

  • Page - 321

    generic NSView , which allows us a bit more flexibility. For now, switch back to XCode and we’ll dig into the code. In XCode, open the file MyOpenGLView.m . We’ll now begin adding methods to handle key elements of the OpenGL render cycle. We start by adding a method to select pixel formats. This code performs pixel format selection in three steps: 1. A structure is read more..

  • Page - 322

    NSOpenGLPixelFormat* pixelformat = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes: (NSOpenGLPixelFormatAttribute*) attributes ]; if ( pixelformat == nil ) { NSLog( @"No valid OpenGL pixel format" ); NSLog( @"matches the attributes specified" ); // at this point, we’d want to try different sets of // pixelformat attributes until we got a match, or decide // we couldn’t read more..

  • Page - 323

    Table C-3 Common Pixel Format Qualifiers for Use with NSOpenGLPixelFormat Token Description NSOpenGLPFAAllRenderers Look in entire set of renderers to find a match. Type: Boolean YES: Search entire set of available renderers, including those that are potentially non-OpenGL compliant. Default: YES Policy: Any NSOpenGLPFADoubleBuffer Double buffer requirements. Type: Boolean YES: Search only for a read more..

  • Page - 324

    Token Description NSOpenGLPFADepthSize Unsigned integer: The value specified is the number of depth buffer bits required. Default: If no value is specified, pixel formats discovered may or may not have a depth buffer. Selection policy: Pixel formats that most closely match this size are preferred. NSOpenGLPFAStencilSize Unsigned integer: The value specified is the number of stencil planes read more..

  • Page - 325

    Table C-3 Common Pixel Format Qualifiers for Use with NSOpenGLPixelFormat (Continued) Token Description NSOpenGLPFAColorFloat YES: Consider only renderers capable of using floating-point pixels. NSOpenGLPFAColorSize should also be set to 64 or 128 for half- or full-precision floating-point pixels (Mac OS 10.4). NSOpenGLPFAMultisample YES: Consider only renderers capable of using supersample anti-aliasing. read more..

  • Page - 326

    In particular, pixel format selection can have a profound impact on both the per- formance of and the video memory usage by your application. Keep in mind that choosing pixel formats with more capabilities may lead to slower perfor- mance than choosing pixel formats with fewer options and smaller buffers. For example, if you have a choice between a pixel format with a color read more..

  • Page - 327

    Figure C-6 Teapot Rendered with NSOpenGLView with Subclass glLoadIdentity(); glTranslatef( 0, 0, -1 ); GLfloat green[4]={0,1,0,0}; glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green ); glutSolidTeapot( .5 ); [ [ self openGLContext ] flushBuffer ]; } @end If you see a teapot—success! In this section, we’ve explored one of the ways to configure a Cocoa OpenGL Surface, delved into the read more..

  • Page - 328

    views of the same data. The technique we’ll demonstrate here allows you to share data between these multiple views. But whatever your needs, this explo- ration will show you how to attach a context to an NSView , getting at the guts of how contexts are created, and then do some rendering. If you need precise management of a context, this is the way to do it in a read more..

  • Page - 329

    With that configuration out of the way, we move straight into the code phase. Save your MainMenu.nib , and switch to XCode. As before with the NSOpenGLView -derived project, we’ll do many of the same things, includ- ing creating a pixel format and creating a subclassed version of drawRect . We’ll also mimic some of the infrastructure automatically provided in NSOpenGLView , so read more..

  • Page - 330

    { NSLog( @"myView::initWithFrame" ); if ((self = [super initWithFrame:frameRect]) != nil) { GLuint attributes[] = { NSOpenGLPFAWindow, NSOpenGLPFAAccelerated, NSOpenGLPFADoubleBuffer, NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, NSOpenGLPFADepthSize, 24, NSOpenGLPFAMinimumPolicy, // select a pixelformat which meets or // exceeds these requirements 0 }; _pixelformat=[[ NSOpenGLPixelFormat alloc ] read more..

  • Page - 331

    2 -proceed without a shared context */ } } return( _context ); } - (void) lockFocus { NSLog( @"myView::lockFocus" ); // ensure we are ready to draw [ super lockFocus ]; // get our context NSOpenGLContext *cxt = [ self openGLContext ]; // ensure we are pointing to ourself as the Drawable if ( [ cxt view ] != self ) { [ cxt setView: self ]; } // make us the read more..

  • Page - 332

    [ [ self openGLContext ] flushBuffer ]; } @end In our MyView.m file, we start by looking at our initWithFrame overloaded method. This method is called when our object is getting constructed, with the desired layout of this particular view. As with our MyNSOpenGLView class, this method is where we set up our pixel format and prepare the rest of our class for subsequent use. In read more..

  • Page - 333

    Put more succinctly, you want your context to be active. In context parlance, this is known as “making your context current.” lockFocus is the place in the Cocoa framework where your view is made current, and where you can then make your context current. If we now look at our code, we can see that we need to overload this method to do the usual lockFocus work when read more..

  • Page - 334

    texture path here. The Red Book [22] has lots of details on the imaging pipeline, if you’d like more information on that. Any pixel data that you might want to render in an OpenGL scene, you can handle through textures. To do so, you would download that image as a texture using glTexImage[123]D calls. Let’s provide an overview of this process and then translate it into read more..

  • Page - 335

    So we’ve covered the how and why of sharing a context, but what, exactly, is shared when context sharing is enabled? Interestingly enough, most OpenGL objects are shared, but the overall context state is not. That’s not entirely intu- itive, but it correlates well with what people usually want to do. You save valu- able card memory by reusing heavyweight objects in read more..

  • Page - 336

    Figure C-7 Two Views, Contexts Shared Example C-5 Singleton Class Declaration for Managing a Shared Context #import <Cocoa/Cocoa.h> @interface SharedContext : NSObject { NSOpenGLPixelFormat* _pixelformat; NSOpenGLContext * _context; } - (NSOpenGLPixelFormat *) pixelFormat; - (NSOpenGLContext *) context; + (SharedContext *) instance; @end Additional Topics 303 read more..

  • Page - 337

    Figure C-8 Final Two Window XCode Contents Figure C-9 Visible at Launch Enabled 304 Appendix C: The Cocoa API for OpenGL Configuration in Leopard read more..

  • Page - 338

    Example C-6 Singleton Class Implementation for Managing a Shared Context #import <AppKit/NSOpenGL.h> #import <OpenGL/gl.h> #import "SharedContext.h" SharedContext *_sharedContext = nil; @implementation SharedContext - (id) init { if (self = [super init]) { _pixelformat = nil; _context = nil; GLuint attributes[] = { NSOpenGLPFAWindow, // windowed pixelformats NSOpenGLPFAAccelerated, // hw-accel read more..

  • Page - 339

    } - (NSOpenGLContext *) context { return( _context ); } + (SharedContext *) instance { if ( _sharedContext == nil ) { _sharedContext=[[ SharedContext alloc ] init ]; } return _sharedContext; } @end If you’re familiar with the singleton pattern, the instance method and idea should be familiar to you. If not, consult the classic Design Patterns book by the notorious Gang of Four [16]. read more..

  • Page - 340

    NSLog( @"No valid OpenGL pixel format" \ "matching attributes specified" ); // at this point, we’d want to try different // sets of pixelformat attributes until we // got a match, or decided we couldn’t create // a proper working environment for our // application } } // init the context for later construction _context = nil; return self; } - (NSOpenGLContext *) read more..

  • Page - 341

    Figure C-10 Context Sharing: Two Windows Demonstrating Common Shared Data and Unshared (Clear Color) Context Data last change—specifically, change the clear color in one of your custom View drawRect methods. If everything works as planned, your application should produce results like these shown in Figure C-10. Remember that the OS X OpenGL implementation follows the conventions read more..

  • Page - 342

    examples include QuickTime full-screen movie presentation, iPhoto/Finder slideshows, DVD playback, and FrontRow set-top display. The most common example of this technique in user software is found in games, usually where a game takes over the display for a complete and unobstructed experience of slay- ing dragons, flying through canyons at Mach 0.8, or conquering the galaxy. A rule of read more..

  • Page - 343

    Example C-8 Capturing and Releasing the Display /*! Captures all displays, returning true/false for success/failure. */ bool capturedDisplaysLoop() { bool error = false; CGDisplayErr err = CGCaptureAllDisplays(); if (err != CGDisplayNoErr) { // failure - maybe another application is already // fullscreen error = true; } else { // your code here: open fullscreen window // your code here: event read more..

  • Page - 344

    Example C-9 Custom Controller Event-Handling Loop in a Full-Screen Context stayInFullScreenMode = YES; while ( stayInFullScreenMode ) { NSAutoreleasePool *pool = [ [ NSAutoreleasePool alloc ] init ]; // Check for and process input events. NSEvent *event; while ( event = [ NSApp nextEventMatchingMask: NSAnyEventMask untilDate: [ NSDate distantPast ] inMode: NSDefaultRunLoopMode dequeue: YES ] ) { read more..

  • Page - 345

    whatever your application requires when an event occurs. This includes mouse handling, key handling, and external device (e.g., joystick, tablet) handling. Example C-9 does nothing more than simply handle the Escape key, quit the render loop, and return to windowed mode. The example deals specifically with key events, handling the Escape key by quitting full-screen mode, and calling read more..

  • Page - 346

    The following sections describe the various techniques available on the Mac for alternative destination rendering and subsequent reuse of those data. We’ll pri- oritize these strategies in terms of their modernity, encouraging you to use the most modern of these, framebuffer objects, whenever possible. For a variety of reasons (not least of which are simplicity and performance), read more..

  • Page - 347

    GLARBrendertexture , by changing color attachments, a single framebuffer object can facilitate rendering to an unlimited number of texture objects. We believe that this extension is the best way to render to texture and authori- tatively settles the question of what to use when performing a render-to-texture operation. Without further ado, let’s walk through how to use FBOs for read more..

  • Page - 348

    Example C-11 OpenGL Setup for FBO Rendering - (void) prepareOpenGL { glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho(-1,1,-1,1,-1,100); // enable, generate, and bind our texture objects glEnable( GL_TEXTURE_2D ); glGenTextures( (GLsizei) 1, &textureID ); glBindTexture( GL_TEXTURE_2D, textureID ); const unsigned int texdim = 64; const unsigned int nbytes = 3; char data[ texdim * texdim * read more..

  • Page - 349

    Example C-12 Cocoa drawRect Routine for FBOs - (void) drawRect: (NSRect) rect { // render to offscreen glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboID ); [ self drawIntermediateContents ]; glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // render to final [ self drawFinalContents ]; // complete rendering & swap glFlush(); [ [ self openGLContext ] flushBuffer ]; } Finally, for interest, we present read more..

  • Page - 350

    glEnable( GL_TEXTURE_2D ); glBegin( GL_QUADS ); float ww = .9; float hh = .9; float zz = 0.0; glTexCoord2f( 0, 0 ); glVertex3f( -ww, -hh, zz ); glTexCoord2f( 1, 0 ); glVertex3f( ww, -hh, zz ); glTexCoord2f( 1, 1 ); glVertex3f( ww, hh, zz ); glTexCoord2f( 0, 1 ); glVertex3f( -ww, hh, zz ); glEnd(); } So what does our example do? Our goal is to render a textured quad to read more..

  • Page - 351

    You can do a lot more with FBOs, including capturing other rendering results such as depth, stencil, and other render targets, but this kind of advanced usage is beyond the scope of this book. We refer you to the OpenGL framebuffer object extension for complete details. Before we leave the topic of FBOs, we’d like to point out a few more reasons why FBOs are superior read more..

  • Page - 352

    Example C-14 Custom View Header for Copy-to-Texture Example Code #import <AppKit/NSOpenGL.h> #import <Cocoa/Cocoa.h> @interface MyOpenGLView : NSOpenGLView { GLuint textureID; float time; float angle; } - (void) angleUpdate: (NSTimer*) tt; - (void) reshape; @end Because we’re only going to render and copy into a texture, that’s the extent of the information we need to keep track of read more..

  • Page - 353

    // add a timer to oscillate the modelview NSTimeInterval ti = .1; [ NSTimer scheduledTimerWithTimeInterval: ti target: self selector: @selector(angleUpdate:) userInfo: nil repeats: YES ]; } As before, our main drawRect routine does the bulk of the work—but here is where the code differs from the FBO version. Let’s look at it now in Example C-16 and talk about the differences and read more..

  • Page - 354

    potentially might not support a real off-screen technique like FBO, so a tech- nique like render-to-texture may be required. And that brings us to the final point: This technique is window-dependent. You’ll notice that we’re copying only a fixed area of pixels from within our drawing surface in our example. If we wanted to capture the entire area, we’d have to monitor read more..

  • Page - 355

    If you’ve got older code that uses one of these approaches, a move to FBOs will likely both simplify and accelerate your code. Take the leap. Summary In this chapter, we explored how to create and configure Cocoa-based OpenGL rendering areas for on-screen windows and for various intermediate render tar- gets. We saw how to create custom pixel formats, examined some of the read more..

  • Page - 356

    Appendix D Bibliography [1] The OpenGL Architecture Review Board. OpenGL 2.0 specification. glspec20.pdf . [2] The OpenGL Architecture Review Board. OpenGL website. . [3] Apple Computer. About this Mac build information. . [4] Apple Computer. Apple developer website. . read more..

  • Page - 357

    [10] Apple Computer. Core video and QuickTime with OpenGL. index.html . [11] Apple Computer. Mac OS: Versions and builds since 1998. . [12] Apple Computer. Quick Start guide for AltiVec. . [13] Apple Computer. SSE performance programming. read more..

  • Page - 358

    Index Note: Information presented in tables and figures is denoted by t and f respectively. A Activity Monitor, 227 Advanced Graphics Port, 29, 30t AGL. see Apple OpenGL AGL ACCELERATED, 99t AGL ACCUM ALPHA SIZE, 97t AGL ACCUM BLUE SIZE, 97t AGL ACCUM GREEN SIZE, 97t AGL ACCUM RED SIZE, 96t AGL ALL RENDERERS, 95t AGL ALPHA SIZE, 96t AGL AUX BUFFERS, 96t AGL AUX DEPTH STENCIL, read more..

  • Page - 359

    AppKit, 16, 16f, 20, 122–33, 123f, 124f, 125f, 126f Apple Fence, 216–17 Apple Float Renderer, 13 Apple Generic Renderer, 13 Apple OpenGL, 16, 16f, 47 alternative rendering destinations in, 109–13 context sharing in, 107–9 framebuffer objects in, 117–19 full-screen application in, 91–101 pbuffers in, 110–13, 110t, 113f, 208t renderers in, 104–7, 107t software layering in, 90–91, read more..

  • Page - 360

    data parallel computation, 42 debugging, OpenGL, 39–41 dependency layering, 50, 50f depth textures, 10t development, history of Mac, 2–3 display capture, 149–51, 309–10 display IDs, 70–71 display masks, 20, 71 display release, 150 displays, 26–27 dl* calls, 265–66 dlopen, 265–66 dlsym, 265–66 double-buffered drawables, 77–78 downloadImageAsTexture, 188–89 drawables, 77–86 drawRect, read more..

  • Page - 361

    GPU. see graphics processing unit (GPU) graphics bus, 29–30, 30t graphics device support, 7 graphics processing unit (GPU) bandwidth limits with CPU, 25 idle time minimization, 204–7 increasing role of, 23 information lookup, 34 transistors in, 23 graphics tools, 228–36, 229f, 230f, 232f, 233f, 234f, 235f, 236f, 237f H hardware and data flow, 24–32 image download to, 180–82 on Mac read more..

  • Page - 362

    NSOpenGLView, 122–33, 123f, 124f, 125f, 126f, 284–93 NSSlider, 221 NSView, 133–40, 134f, 135f, 294–300 O object-oriented programming, and state management, 197–98 Objective-C, 89, 121 off-screen drawables, 82 off-screen rendering, 161–62, 321–22 off-screen surfaces, 109–10 OpenGL advantages of, 3–4 as specification document, 8 debugging, 39–41 feature support, 14–15 graphics tools, 228–36, read more..

  • Page - 363

    renderers, (continued ) obtaining information on, 68–76 selection in CGL, 56f, 61–63 switching between, 19–21 rendering, retained vs. immediate mode, 198–200 rendering destinations, alternative, 152–62 Resources view, 233, 233f retained mode rendering, 198–200 S Scripts view, 234, 235f secondary color, 10t shader instruction limits, 201 shader performance, 226 shader use, 200–201 shadow read more..

  • Page - 364

    OpenGL® Titles from Addison-Wesley OpenGL® Programming Guide, Sixth Edition The Offi cial Guide to Learning OpenGL® Version 2.1 OpenGL Architecture Review Board, Dave Shreiner, Mason Woo, Jackie Neider, and Tom Davis 0-321-48100-3 OpenGL® Programming Guide, Sixth Edition, provides defi nitive, comprehensive information on OpenGL and the OpenGL Utility Library. This sixth read more..

  • Page - 365

    Available wherever technical books are sold. For more information, including free sample chapters, go to OpenGL® SuperBible, Fourth Edition Comprehensive Tutorial and Reference Richard S. Wright Jr., Benjamin Lipchak, and Nicholas Haemel 0-321-49882-8 OpenGL® SuperBible, Fourth Edition, offers compre- hensive coverage of applying and using OpenGL in your day-to-day work. read more..

Write Your Review