Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2000-186
$eventId
ID of event: wwdc2000
$eventContentId
ID of session without event part: 186
$eventShortId
Shortened ID of event: wwdc00
$year
Year of session: 2000
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC00 • Session 186

OpenGL: A Technical Introduction

Digital Media • 1:02:52

This session focuses on the implementation of OpenGL for Mac OS. We give developers the knowledge required to develop OpenGL applications quickly on the Macintosh. Topics include the Macintosh OpenGL architecture, integration, and texture management.

Speaker: Geoff Stahl

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

I'll be talking today about OpenGL. I'll be doing an introduction to that and talking about how you can get started in OpenGL and exactly what Apple's OpenGL implementation, how it's made up. First of all, this is going to be a high-level overview of OpenGL. We're going to talk about a little bit of Apple's implementation and the setup. We're going to introduce OpenGL and talk about how that works. And then we're going to discuss Apple's implementation and give a little bit of how-to to get you going to lead into the next session.

First we'll talk about what is OpenGL, exactly how does it fit in, what does it do, and for some people who've kind of heard OpenGL term bounced around a lot. We've talked about it, we've said this is a great thing, but how is it a great thing for you? What can you do with it? And then we'll talk about our implementation details, we'll talk about using OpenGL, and we'll give you some references to get started and to get you on your way that will give you some really good source code and some documentation for it.

First, OpenGL really is just a software interface for graphics hardware. It drills down and allows you to really get at the meat of the hardware. And with all the research we're doing these days in the 3D hardware that companies are doing, it really allows you a really good way of getting high performance graphics to the screen.

Geoff Stahl It's platform agnostic. So a lot of you who have things that may run on Unix or may run on Windows or may run on the Mac OS, OS 9 or OS 10, can use the same OpenGL graphics code for both and have that stay the same across multiple platforms for your application. So it solves your development problems that way. You don't have to write windowing code for every single application and write the specific graphics engine for every different platform you're on.

Geoff Stahl It's also asynchronous. This is a key to understanding the application. You have a graphics engine and you have your application. You're submitting commands to the graphics engine. This kind of comes back from when it was originally from the SGI design that you could have the graphics, you have a client server kind of operation that you would not have in what you'd say a PC today.

We've carried that over and everyone's carried that over when they build OpenGL. And what that does is means that your commands are submitted and then you swap the buffers and it basically executes a batch of commands and displays whatever your commands are. So it's a really good way to understand OpenGL. So it's a really good way to understand OpenGL.

whatever your image becomes on the screen. It's also based on geometric primitives. Instead of some higher level languages, that might be PDF-based, like Quartz, or that might have a file handling capability, it doesn't have that. What it has, basically, it has the basic points, lines, and polygons, and you build from the bottom up.

And, real important understanding of OpenGL is that it's a state machine. What state you set it in is always the state it's gonna be in. If you're texturing on, it's gonna stay on until you turn it off. If texturing's off initially, if you try and texture a polygon, you're not gonna get any texture. You're probably gonna get a white polygon, 'cause it's not gonna apply a texture until you turn the texturing on. And there's lots of examples of that. And a lot of new OpenGL programmers, myself included, have been bitten by that many times. That's about it. Let's move on.

So we talked about it as a state machine. As I said, this is a key to understanding OpenGL and successful development with OpenGL. By understanding it as a state machine, you can understand why things happen in your application. And as I said, with texturing, you can add almost anything in OpenGL, including the modes, not just the switch kind of mode, but including some of the drawing modes against states. And you can change drastically the behavior of the application by setting simple states.

Also, state changes can be expensive. Sometimes they're not, but in a lot of cases they can be. For example, you design an engine to draw something on the screen that every frame goes through and sets every single state that you need set. In some cases, you can really be hitting some long paths through our drivers and through OpenGL, thus making your application run significantly slower than it could run if you actually set the state once and then think about when you need to change it.

So, for example, if there's only two things in your state, one is texture mapped and one is not texture mapped, draw everything that's texture mapped, and then draw everything that's not texture mapped. That switch once rather than on a per polygon or a per point basis. So also, we talk about setting and getting states.

It's really key when you want to know how to set a state or how to get a state, you can use glEnable and glDisable. Throughout the API, you can use them for almost every state. The documentation covers the litany of states that you can set. Also, there is a lot of information. The key here is a glIsEnabled and a glGet.

The key here also, sometimes that has to query the hardware. And to do that, since it is an asynchronous operation, you can have a command that changes a state somewhere in your pipeline. If you call a glGet, say, "Hey, is texturing enabled?" What happens is it may have to wait for your whole command pipeline to execute to query the hardware to say, "Am I in that state?" Get the command back. So, as you can see, that could be also an expensive thing. That's not a shortcut. There's not a state that is always saved off in the software. It really ties the software, OpenGL drivers, and the hardware tied together very closely.

And GL push attribute and pop attribute. The reason I mention these is sometimes if you want to change a lot of states, you have a pile of things you're changing, you may want to use push attribute and pop attribute. So a lot of times it's faster to do that than it is to save all your states or check your states, enable your states, disable your states one at a time.

So let's talk a little bit about the OpenGL Pipeline. Real simply, the OpenGL Pipeline, this is a really high level overview of the pipeline. I say that you might want to go to the references, and there's a lot of, in the specification and in all the references, there's a lot of more in-depth section on the OpenGL Pipeline. So I'm not going to really go deep into this, but it gives you an idea of how it works.

And so this is, all your data comes into this pipeline. And first thing that vertexes come into, so if you have a vertex, you have a point in space, it comes in there, and basically when the vertex comes in, it applies a transformation that puts that vertex somewhere in space.

It says, okay, the model transformation, it's over here by the podium. And then it takes the transformation, the view transformation, basically says, I'm looking at it from this perspective. And so that sets out the relationship between the point and the eye. And also the projection transformation, which actually projects that point from your 3D space into your 2D flat screen. That all happens in the vertex operation.

Then we clip the thing, perspective divide and viewport transformation happens, so we actually transform it into what size your viewport is. You'll see in one of the applications I'll demo later that you can drag the window and make it larger. That's a, you'll translate that, and it's resetting the viewport to a size.

Perspective divide basically scales things via your Z or how far away it is, making things smaller, far away, and closer. And when things are closer, it makes them larger, obviously. One key here is that perspective divide is based on information you supply to OpenGL. It's not based on OpenGL always does this. It's a 3D application. It has to look exactly this way.

For example, one thing we'll talk about later in the week is using OpenGL for not a game or not an immersive 3D application. You can say, "Hey, I want this to be orthographic. I don't want that perspective. I just want everything to be directly parallel projection, and I'm going to make everything the same size no matter how far away it is." And you can do that if you're working on a CAD program, for example. So these are things that it does in general, but depending on how it's set up and what state it's in, maybe depending on how actually it carries out these.

And it calls either... It can do a lot of things. It can do backface culling. So if you have my proverbial cube, and I don't want to show the backfaces of that cube because maybe it's transparent, it will look at the polygons and determine, based on whether it's clockwise or counterclockwise, what polygons to throw away that may be facing away from you.

Now we talk about pixel operations. Pixel operations are parallel to the vertex operations. If you put a texture in there or you put a bitmap into OpenGL, they go through the pixel part of the pipeline. Basically the pixels are unpacked and sorted into a format that OpenGL can understand.

And that's real important because when we talk about texturing later, OpenGL expects a certain types of formats and you need to be able to supply this type of format graphics for it to expect. And you'll see why we have some good news in that area as I get through the presentation here.

Pixel maps are processed and they're passed to the texture memory or to the rasterizer to be drawn. So basically it hands it off to texture memory. Here you go. Here's your form, your bits and pixels in a proper format. And then when the texturing instructions come in, they can pull that texture out and they can texture to the screen.

Rasterization. Rasterization basically takes your geometry and pixels and converts them into fragments. Fragments is something that represents basically one pixel on the screen. As you notice at the bottom of this slide I have X, Y, Z, W, RGB, ST, R and Q. So those are basically a point in space that has an X, Y and Z value. You may say, "Hey, didn't he just say that it was already... We already converted to 2D. We did this perspective divide thing. Why do I have a Z?" Well, you can do depth sorting with this fragment.

So when it's... If you have depth sorting turned on, it turns into a fragment and says, "Hey, am I in front of everything else? Am I fully topaq and am I in front of everything else?" This is the fragment should actually be this fragment instead of the fragment behind it. RGB is obvious. ST, R and Q are using texture mapping. But basically... So this converts everything to the single pixel on the screen and allows it to then be drawn to the screen.

And lastly, we do fragment operations, which is texturing and fog. So it says, "Hey, I got this colored pixel." It may be white, it may be gray, it may be blue, but now I want to find what piece of a texture map corresponds to that single pixel, and I color that pixel with my piece of the texture map, if we're doing texturing.

If fog's applied, it applies the appropriate fog, and it can do scissor checking, scissor something down, alpha, stencil buffer, depth test, all done in here. So this is why I talk about depth tests. So you're going to take multiple fragments with different depths. It's going to take the front one, but one could have an alpha value, so you may have some different interactions there, but this is where it's done.

Okay, what does OpenGL not have? This is what people don't understand a lot. OpenGL doesn't have a built-in windowing system. It doesn't know about Mac windows, it doesn't know about Windows windows, it doesn't know about Unix windows, it doesn't know how to draw things to the screen. So on the Mac we have AGL, we have NSGL, we have GLUT, and we have NS OpenGL View. These are all ways to set up an environment that OpenGL can use and use that to draw into.

AGL is fairly simple to work with because it can be used with OS 9 and OS 10. NSGL is going to be on 10, GLUT is on OS 9 and OS 10, and NS OpenGL View is also on OS 10. There are different ways to work with it. The NSGL and the NS OpenGL View are both object oriented. NS OpenGL View is kind of interesting because you basically can do everything. You just instantiate an NS OpenGL View object and it already sets up your OpenGL for you. You're ready to go.

It also doesn't have a built-in window. It's a little bit more complicated. It's a little bit more complicated. It also doesn't have input methods. Input methods are OS specific things. So for example, if you're in a Mac OS application, you're going to have to take care of the normal keystrokes, those kind of things. OpenGL is just a graphics API. It does not have any kind of input. If you're using GLUT, obviously also, which I'll talk a little bit about later, GLUT has its own keyboard interface and mouse interface.

It also does not have file handling. This is one of the things that OpenGL being a lower level API rather than a high level API, it doesn't have the handling of an importer for a certain kind of file. If you build a model in Maya and you export it, it doesn't have intrinsically a way to read that Maya model in and display that. You have to put that together or use some sample code that's already created.

It also does not have, like I said, high-level modeling. It doesn't have any tools built in to do high-level modeling or to understand high-level models. High-level models can have a certain way of texture mapping. It also can have a certain way of handling a hierarchical structure, like a skeleton. And that's not built in.

You can decide how to do that, and that's something for you to do in your applications. Or you don't have to. If you don't have high-level models, you want to display some small things or some primitives or use some of the primitive drawing, you don't have to build a complete handling system for every file out there.

Okay, now we're going to talk about Apple's implementation. First thing I'll do is go over a quick overview of what hardware we have out there. I know I probably have some new Mac developers out here, probably have some old faithfuls here. This is going to be a real review for you guys. Then I'll talk about some frameworks for OS 9 and OS 10. I'll talk about what extensions we're supporting. I'll talk a little bit about GLUT. And I'll talk about AGL and SetupGL.

So current hardware is obviously the iBook, the iMac, the PowerBook, and the PowerMac. The iBook, the first part is standard, but the key here if you're working with OpenGL is what kind of graphics hardware is it going to support. It has a Rage Mobility graphics processor, which is basically like a Rage Pro. It has 4 Mega VRAM and AGP2X. So what does that tell you? The 4 Mega VRAM says about how much limitation you have on texturing and buffering.

When you're working with OpenGL, it's not critical to understand, but something you do want to understand is the fact that if you're doing OpenGL, you have a front window. You have a screen that takes up a certain amount of VRAM. You have a back buffer for your OpenGL window that takes up VRAM. And you also have a depth buffer which may take up VRAM.

And any textures you upload are also going to be in the VRAM. So thinking about what the configurations you're shipping to, what kind of VRAM, is kind of critical. And also I would say testing on multiple systems is also critical for OpenGL. I'll tell you a little story here. When I came in to do my demo, I brought my PowerBook in. Works great. My demos run great. They're really simple. Shouldn't be any big deal. Hooked it up here, turned on video mirroring.

Forgot that the VRAM was split between the mirrored and my PowerBook display. And when I loaded my texture, it was doing texture paging. So that's something that's important. And that's a good reason to go test your app on your multiple platforms and make sure you're running and make sure you understand the constraints of running your app.

iMac has a Rage 128 VR graphics processor. Really great thing to work with. I mean, if you have an iMac, you can surely do OpenGL development. It has really good support for OpenGL and is one of our, you know, the Rage 128 is our top processor we're going to support as far as feature sets. So you're going to get all the features there. 8 Mega VRAM, that's good. AGP 2X also. Amen.

PowerBook, 400 and 500 megahertz PowerBooks, ATI Rage Mobility 128 graphics controller, 8 mega VRAM, and ATP2X. One thing that I have to say is that this is one of the unsung heroes of our product line for me, because I'm like, "This is great! You can get this, you can do OpenGL work here." I mean, I used to develop OpenGL on a Rage 2, which I had to do like a 200 by 100 window, and looking at it, "Did it get right?" So, this is great to have this, because you can develop full-speed applications, you can develop full-screen applications, you can work on your PowerBook wherever you are without having to sacrifice the graphics processing.

Another PowerMac, the Rage 128 Pro graphics processor, up to 16 mega VRAM and ATP2X. There are also third-party hardware that's supported for Mac. 3DFX, both have good offerings. 3DFX has obviously announced full Mac support, and they're going to be rolling out some really high-powered cards. So, we're looking also for people to add on cards and get more performance even than we may supply initially.

Okay, let's talk about how OpenGL is structured in the OS. So for Mac OS 9 implementation framework, we have an application, we have a little setup code. The reason I segment those out is because, as I said, OpenGL does not have a windowing system. It does not know all about how to draw to a window. It does not know what your windows are like. So the setup code is what handles that. So when I say setup, I say constructing your window and telling OpenGL this is where it's going to draw.

Two ways to do setup in Mac OS 9. Through the GLUT, which GLUT handles the setup for you. Basically you say, "Hey, this is my window. Here's what I want," and it builds it for you. Or AGL, which you build your window and you say, "I want a certain pixel format.

Here's my drawable. It's that window, and I'm going to pass it to you, and you're going to take care of that, and you're going to use that for me." Once you get past that, you can see that then you actually can talk to OpenGL directly. The application for GLUT application can actually do some things in GLUT to produce output, but also it can go directly to OpenGL once you have the setup done. Then you go through OpenGL, make all the GL calls once you have the setup done, and then that passes through to the drivers, which handle actually rasterizing and drawing things to the screen.

OS X is a little more complicated. OS X, there's a lot of different ways to set up. But if you notice that the application still is using GLUT or is using OpenGL. That hasn't changed. You can pick a lot of different options for setting up. But in reality, your OpenGL, your application code doesn't change.

I have a number of examples I've been working on over the past few weeks for some of the demos and just for some of my stuff on OS X. And I didn't change any of my OpenGL code. None. Zero. I mean, all I did was change my setup code, which is really a good story.

Because it means that you can move your applications that may be on 9 forward and you can create applications that run on 10, run on 9, run on Windows, run on Unix without having to change your code for every single platform specific. You just have to change some of the setup stuff. We talked about some of these. The NSOpenGL view is available in Cocoa.

We also have GLUT, which is going to be available. And the GLUT that's available will be available on OS X and OS 9. And there are different implementations, but they should be code compatible. GLUT is a, if you don't know, is a, basically a free, not freely distributable as far as, better way to say that.

It is not given to you free. We, it's not our application. Mark Kilgard, who used to work at SGI, wrote it. And he distributes it freely, but it's not, he still owns the source code. You're not free to go and change it and call it yours and resell it or something like that.

NSGL is also there. GLUT is implemented on top of it and NSGL OpenView calls into NSGL. AGL is there. Works, works basically the same on 10 and 9. They call into the low level core graphics GL, so it's CGL and that goes to the kernel and to the drivers.

So the key here is to understand is there's lots more ways to get out of OpenGL. If you have a Cocoa application, no problem. Set up OpenGL through Cocoa, through NSGL, off you go. Dave Springer is going to talk in the next talk. We'll show you some demonstrations of using NSGL and show you how easy it is. and show you how easy that can be.

Okay, this is what we have for extensions right now. A couple Apple extensions that may improve some rendering, some transform hints, compile vertex array for speed, Quake uses that, multi-texture, Quake uses that too, a lot of people use multi-texture, get the texture working, and text-dnv-add. Well, what I'm going to tell you right now is that we've had a lot of developers say, "I need this, I need pack pixels, I need this other format." Actually, let me back up a little bit. Extensions to OpenGL. For those of you not familiar, but I may have moved a little bit too fast here with OpenGL, OpenGL has a particular graphics API it defines.

It has a method by providing extensions that extend that API. For example, with the multi-texture, it allows you to do multi-texturing, layering more than one texture on top of each other in OpenGL and passing that to the OpenGL pipeline, rather than having to do it in software, where you might blend things together and then pass it as a single texture. So, there's a litany of extensions, there's a lot of extensions out there. We picked some of those to implement. Some of them are vendor-specific, so they might be an SGI-only thing. And some of them are the ext type, which are multi-vendor.

Obviously, we have two vendor-specific ones here, and the rest are multi-vendor. There's a lot of other extensions that people say can handle textures better, can do some more kind of combining textures. And we, up to this point, haven't supported that. What I can say is that, basically, as of... I'll tell you the availability when I get there. I'll tell you the availability right now. OS 9, VADC seeding, and very shortly we're going to have these extensions available on a seed for OpenGL 1.2, which will be a 1.2.2 compliant OpenGL.

One of the keys here is our software implementation and the API that you can write to is 1.2.2 compliant. So, OpenGL, there's two pieces. There's a driver piece, and there's our implementation piece. As drivers come up to speed with 1.2.2, you get a full OpenGL 1.2.2 implementation. But the key here is you can get these extensions very shortly from seeding, and then after that, they'll be in our next OS rev when we bring that out, next OpenGL rev. Also, for OS X, the same set of extensions will be available for OS X very shortly.

So, for developers who want to look and use these things, they'll be available very shortly, and pay attention to the OpenGL list, and also in the ADC seeding, and they should be available for download and for installation onto DP4 or onto Mac OS 9. We're looking for Apple PAC pixels, and some people who are familiar with PAC pixels are saying, "Why is it Apple PAC pixels?" We're extending it a little bit to recognize the kind of pixel formats we need, but it should be the same as the normal PAC pixels.

We have a transpose matrix. We have an ABGR, so we can do different pixel orders. We have pixel ordering, pixel color ordering, and a whole bunch of others. We may even add to this if we see that there are some that the developers are looking for. So, this is, I think, good news for developers, and we can really extend your ability to develop on the platform.

Okay, let's talk about GLUT a little bit. GLUT is GL Utility Toolkit. As I said, it was written by Mark Kilgard of SGI. Written a number of years ago. It's available as source code through a number of different vendors. We give it out with our SDKs also as source code. When we first brought the OpenGL SDK 1.0 out, we brought GLUT over to the Mac. It's on Windows and Unix.

We ported that in the 3.6 format, which had some things that it lacked. We ported that to the Mac with the 1.0 SDK. Shortly we'll be releasing the 3.7 version of GLUT, which includes a couple of new things. It included game mode or game GLUT, which basically allows you to get a full screen mode on GLUT. Also some contextual information. We have contextual menu support, which is a normal way for GLUT to operate. We're finishing this up right now, and this should be sealed up and should be out with our next SDK release shortly.

Some bug fixes we're on 9 are better child window handling and just some general bug fixes. 3.7 will be available for Mac OS 9 and Mac OS X. I have to actually think that is this correct, but the 3.7 API, maybe minus game mode, should be on the DP4 CD, and that's correct.

So GLUT is a little bit different. The 3.7 is on DP4, and a significant amount of the examples that we have going with it will be there also. So why should we use GLUT? I would honestly say GLUT is probably not something you would want to use for a shipping application. If you want to build a little bit of OpenGL, experiment with it.

If you want to check out a rendering technique or do some work on an engine that you may want to put into GLUT, that might be a good framework just to work with it. It provides an API or a platform agnostic. I A GUI environment. I'll say GUI, a little bit of a GUI environment. Basically gives the platform setup, the setup for the Windows, handles some input, handles keyboard, handles some mouse events, handles menus and those kind of things. And your code can go from Windows to Mac to UNIX without really any changes.

AGL and SetupGL. I alluded to this a little bit earlier. We talked about AGL and SetupGL. AGL is Apple GL. It's basically our interface to the GL. So this is the thing that handles Windows setup. It handles basically all the pixel formats. It handles some utility and some error codes.

AGL is available on Mac OS 9. It's also available on Mac OS X for Carbon. And you can write basically the same code in Mac OS 9 and Mac OS X. And I've been working on some stuff that basically compiles one binary, runs on 9, runs on 10, runs on OS 9 as an OS non-Carbon.

And I'm sorry, one set of code and the same code runs on 10. It wasn't that difficult to do. They were talking about a few weeks to carbonize it. It took me two weeks to do it. Maybe, you know, probably an afternoon. Probably really four or five hours at one sitting. It's better to cost two or three days.

And what is SetupGL? If you're not familiar with OpenGL on the Mac and you're not paying attention to our OS OpenGL news group, you probably haven't heard of it. It's actually a piece of sample code that you can have all the source to. What I try to do is in our sample code, we have a section we call more is better. And there's more network setup.

There's more files that some of our other engineers have written. And what they've done is basically trying to encapsulate a real significant piece of the functionality that you will need into a piece of sample code. Instead of having a sample code that shows, okay, here's how to draw a square in OpenGL. Instead of just doing the absolute minimum, try to do better error checking, better error returns. Try to add in actually handling, you know, your VRAM requirements so you can send a different VRAM requirements.

Handle full screen window switching. So one call can get you a full screen context. You can destroy that context and call one call again and get you a window to the same thing. So it's not limited to just doing one thing. So I think it's a reasonable thing to start with. It gives you either a good base of source code or you can use it directly. SetupGL is Mac OS 9 currently. And I say Carbon soon. That's actually not correct.

As of when this presentation was written, it was Carbon soon. Now it is carbonized and it should be out this week on... on the ADCC. It should be on the sample code site. You should have a Carbon version of it that you can run in Carbon and run on Mac OS X DP4 and in OS 9.

So AGL, we're going to talk a little bit more about AGL and a little bit more about the specifics of AGL. AGL handles, we're going to talk about the basics, and it handles pixel formats, handles context, drawables, swapping fonts, and errors. So what are all of those things? First, the basics. As we talked about before, it handles setups, it handles swaps, and it provides utility function.

If you're familiar with Windows at all, you'll see that an AGL drawable, which is defined as AGL, and that's the main construct that you're going to pass to GL and say this is what you're going to use. It's equivalent basically to a C window pointer, which is also equivalent on Windows to an HDC. So that's kind of the equivalency if you're coming from WGL.

The key here is that people sometimes try and get away from it, "Well, I can use a C graph pointer. I can just point to my off screen, or I can point to this piece of memory, I can point to whatever. I can grab a C graph pointer on the screen and just draw to that." A key, a real key for GL here is it uses the information in the window pointer to figure out what piece of hardware you're rendering on.

If you have two cards, one's 3DFX, one's Apple, and you drag your window from one monitor to the other, using AGL correctly if you have a window pointer you can fairly easily do that and it will render on one and it will render on the other no problem.

If you pass it a C graph pointer, probably best case is if you start on your main monitor it will render correctly. If you move it off it may not render anything. If you start on, if you have your window on your secondary monitor and you pass a C graph pointer it will probably draw on the upper right corner of your main monitor just over everything else.

So the key here is use a window. The window information is important, you can't substitute a C graph pointer in this case. An AGL context. An AGL context basically maintains an AGL state and a GL state with that. So basically you can switch between contexts and now switch between one rendering state to another rendering state. And that's the same as HGLRC. I love this one man, this is great. We have a nice AGL context and they have capital HGLRC.

So what is an AGL pixel format? You say, isn't that like what's on the screen? Well, not quite. An AGL pixel format may be a misnomer. AGL pixel format actually is a request for a drawing mode. It has some more things in it. You can tell it. You know, RGBA, you can say you want a double buffer. You can say you want a back buffer, or a depth buffer.

You can say how deep that depth buffer is. There's a lot of specification to the AGL pixel format. And it's not just saying I want 32 bits, 16 bits, 8 bits, whatever. It's more than that. We'll go through that in a minute. But it's equivalent to the pixel format descriptor. I like that. So moving on.

Pixel formats. Okay. So the two main things we're going to use is AGL Choose Pixel Format and AGL Destroy Pixel Format. And please, if you're doing GL, check for errors, check for AGL errors. It's reasonable that when, if you give it a pixel format that's not supported on a card or on software or on this other monitor you're using or whatever, then it may fail. And if you go off in your merry way and set up your context and draw your GL, you're wondering why you're not getting anything or why your program's crashing, it's because you could have not returned a valid pixel format.

It says, hey, I can't do this. So you have a set of attributes there. And what do those attributes actually say? Well, in this case, it's telling AGL that you want a red, green, blue, and alpha buffer. You want it to be accelerated. You want it to be double buffered.

And then the AGL none says you terminate that, that set of attributes. You'll do this, this for every kind of pixel format you work with. You can add the double back buffering to that or depth buffer. You add that and you want to have a double back buffer. And then you want to have a double back buffer.

And after that, you specify the depth, how many pixels your back buffer, or I'm sorry, how many bits your back buffer is. What are some other things you can specify? You can specify or you can ask for how many bits for each component you want. And one of the keys here is that, is the AGL accelerated in that string. AGL accelerated, I think I've written, or maybe I didn't write, I can't remember actually.

There is a, actually there is. There's a Q&A about AGL choose pixel format, which I would recommend anyone who's looking to open GL to read and look at. There's some caveats on how this works and it's probably more in depth that I can go into it in this setting. But realize that it may not be obvious how it's choosing pixel format.

It's very logical and it's very easy to figure out once you know it, but it may not be obvious first looking at it. For example, what it tries to do is tries to match across any possible display that you pass it, this pixel format. So if I have four displays and I say I want this pixel format anywhere, but having two of those displays are not on accelerated AGL, I'm going to have to do a little bit of a test.

So if I have a display that's not on accelerated card at all, I pull some cards out of the junk bin, put them in there. It'll fail. It'll say, hey, I can't accelerate this because I, these two don't have GL renders on it. So that's, and people will say, no, why is it failing? I have my Rage 128, I want to, that's where the window is and so.

There's some nuances there as far as selecting displays and what you want to do. If you want a window to be draggable, you want to, you want to make sure you do a choose pixel format for all the displays you could drag it across. If you want a window not to be draggable, you want to probably limit it to the display that you're actually on. So that's some nuances there.

So that's an AGL choose pixel format. But then it's real simple. You call AGL choose pixel format, you pass in an HGD, you tell it how many displays that you're passing in a list of HGDs, and you pass it the attributes. So in this case, we're going to say I'm on this HGD handle, I'm sorry, that's my shorthand, handle to a G device or a GD handle.

And I have one monitor and I want to run on that monitor and here's my attributes. When you're done with it, you call AGL destroy pixel format. When you're done means when you're done creating it. You don't need to keep it around until you're finished with GL. You can actually create it, assign it to a context, attach the drawable and off you go and destroy it right then.

So context. Next step in the process, you have a pixel format. You said I want to do RGB, I want to have a double buffer, I want to have a depth buffer, etc. Now I have my pixel format for those displays. Now you want to create a GL context that you're drawing in which, say, CASELE can encapsulate the GL state.

You can have more than one of these, by the way. It doesn't mean you have to have one of everything. You can have as many as you really want to work with. I'd recommend, depending on what you do, you look carefully at the difference between a pixel format, a context, and a drawable.

You may want to create one pixel format, create a context, and create a couple drawables to that pixel format and context. Or if you have maybe a window that you don't need any depth buffer, then maybe you have a different pixel format for that without a depth buffer and a context that encapsulates that.

But if you have everything that needs the same thing, everything needs a depth buffer, everything needs RGBA, everything needs to be accelerated, you can use one context and create multiple drawables for that context. This is simple. This is basically, you pass it in a pixel format, you pass in null, and you just create a context. Pretty simple.

You get the context out, check your errors, and when you're done with it, you actually want to destroy it. Another thing is set current context. If you have multiple contexts, you want to do set current context when you want to draw more than one context. One of the things that I also find that people miss is AGL update context. It's not on the slide, but I'll go over it a little bit.

If you're moving your window, sizing your window, showing your window or hiding your window, you definitely want to do AGL update context. It lets AGL tell OpenGL how to reset the drawables and reallocate buffers if necessary. For example, if you size a window, we have to reallocate the back buffer there. We have to make sure that we have a new back buffer that's the right size of the window.

So it's not a good thing to do these updates without, or do updates to your window without actually telling it. Same thing if you move from one renderer to another, we need to tell GL to not use the RAID 1.28 and to use the VUDU that you have on this other monitor.

Okay, drawables. Real simple set drawable. You basically, all the set drawable's going to do is going to attach a drawable to a context. You can say, "I want to draw into this window," basically. And so you can have five windows, or you can have, for example, the standard CAD program has three views: top, left, front, and the projection view. What you could do is you could set up those three are orthographic.

You set those three up that basically have, you know, they're parallel projections. And you're going to do one context for those three, and you're going to have all of those be parallel projections with three separate drawables. And you attach one, you move your camera, you draw that one.

You attach the other, move your camera, draw that one. Move your camera, draw that one. Then what you're going to do is you have a second context for the one that has the perspective projection, and you're going to set that up with perspective. And you have that as its own context, its own drawable, and you basically switch to that context, set the current context, draw that one, and off you go. Calling sort. buffers have when you finish drawing for each one of them.

Okay, for swap buffers, it basically tells OpenGL I'm done submitting stuff to you, go ahead and draw. So it's kind of the go ahead and take off and let your engine chew on this data. So you pass data, you pass data, you pass data, call swap buffers, it sends it all off to the card.

And actually that's probably not correct to say it sends it all off to the card, but it actually starts executing that actual frame to draw to the screen. Real simple. Here's AGL swap buffers with a context. One note here is it does implicitly call GL flush, which means it basically terminates that scene for rendering and says go ahead and at some finite time in the future I know this will actually execute.

AGL use font, AGL use font is a real nice thing to have. When I first looked at GL a while ago and looked at AGL use font, you know, I can't quite understand it. I can't get it, and then I thought I pulled around and said, "Oh, this is really easy. This is like super simple, and this is great because I can put all kinds of data in my stuff. I can put out, render them on, I can put in my frame rate. I can put out what it's doing. I can put out state information.

I can do all this by putting text on the screen in OpenGL without having to, you know, draw text to the screen, which I'll talk a little bit about later. But basically you don't want to try and draw text in OpenGL window because OpenGL doesn't know you're drawing text and there's no idea, and so it'll draw right over it or your text will draw over the OpenGL, and it's not designed to work in that fashion.

But AGL use font, I get an Fnum for Monaco, for example, and then I'm going to go use, create a GL unsigned integer, which GLU is. And I'm going to create a new element, list base, and that's the base of my, base of a list of basically textures I'm going to have there.

I call gen list 256, which generates 256 slots in that list. I then call use font with my contact, my font ID, the normal 9.0200 is the beginning of the list, 256, which is the end of the list, and the list base. And what does that do? That creates, that basically takes that font and draws it into all those little slots in the list.

So now I can go and I can say, . . . . . . my nice little function here, which is I use call list, with the string length and set the list base, and basically what I can do is I can, with the base of the C string, and I can put a C string to the display.

I set a position, I use this call list function, tell it what the string is with a null terminated string, and use a, and, well, put the string and then the length of the string, and it just writes the text out to the screen no problem. So it's really easy to put text to the screen. You can use printf, you can use, you know, S printf to format whatever you want, and you can just put it out. You can put out errors if you want to the screen. So it's real, real simple to do.

Agl errors. This is to differentiate from the gl error, but agl error has agl error, agl get error and agl error string. Real simple. You get, you, what you're gonna do is you're gonna get the error, you're gonna pass it in if it's not no error to an agl error string, it actually puts the string in a parsed format, what I a lot of times do, is you do, do a debug string and so it drops into the debugger and then I'll conditionalize that in a debug mode or non-debug mode so I actually don't get the debug strings when I'm in my final build but in my, I always want to be, I always want agl to tell me if there's problems creating something when I'm doing my non-debug build. So there you go for agl error. It's pretty simple to use and I'm putting in parse it right there. We give you the ways to parse I set up GL back to that sample code.

This sample code is about five files, six files. And you can pull it apart, you can tweak it around, you can do whatever you want with it. It's provided as is, but I think it does you a pretty good service. You can just get it. It's just one call to set up, one call to take it down, and off you go on your GL. You don't have to do anything else. I ported a couple screensavers from one of the folks who do Windows 3D screensavers.

And I ported literally one of them in like 30 minutes using setup GL. I just replaced something, moved a couple things around for the WGL calls, and that was it. And I was done. So it works pretty well. It was originally used for Quake 3, and this is based on the Quake 3 code that we worked with them for.

It handles both Windows and full screen. The full screen is currently Mac OS 9 only. And I'll go through that a little bit right now. Full screen on 10 is being implemented right now, or is in development right now. And we're going to provide that shortly via seeding as a patch to 10.

So we don't have a way of getting full screen for OpenGL at this time. That's something I would love to have had in DP4, but we have to close the lid at some point and get something to you so you can be developing with it today. But expect that really shortly. Obviously I can't give you definite times, but I'll alert people on the OpenGL mailing list when it's available so they can get it and they can download it.

and so they can get it and they can download it, and immediately after it's available I'll extend this to use the full screen section, and if you want to find more about full screen, full screen applications, we have a games on X session tomorrow, I believe it's tomorrow, that will talk about some of the options in OS X for full screen games.

It handles multiple contexts, has a pause and resume in it, and the source is available sample code at that URL. It's really simple though, developer.apple.com/samplecode, and we have a real good hierarchy in the sample code, it's really easy to find, so you just go to 3D graphics and you'll see any of our sample code for 3D graphics there.

So let's talk about using OpenGL. I'll go through a little section about how the basics to set up and use OpenGL is, how to set it up, how to do some basic transformations, how to do some basic using what the basic primitives are, talk about alpha blending, and talk about texture mapping a little bit.

Okay, so let's look at this code here. This is through AGL. The first thing we're going to do is we're going to set up AGL attributes, basically the same thing we did before, AGL RGBA, double buffered and none. So this is saying I want a double buffered context so a swap is actually going to draw into the back and a swap to the front.

AGL RGBA, obviously, red, green, blue, and alpha, channel for it. And depending on what my display resolution is, is depending on actually what the target is. This does not set your display resolution or have anything to do with that kind of thing. It just tells OpenGL how you want to draw.

Pixel format and context, I'll set those variables up. I'll choose a pixel format. In this case, it's a different example of choose pixel format. In this case, I pass null and I pass zero. What happens here is it looks across every monitor that you're looking at, and it says, "Can every monitor that is attached to the system, or every video card, every graphics display device, satisfy that pixel format?" If it can't, this may fail. So realize that's when the accelerator thing comes in again. If you realize that setting AGL accelerator means that everything it looks at has to be accelerated for it to succeed. That's one thing to think about.

I'll call AGL create context, passing the format in that I got out of the pixel format. Obviously there's no error checking included here, but I would definitely say given the code for the error checking, it's pretty simple to write in the AGL git error, AGL error string. And then I set the drawable. Basically I'm going to cast a p window to an AGL drawable. Again, I can't stress enough that you want to use a window, not a c graph pointer for this.

SetupGL simplifies your coding, or you can rip it apart, you can pull pieces out of it, and you look at it as an example. I really don't care. Whatever works best for you and whatever helps you in your development efforts. In this case, I call it PreflightGL. Basically, if I expand this a little bit, the way SetupGL works is there's a glInfo, which is a structure. You fill out the structure. It's pretty simple. It's a width, it's a height.

Do I want full screen? Do I have to have this width and height? Because otherwise SetupGL will pick out a window that kind of fits into your screen, what works with that, what works there. I pass in the glInfo full screen to PreflightGL to know whether I want to use DrawlSprocket in this case to do full screen or not. If I don't, all it checks for is the existence of GL. If I do, it checks for also if DrawlSprocket exists and can call that.

Then I call BuildGL. In this case, I'm going to pass in the name of the script. I'm going to pass a pointer to a drawable, a pointer to a context, and a pointer to a DSP context, which may be null if I don't have a DrawlSprocket. If I don't want it on full screen, that could come back as null.

Then I can pass a number of the device, so which screen I want on, and basically pass my information in there. Inside that information is the pixel format descriptor like we saw before. That one call, boom, you're done. Out of that, you get your drawable and your context, which is what you need to draw for GL. DestroyGL, real simple, pass the same information in. It takes care of shutting everything down for you and closing everything out. Okay, let's move on to transformations.

This is kind of a tough slide to go through and there's a lot of information on there and this is absolutely scratching the surface here. One thing I look back on the years ago when I was in college, I say, "Man, I really wish I had studied more and paid more attention to linear algebra. If you're work, if you want to work in GL, and you want to do more than, than your fairly simple applications, I would really look to make sure your linear algebra, and your matrix handling is good.

There's a lot of simple things you can do without it, but if you really want to, for example, if you want to write the next quake, definitely you want to understand how matrices work, and how rotations work, and how offsets work, and how, how that interact with each other, because that's a, that's a key to actually being effective in open GL programming.

But there are some simplifications here. There are some, some things you can do that don't require the super knowledge of linear algebra. GLU, look at. I didn't mention GLU yet. GLU is not a GL call, it's a GLU call. It's a little bit higher level. With every open GL implementation, there's also a GLU.

The GLU does some nice things for you, and kind of builds higher level instructions that rely on the GL instructions. In this case, you tell it where your eye is, x, y, z. You tell it where the center of your display is, x, y, z. And you tell it up, x, y, z, so what, what the up vector is.

So you can say, I'm at zero. I want to look at 10, 10, you know, 10, or 0, 0, negative 10, z. And you can tell them what your up vector is, and you're, you're rolling. You don't have to figure out, well, okay, that's a right hand rule, and I'm looking here, and I'm moving around here. You just tell it where you are, tell them what you want to look at, and I'll set up. So it sets up the model view transformation. It basically sets the basis for where your eye is relative to where the center of your screen is.

So if you just draw something now, it'll draw relative to the center, relative to the zero on your screen, which you can, you can move back and look at the zero if you wanted to also. For modeling, that's for moving your eye. For modeling, to move your model, you basically want to set up whatever you're going to do, whether it's the, whether it's a cube, a square, or whether it's the, the Sarge and Quake, or whether it's a Maya face model. What you're going to do is you're going to use translate, rotate, and scale.

What that's going to do is you're going to, they do exactly what they say. One translates, one rotates, one scales, and they can move your model around. You want to apply this to all the vertexes in your model, obviously, and you want to realize that what order you do things in, where you translate first and then rotate has different things than if you rotate then translate. We can easily see that.

If you have a square in front of you, or you have whatever, a car in front of you, and you rotate, and then you translate in that, in local coordinates, it may translate differently than translating and then rotating. So you're going to use, you're going to use translate, rotate, and scale. What that's going to do is you're going to use, you're going to rotate, and then you're going to rotate.

So that's something to look at. Some of the OpenGL references talk about that and talk about how to think about that in a way that works for people who have not done a lot of OpenGL programming. It's not too bad. If you work through it closely, it's pretty easy to do once you kind of get the hang of it.

One of the keys here, one of the funny things that I think every OpenGL programmer realizes is there's more ways in OpenGL to get a black screen than in anything else in the entire world. Everyone who's working OpenGL goes, "Okay, I got this figured out, and I got it out there, and I checked it, and I have my paper, and I'm sat in my office and stared at my thing, and I got this rolling.

Okay, Let me look at something. Let me look at my GLU look at. Well, so how do you know if your GLU look at is wrong? I mean, your model could be off in the next building over as far as you know. I mean, so there is, my recommendation for all of this is to, there's a ton of examples out there for OpenGL, a lot of GLUT examples. It does tons of things. Dave will show you some examples and some of the stuff he's done.

And there is like 500 examples in our SDK. Use them, build off of them, look at how they do things, move in small steps. Don't decide, like I did the other day, that you want to display a movie on a surface that's rotating and deforming and have your eye move around at one time. I'll add this all at one time. I don't want to add all this in pieces. So, you know, work slowly, look at your transformations carefully, learn what they're doing, look at the different effects of the different transformations, and you'll move forward quickly.

If you sit there and decide you want to write a new model, you're going to have to do it. You're going to have to do it. If you're going to write it from scratch and you want to figure it all out, I guarantee that you'll be looking at a lot of lock screen.

For projection, GLU Perspective is really nice. Field of view Y and aspect ratio in a near and far plane. Pretty simple. I mean, it just basically, you can go from the fisheye lens to the telephoto lens. And, you know, how squished it is, how round it is. I mean, it's like aspect is probably going to be your screen aspect. But you can do special effects with it. You can squish things by changing aspect ratios and those kind of things. It also tells you how powerful a lot of the major things are. A lot of the matrices are in OpenGL.

Because it allows you to actually change some things that, I mean, because you have a square window, it does not mean you have to have a square projection. It can squish it. It can stretch it. It can do whatever you want. GL Ortho is an example of how to do an orthographic projection. Thus, you can do a parallel projection, and it specifies instead of a frustum, it specifies a box.

And GL viewport allows you to set the X, Y location and the width and height of your drawable inside, of your actual rendering area inside your viewport. So that's something nice to do. Also you can move it around and you can move windows off. There's other nuances there as far as like using a buffer rack in AGL, but viewport allows you to do the basic GL setup.

Basic primitives: Points, lines, triangles, quads, polygons. Real simple, I guess saying this is actually pulled out of the draw a square code, which you'll see later in its full wonderfulness. Setup a color, call three vertices, and end. Actually that draws a piece of the square, that draws a face of the square. Or a face.

And you can do that, I mean this can be complicated. For example, the Maya demo you saw. They don't use the OpenGL internal NURBS kind of calculation. They tessellate everything and they turn everything into tri-scripts. So they have, they basically, in their code, you're going to see GL, you're going to see a GL triangles, or a GL tri-script, and then you're going to see three vertices with color, with some, with a texture coordinates or whatever. But they're basically doing the same thing. It's just a low level drawing primitive.

Alpha blending. Alpha blending is real simple, simple transparency. And what you do is you have to enable a blend mode. It's again a state machine. You can, normally it's not enabled. When you enable a blend mode, you can then set your blend function, which basically tells what the foreground and what the background does, and then you basically set, instead of your color, which you noticed before I had set a color. This time I set up an alpha value in the color. So I use four components and the last being the alpha value, and the alpha value says this is 50 percent transparent, and I do the same thing I did before.

we got. Okay. Let me show two demos real quick. And these, these are, I have to say, the idea with these demos was to make something really simple to show some of the things that OpenGL can do. So, so this is not supposed to be Quake. This is not supposed to be, you know, the next great app because what we kind of get is the spinning square. You know, this is a good place to start. You're looking at something that really works. You get, you get a square and you can go from there. So that's, that's the spinning square. So that's the setting with no, with no blending or alpha on.

Why don't we turn on, let's see, let's : So basically I pulled the code that you saw on the other monitor out of that and basically I just do an alpha blend with a square. I mean, it's not great, but it shows the effect and you can do some cool things with it. So, I'm going to go back to the texture mapping slide now. You can go back to the PowerPoint.

So, in reality, I mean, flat objects, objects that have smooth shading, don't really, aren't really exciting. As you saw in the demo this morning, as in the keynote, it's really a lot more exciting when you put the texture mapping on there, when you've got a scene that looks, looks lifelike, pops out at you. That's when it gets real interesting. So, steps in texture mapping.

How do you texture map? The texture mapping is a little bit strange when you first look at it on the Mac, because you kind of understand that you supply this buffer to OpenGL, and you want to use that for a texture, but you're kind of like, well, how do I get the buffer into the Mac, and how do I tell OpenGL to use it, and what's the difference between, like, a GWorld and a buffer? So, basically, you need to create and draw your texture and set your texture parameters, and then you enable texturing. The enable texturing is easy. That's basically how I'm going to put my code down there, and I'll show you code on the next page.

To create a texture in OpenGL, the simplest thing is to draw anything you can into a GWorld. So, for example, you use QuickTime. I love using QuickTime, and you can use, read any file format you want. basically want to save things as, and you read it into a GWorld, Then you would do what's called swizzling texture, swizzling pixels. You have to actually put the pixels in an order right now. This isn't until when with the packed pixel format. This is one reason packed pixels is a really good thing to have.

But right now you have to move those pixels into a buffer that has them in an order that OpenGL expects. So for example, most textures you may want RGBA. If you say your texture is RGBA, you set up a buffer that just has a width and height times three components times 24 bits size buffer of RGBA.

And then you extract components from your GWorld and put them into that buffer. It's not really difficult to do. There is sample code. I'm not sure if it's up yet, but it will be up this week. That tells you how to do that and it's basically a 1015 line function. It's pretty simple to do.

And it's not that slow either. You can do some good stuff with it. If you really want to be aggressive, you can go and use the velocity engine and optimize that using the permute instructions to blast pixels in. But for me, I just picked the right pixels out, put them in the right order, and moved them over. And it works pretty well. So the first part is set track texture parameters. Basically, these are kind of some standard settings for texture parameters. I set up some filtering for it so it knows how to filter textures.

Then here's the actual meat of it. We enable texturing, state machine again, we make sure we enable 2D texturing. GL text image 2D, and this actually, this is probably easier to look at in the documentation than it is on the screen, but the key here is that basically I have three components.

I pass the width and the height and then I tell it it's RGB, it's a 2D texture, unsigned bytes, and I pass the buffer there as a pointer to my buffer, which I've extracted from my G World and put in the right format, and that's the texture. So that tells GL what the texture is.

I can then go, the same thing I did before, which is basically say, hey, I got the face of the square, make a quad, but also I've added the GL text coordinate, and then GL text coordinate is pretty simple. Texture coordinates are set up to be zero to one. So if I have a texture that's 512 by 512, it's zero to one as far as texture coordinates, so assuming that I'm mapping it to one single polygon, it's real simple to set up.

When you're mapping to multiple polygons, it can be a lot more complicated. One thing you should look at is another GLU function, is a GLU textgen function. It's a fairly complicated function, probably beyond the scope of this talk here, but it's something to look at. Look at some of the sample code that uses it because it really can be an interesting function for texture mapping on more complicated surfaces that you don't want to calculate every single texture coordinate yourself. What else was there? Another note on textures is textures should be powers of two. Our implementation right now specifies that texture needs to be power of two, and people will say, "Why do I get white textures?" And so, I talked about QuickTime for image handling.

I talked that the pixels must be swiveled, swiveled from Apple ARGB to RGB until packed pixel format is actually out. And alpha channels are indeterminate in QuickDraw. One key there is that QuickDraw does not support maintaining alpha channels. Thus, for QuickDraw, you're going to need to put your own alpha in.

There is cases where you can put your own alpha, and there are cases where you can put your own alpha in. But I'm not going to talk about that. There is cases where you can read it in using QuickTime and immediately blast it out with the alpha, but you've got to be real careful that you're doing the right thing. White textures.

What things can it do? If you're out of system memory, I think people have seen that with Quake, if you don't have enough system memory there, you may run out of texture memory in the system that we need to store textures into. You can increase the VRAM, or the virtual memory, sorry, increase the virtual memory on this, and that will solve that problem.

It may not ever access that texture again. It may just sit there, but it needs somewhere to store it so it can restore it if the card has to purge it. So, you can have a texture mode error. For example, you didn't turn texturing on. So, that didn't work, or that was the last one actually, or in this case I was referring to if you have 255 by 255, it's going to say I can't, I can't texture this thing.

I don't know how to read that texture in. So it's just going to fail reading and you get a nice white texture. So what kind of texture demo I can have? And this is again really simple. One of the, one of the things that I wanted to stress about these, you know, I'm not going to go into The design of the OpenGL application is that these are all built with a carbonized version of Setup GL, runs on 9 and 10.

The design is to make it real simple, but using Setup GL for both simplifies it. As long as your application is Carbon compliant, Setup GL will allow you to be Carbon compliant. Geoff Stahl So I'll run this, and this makes it at least a little bit more exciting.

Pulling the Maya face from what we had earlier today, putting a marble texture on. And this literally, the code you saw I added was basically the code I have to add. I mean really, going from something that's really nothing, just a flat shaded square, to something that's actually interesting to look at, or reasonably interesting to look at, is not hard. Also, we added the reflection there. The reflection was just using an alpha blending. Real simple stuff, but something that is not hard to do. If you haven't used OpenGL, you can use it. But with Setup GL, it's pretty easy to get to this point.

Can you go back to PowerPoint? So we're going through that. The last thing I'll cover is some references. Big time. If you're looking at open GL get the red book. The red book is the OpenGL programming guide. Also if you want a reference manual. I can go back and forth.

If you can download this specification from www.opengl.org or you can actually buy the blue book and buy that as a reference depending on what you like. I think the OpenGL specs in PDF format and you have to have, if you want to print it, I think you have to have a PostScript level 2 printer to actually print it because of the font handling.

But as far as the programming guide is really critical to have and it actually goes through kind of step by step through all the pieces of OpenGL. Goes through a lot of examples. Go through a lot of kind of hand holding to show you how things work without just sending functions at you. Where the reference manual is just a function reference. In alphabetical order the whole book is just function reference. So they're both critical to have in different ways.

Online. www.opengl.org. Great place to go. A lot of developer documentation. A lot of white papers. Tremendous amount of things that you can find there if you look around. People ask me questions sometimes and I go there and I search around a little bit and I'll find the answer to their question that I may not have known just by something else that someone wrote.

Mark Kilgard has some great papers out there. Michael Gold has some great stuff out there. Steve Baker has some great stuff out there about some of, I think Mark Kilgard has the 16 common OpenGL mistakes that almost everyone makes. It's a good thing to read when you're getting going with OpenGL. And also list.apple.com.

Easy thing to do is just go to list.apple.com, search for OpenGL and you'll see the OpenGL list. Subscribe to that, ask questions. We monitor, the engineers monitor the list and we try and answer a lot of questions there and that's a really good thing to get information on Apple's OpenGL. And I'll be in, when we have the seeds ready, they'll be announced there. When the full screen support is out there, that'll be announced there also. So it's a good thing to look for. Okay. I think that's about all I have. Thank you. Ah, key. Roadmap.

OpenGL Mac OS X. Dave Springer's going to talk about that. That'll go into a lot more depth than I did, and I'll talk about OS X-specific OpenGL. OpenGL Beyond Games talks about using OpenGL for non-gaming applications. We're talking about handling multiple windows, how to texture map a movie onto a surface, and things you can do with it.

You don't have to use OpenGL. You can use OpenGL for, like, a 2D sprite engine that gets you a lot of special effects for free. It gets you rotation, it gets you translucency, it gets you all these things for free, and you can take advantage of the GL hardware.

Our OpenGL tech lead is going to talk about advanced optimization techniques following that, and then we'll have the feedback form after lunch after that. And I welcome you all to please come to the feedback form, tell us what we're doing right, tell us what we're doing wrong, and give us suggestions so that we can move forward.

Okay, question and answer? And actually, this lies. I want to bring Bob Beretta up on stage, who is one of our OpenGL engineers. He's the guru. So when you ask a hard question, he's going to answer it. So, Bob. So, if you have a question, please come up to the mics and ask your question.