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: wwdc2008-702
$eventId
ID of event: wwdc2008
$eventContentId
ID of session without event part: 702
$eventShortId
Shortened ID of event: wwdc08
$year
Year of session: 2008
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2008] [Session 702] Getting Sta...

WWDC08 • Session 702

Getting Started with OpenGL on the Mac

Media • 1:09:47

OpenGL provides access to high-performance graphics hardware on Mac OS X. Get started with OpenGL development and learn how to develop OpenGL applications quickly on the Mac. Gain a strong understanding of the design and construction of a new application using OpenGL and Cocoa. See how to take your application full-screen, load texture data from a file, render geometry and control graphics state. Understand how to leverage GLSL and the GPU to support more advanced rendering techniques. Attend this session to gain a thorough understanding of OpenGL best practices and explore the power of OpenGL in Mac OS X.

Speaker: Geoff Stahl

Unlisted on Apple Developer site

Downloads from Apple

SD Video (849.6 MB)

Transcript

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

Good morning. So this morning, Tuesday of WWDC, we're going to actually start into some of our sessions. And this one is getting started with OpenGL on the Mac. And it's an interesting session because it talks to a few audiences. It doesn't talk to someone specifically who's really experienced on the Mac or really experienced with OpenGL on the Mac, but it does talk to people both who are new to the Mac or maybe who are new to OpenGL. So I'm Jeff Stahl. I work in GPU software, and I'll be taking you through our session today.

So the first thing we're going to talk about really is what is OpenGL. So there may be some of you in the audience who are experienced with OpenGL who actually know what it is. In this case, it will just be a little bit of a refresher. Talk about why use it.

We'll go into some reasons why OpenGL is interesting both from a 3D games aspect or from a 2D application aspect. Because I think that one thing you saw yesterday from the keynote and the State of the Union addresses is that OpenGL is really a great way to get accelerated graphics, not just how to do 3D games.

Then I'm going to talk about learning OpenGL. So the folks in here who may not know OpenGL at all, I'll give you some resources, point you in the right direction. So after this session, which you've taken some nuggets, but really you're not going to remember every single thing I say.

You'll have places to go to find the information you need to work with OpenGL on Mac OS X. And taking this session, combining it with the session this afternoon on OpenGL ES on the iPhone, I think you'll have a great start on working on OpenGL ES on the iPhone also.

So next thing I'll go into is a little bit of an intermediate level topics. We're talking about platform specific data and things you need to know to really get started with OpenGL on the Mac. A little bit about the architecture on the Mac OS X where it may be different than other platforms.

A little bit on OpenGL ES on the iPhone to kind of get you prepped for this afternoon. At 5 p.m. we have a session specifically on that. And then finally, I'll finish up with some techniques that involve combining the Mac OS API with OpenGL ES on the iPhone. with OpenGL and talk about our tools.

[Transcript missing]

So OpenGL, what does it do? The basic thing that OpenGL does, it takes vertices, transforms them, applies visual operations and outputs a fragment. And that's going to be a little bit different than we talk about later in the week when we talk about OpenCL. Because OpenGL really has this many-to-one or this gather kind of concept.

We take vertices, determine where the vertices will be on the screen from 3D space to 2D space or from 2D space to 2D space if you're just working in two dimensions. And then we actually determine what fragments that covers and OpenGL iterates across those fragments. So let's see actually how that looks.

So we take something, this kind of zoom-in shot from Modo, from Luxology, and let's look at kind of what you would think about this in 3D space. So you have a grid. You have a grid of polygons that cover this in 3D space. These are the vertices you send in.

And if we zoom in on one little area right here, we can see from the triangle standpoint, there's this one triangle we're going to focus on. That triangle is sent in in 3D space. It's transformed to be 2D space. So instead of thinking of that triangle as perspective, actually think of it as the pixels it covers relative to your viewpoint.

So what that comes out is you have, there's a triangle. And those are the actual pixels that make up that triangle. And what OpenGL does is it actually iterates across those. It's iterating across each one of those pixels, taking the texture coordinates that you've passed in when you drew this image, and it actually colorizes each pixel based on the texture lookup. It's actually, when you break it down, a pretty simple operation.

I mean, it takes, it does linear math on a set of vertices to convert to 2D space. And then it interpolates from one end to the other and draws colors. That's all it really does. It happens that the colors have meaning to us. That the 3D graphics we have have meaning. putting those all in the 2D space really gives you the picture you're expecting.

So, moving on, let's look at OpenGL ES. So we know what OpenGL is. What's different about OpenGL ES? Why is OpenGL ES different and why is it not in OpenGL? Well, OpenGL ES has a specific purpose in life and that's to support embedded systems, obviously the OpenGL ES. It's actually a reduced form of OpenGL.

It takes some OpenGL 1.5 and it kind of optimizes it. It takes out some of the kind of crufty older stuff and makes it so it really fits well on embedded systems. You'll find that many apps, if you write a modern OpenGL app, it'll work very well in OpenGL ES in most cases. And we'll talk about that today, how you can go from an OpenGL app, or we'll talk about it later today, this afternoon, go from an OpenGL app to an OpenGL ES app.

It removes some redundant pieces of the API. Obviously, OpenGL evolves over time and ES had a nice idea of it could take a snapshot. It could say, okay, what do we want from this piece of time? And it could say, we don't need this. This has already been superseded by other things we have. So it could remove those at a time.

And also, the one important thing about OpenGL ES, it doesn't require some kind of software fallback. So in almost every case, you can assume your hardware accelerated on your embedded platform. So a little bit, OpenGL ES, same as OpenGL, kind of in mindset, a little bit different in focus. Thank you.

So what is OpenCL? We talked about OpenCL yesterday. OpenCL is kind of a new thing, but isn't it the same as OpenGL, or isn't it like OpenGL with some stuff added or taken away? It's actually a completely different code path on the top end. It's a completely different API, and really, it's compute focused.

It can use the same graphics hardware, or it can use the same CPU underneath, but the idea is you basically build compute kernels, and you execute them on the graphics hardware. It doesn't know anything about 3D. It doesn't know anything about graphics, or pixels, or those kind of things at all. Think of it as just a computation engine.

But if you wrap your mind around that, you can say there are some things you used to do in OpenGL that weren't really 3D operations. For example, the denoise operation we saw yesterday in the demo. Denoising that movie is not particularly a graphics operation. Sure, you're working on pixels, but you're really working on a pile of data.

So really, it's an algorithm run on a piece of data. And so OpenCL kind of focuses on that. It's a very simple API. It just executes kernels. It's designed for parallel data. You can get very low latency across the multiple CPU cores you have, or you can do access to a GPU, and it's very high bandwidth of working with data. So the idea is performance critical data parallel algorithms are the target for OpenGL.

So I mentioned the OpenGL.org site. I mentioned Kronos. And so what is Kronos? Kronos is an international standards body and it has over 100 member companies. The interesting thing here is it actually controls the specifications for OpenGL, OpenGL ES, and we've opened a new compute working group and Apple is proposing to Kronos a standard that we would like to be the basis for OpenCL also to come under the Kronos auspices.

And as you can see, some of the leaders in the industry in the graphics area and also in embedded technology are members of Kronos and promoters of Kronos. And we're very involved in this. We want actually to produce APIs that can be run on multiple platforms that are standard internationally and you can actually adopt and be comfortable in adopting that you're not going to be kind of scattered and taking a shotgun approach to how many APIs you use in your application.

So I've kind of talked to this already, but I think we definitely want to talk about why should you use OpenGL? Why is it interesting to you? Why are you sitting in the audience today? What is interesting about OpenGL? So it's a graphics hardware abstraction layer. As you saw again yesterday, the horsepower in the GPU is phenomenal. And it doesn't even matter in some cases if you're using OpenGL. You may actually want to use a CPU for some high-quality render or something like that.

So OpenGL can also go that route. It's not required to get to the GPU, but definitely it is the gateway to get to the GPU. So it's basically, as I've said, it's the way to do high-performance graphics on Mac OS X. So anything from, you know, you've got Doom, kind of games to get that kind of thing, to Google Earth. So this is massive streaming textures. So you're streaming textures to something. You're applying it over a mesh or on a flat surface with perspective, and you can get like a Google Earth kind of application.

Or you can do something like iChat. iChat, the video effects. We use OpenGL to enable that kind of immersive, interesting feel for that iChat conference. And also, you've probably all worked with iChat effects. iChat effects obviously power with Core Image and OpenGL. Again, using the GPU to get access to that graphics hardware power.

So OpenGL today is this kind of, it's used in Mac OS for 2D effects, used for the windowing services, so we talked about Expose and the windowing compositing system use it, image processing and digital video effects. Also, another thing is for people in here who think, you know, after this talk, they're thinking, you know, OpenGL seems a little bit too low level for me. I need something a little bit higher. We have that.

We have Core Image, we have Core Animation, as we talked about yesterday, which was originally developed for the iPhone, is also available on the desktop. We have Core Video, Quartz Composer, which is a great way to simply prototype or to build very high level applications as the graphical programming interface works wonderfully. And also, we have Quartz GL, which is the acceleration of desktop elements through OpenGL. And these pieces you can either adopt or sometimes you get for free.

So, you can use OpenGL with your apps. And you don't have to use OpenGL, but underneath the covers you will be using OpenGL. So, things you take away from here will actually give you a better understanding of how these pieces work. They're all built on top of OpenGL. There's no real secrets here. There's no weird wire that goes in the back. These are all built right on top of our OpenGL implementation.

So we talked a little bit about OpenGL and OpenCL. I want to kind of stress the difference here because there is definitely a choice between the two. So OpenGL, graphics-centric obviously. So things like StarCraft II, if you're building into the next StarCraft II, I would be the next, next thing. But if you're building something like that, like we see in the picture up there, OpenGL is like the way you want to go. That's something you want to have. A 3D graphics game application makes sense to use OpenGL.

But then if you're doing protein folding, if you're doing protein folding, you're going to have to use OpenGL. So if you're doing protein folding, it's an algorithmic simulation. A simulation of protein folding. It sure has a graphical interface, but really the algorithm behind it is very, is very a scientific kind of algorithm. It's a compute-oriented algorithm.

It's not a graphics-oriented algorithm. There's a display component of it. But in that case, you probably, for the algorithm side, OpenCL is a great place to look. OpenGL also is very broad. All of our, basically all of our hardware that's been out for since about 2000 support OpenGL in one fashion.

Some of the hardware, obviously, is less capable. Some is more capable. So you have to do a lot of some work to figure out the capabilities. You have to figure out, am I on an integrated graphics machine? Am I on a desktop with a very high power discrete graphics? Maybe I have two graphics cards. So you have to do that work.

For OpenCL, we have a more constrained market. There's only a certain level of capability in graphics cards that actually support OpenCL. So it's more limited hardware choices, but the hardware choices have the same robust feature set across them. So there's, if it works on, the hardware you have supports OpenCL, it supports OpenCL. There's not a lot of choices, and you don't have to write a lot of different code paths in your app. So both have their advantages, but may affect your adoption.

So let's talk about learning OpenGL. So I figure some of you in this room probably have not used OpenGL and want to know how to learn it. I'm not going to do a 101 OpenGL. We could take a week kind of doing that depending on what topics we wanted to cover. But what I will do is talk about resources for learning OpenGL. And I'm serious when I'm saying there's a lot of resources out there.

There's a tremendous amount of reference material both in books and on the web that really probably cover most of what you need to do to get started and get started and move very quickly into getting good content out. I find that either from our reference library or web references, you almost always can find something that someone's, to solve the problem that you have using OpenGL. So first, OpenGL.org. I mentioned Kronos before.

OpenGL.org is the website for OpenGL. I suggest you bookmark that. On that website is the OpenGL specification. So I would go to the website, get the specification, and use that as your reference material. That should be the thing that you have on your desktop in your reference material folder and that you use it while you're programming OpenGL.

Also, if you're learning it, simply search on the web for some OpenGL tutorial. You'll come up with a lot of things. A good example is the Nehe tutorials. There's 40 or 50 tutorials that are just little kind of snippets of code. They're not perfect, but they actually do show some definitely interesting techniques. And so if you're brand new to OpenGL, these are a very good way to actually kind of get some ideas and get started in what's going on.

The Red Book is the OpenGL programming guide, affectionately known as the Red Book. The Red Book is a great take you from the very beginnings to reasonably advanced in OpenGL. The caveat I have is it's been updated over time, but it still uses some really old programming paradigms. So we'll talk about that a little bit later. But the Red Book, good book to have, but be careful about how modern some of the techniques are.

The Green Book. The Green Book just came out recently. The Green Book is basically OpenGL programming on Mac OS X. It's a, I'll say, a complement to some of the things we have on our developer website. It talks about Cocoa. It talks about performance on Mac OS X. It's probably a good book to definitely peruse and look at and decide if it fits your needs to go out and purchase that also. And finally, developer.app.com.opengl. This is a, I'm going to bookmark this as a great resource for any person developing OpenGL.

First, sample code. Almost everything I'm going to talk about today is available in some form or fashion as sample code. So you can grab the sample code, download it, play with it. It may be a little bit more advanced than what I show or maybe a little bit simpler than what I show, but it's probably up there. Also, there is the OpenGL programming guide for Mac OS X.

That was recently rewritten a few months ago after a major rewrite a couple years ago and it really is up to date with the latest techniques. And when I talk about virtual screens later and you're going, what the heck is he talking about? You can go to the programming guide.

They have a complete section on it. Read through it and I think you'll understand where I'm coming from and you'll understand the techniques behind it. It will really help you in the future working with OpenGL. So those are some resources to actually when you're working with OpenGL. So I think that's the end of the kind of intro about OpenGL, where to learn it, what it is. And so let's talk about something that's really Mac specific. So we're talking about Mac specific data. So OpenGL spec is a cross-platform industry standard. What that means is it takes into no account the windowing system on that platform.

So it doesn't know anything about Cocoa. It doesn't know anything about Carbon. It doesn't know anything about an NS window or a view. Nor it doesn't know about our iPhone and its Eagle API for getting access to the OS specific pieces. So it is just talking about GL drawing triangles, textures, those kind of things. So there are a few pieces of data that are critical for working with Mac OS X you should understand. Virtual screens, pixel formats, context, and drawables.

These are well documented. I'm going to give you an overview of them here, but I really strongly suggest, again, that you go to the programming guide after the session, later on, and look through it. Because I think you'll see that you'll understand if you go through that. And I can't really stress that enough, because if you spend an hour this evening reading through the programming and skimming and understanding those concepts, the rest of it will be easy.

If you don't, you'll end up copying code from a sample. And you'll probably use that code significantly without really understanding the nuances of it, which later on, I'm sure there'll be something that comes along. They'll be like, oh, yeah, that's why I was doing it this way. So I really suggest take a little bit of time to look at that, because it'll really help you in the future.

So desktop-specific data flow. So what are these things, these pixel formats and these virtual screens and stuff? So you have an application in gray down there. The first thing you do is create a pixel format. So what is a pixel format? A pixel format is really just made up of two pieces. To specify a pixel format, we have two pieces of information. One is the render attributes.

And the render attributes are things like accelerated, or software, or a specific render. It actually determines the list of renderers that you can support with that pixel format. So it makes sense. You have the things that say, I only want accelerated renderers. Or I want only software renderers.

Those are render attributes. The other thing is buffer attributes. And buffer attributes are things like double buffer, or depth buffer, or how deep the depth buffer is. All those things are buffer attributes. So when you think about it, you have render attributes. And then you have the list of buffers you're going to create and how you're going to create them. Those are those two pieces that make it up. So in pixel format, you specify the two pieces. A really simple thing is just to say, accelerated double buffered, or just double buffered. So that would be a basic starting point. But now you understand where that comes from.

So once you have the pixel format, you can build the context using the pixel format. So you're basically telling the context, when you give it a pixel format, what kind of things you're going to support. What kind of the accelerated are you going to support? What kind of set of buffers are you going to create? The key here is a context.

The OpenGL context-- think of that as a big state bucket. So OpenGL is a state machine. OpenGL takes-- the best way to describe for OpenGL on a state machine is you have a pen. And the context is your pen. And you pick up a pen. And let's say it's a fat blue pen.

And you start drawing with it. Until you change that and change your pen, you have a fat blue pen. If you pick up the thin red pen, then you actually make calls. You say, I'm going to change my current color. I'm going to change the type of pen I have.

If I clear color, all those calls are setting states. So until you change the state, it keeps that current state around. So the OpenGL context is really like the pen. And it contains the state. So really, what your current state is is what kind of pen you're drawing with.

Once you create the context, you can, if you want to, get rid of the pixel format. It's only used basically to tell the context how it's supposed to be created. One reason that they're separate, you think, well, why aren't they together? It's because you may want to create one pixel format and create multiple context. So the pixel format is a separate piece, and you can keep it around or throw it away as need be.

So we'll throw it away in this case. Then you create a drawable. So the drawable is your view, your window, a full screen, all those things make up drawables. And basically that provides the surface dimensions. So remember the buffer attributes determine depth. They determine whether you have a depth buffer and how many buffers you may have. So when you put all those together, you get drawable dimensions, you get types of drawables, and you get the types of renders that are supposed to support those.

When you actually instantiate this and attach, you actually pick a current renderer. So for example, I have a screen attached to a graphics card. That would be the current renderer. Maybe this graphics card that it's rendering on the screen. And the target surface, the OpenGL buffers get created. So when you actually use OpenGL, the application issues calls through the context. You always have a current context for a call. So every GL call has a context it's going through. The PIN it's using.

They issue the call through the current context. It uses the current renderer and draws to the current set of buffers, which then are shown on the drawable on the screen. So if you make sense, all these pieces of information are specified. And again, this is all referenced in some of the reference material I talked about earlier. So you can review and go through it and understand it.

But understanding this kind of concept initially is very good. So virtual screens, we talked about those a little bit. Actually, we didn't talk about particularly virtual screens. Virtual screens embody this kind of concept of, of a renderer in a pixel format. A virtual screen, so my two examples were accelerated or software. And those things could be limiting yourself to a single renderer. What say you didn't specify those? You just go double buffered. Well, what kind of renderers could support that? Well, you could support your graphics cards could support it. And your software renderer could support it.

So what that means, you might have two virtual screens. You have two renderers associated with a pixel format. And basically, any time you change virtual screens, you can look at your renderer, and you can see, oh, I have a virtual screen. Any time that changes means your renderer changed.

Why is this important to you? Why do I care about virtual screens? Can't you just have one virtual screen? It would be a lot easier. You wouldn't even have a slide for it. But if you understand that you might have multi cards, the cards may be disparate capabilities. The software renderer may not have the same capabilities as the hardware renderer. You may want to know about those kind of things.

You may actually have a card that's not connected to any heads. It's just their compute asset or graphics asset. And in that case, when you change to it, you want that, that flag to say, hey, you've changed virtual screen. So basically, you're going to have a virtual screen. Basically, you have one virtual screen that's active at a time. One renderer is active at a time.

Your virtual screen will change when you change renderers, and you should check to see what capabilities are available. If you do this, you'll be extremely well-suited for handling multiple cards, multiple heads. Someone puts a projector in with a different card or something like that. Things change, you'll understand all those kind of things.

One thing we haven't talked about much in the past is to allow offline renderers. It's something new we've added. We've added it to be able to use multiple cards as just rendering assets. So for example, if you have a very high-end application that you want to do a lot of rendering on, and the card that's connected to the display is not enough power for you, you can now go out and buy an extra graphics card. You don't even have to hook a device to it.

It's still a compute asset. It's still powered up. It's still there. You can still set the virtual screen to go to it, and you can actually render on it. So you can use it as, like, I'm thinking of kind of Final Cut Pro kind of app. If you're doing a Final Cut Pro and you have this lot of offline rendering you're doing, you can have one card just displaying your content and one card working as a kind of computational asset.

In fact, some of the demos we showed yesterday with OpenCL, OpenCL takes advantage of this. Two cards in the machine, one card was a compute asset, one card we used for OpenGL. So in this way, you can take advantage of that, you know, tremendous horsepower that just may be sitting idle in the machine. Again, allow offline renderers, shows renderers that do not have a display attached to it.

And at the end, it might be interesting to get a render ID to know what kind of renderer you have. This is the kind of way to do it. You get render ID, and render ID is supposed to be with the families of renderers. You have the GeForce render ID for various GeForce families, and the Radeon families are the software render ID.

So if you want to say, hey, am I on the software renderer, you can use this little snippet of code. This kind of code is, again, in the resources. It's not, you don't have to copy it down madly, because all these code pieces are taken from other samples or resources I'm going to talk about.

So pixel formats. I think we talked a lot about those already. I wanted to highlight some options you have here. So offline renders, we talked about that. That's something that goes in the pixel format. Require accelerator renders. Accelerated again or no recovery. So what that says is, accelerated says, the key here is I'm saying require accelerator renderers. Accelerated says I definitely want an accelerator renderer.

No recovery says I don't want to fall back to software ever. So if your application needs to run on an accelerator renderer all the time, those are the things you're going to want to do. So those are the two things you want to specify. If you want to run in software, for example, let's say you want to run on the CPU. You have the GPU doing something else. We have some applications internal to Apple that do high quality rendering kind of in the background on the CPU while the GPU is doing something else.

You can specify that with a render ID and it gives a generic float ID. That's our current floating point software renderer. And then one note about this, just for trivia's sake, is our new software renderer actually is hardware accelerated. We actually do all the work in software and then we actually use a graphics card to help blend those things onto the screen.

So we actually only touch the pixels we need to touch and we can, if you're going to the screen, we actually use the hardware to assist getting those pixels on the screen to make it even faster than it ever has been. And finally, if you really just wanted to render to system memory, you can use the off screen. This won't be accelerated, but definitely will give you a system memory buffer with your results.

Context. Again, we talked about many of these things already. State bucket. It really represents the open jail state. It's the pen you're drawing with. So you need to change the pen when you want to change your drawing. And remember, you can do something over here with that red pen.

Program goes on, goes off in subroutine, goes off in the function here, goes into some other thread over here. You come back and you start drawing again. What are you drawing with? You're drawing with the red pen. If you didn't change anything in that context, you're still drawing with everything you set. So it's not like a set and reset. You don't set some things. You can do a function and have it reset back to current, what you default automatically.

This does mean there's a thought process in handling state. The thought process is you don't want to make two mistakes. One mistake is you overset state. You really absolutely define every single state change for every single time you draw. So you don't want to go, okay, I'm going to set the color, I'm going to set the clear color, I'm going to set the blend mode and go through all these states no matter whether you changed it or not. It's just a waste. State calls can be expensive.

Having this huge amount of state setting and then draw and then a huge amount of state setting and then draw is probably not the right approach. The other approach is actually probably not correct is to say, okay, I have default state. I'm going to change a few things from default and now I'm done with that state. I'm going to change them back to default.

I'm going to change some things to default. I'm going to go back to default. That's not a good approach either. The best approach actually is to understand the states you need to draw and do the minimal amount of changes to get to those states. Some bookkeeping on your end? Yes.

And you may not want to do it everywhere, but you definitely want to do it in the cases that are performance critical. You want to minimize the state changes, coalesce states of the same, and actually try and draw everything with the same pen at the same time. So instead of drawing the tree with the green and the brown and some flowers on it and then going over to the bush which is green and brown and has some flowers on it, you want to draw all the leaves and then all the brown twigs and bark and that kind of stuff and then all the flowers. If you want to think about it that way. That's the efficient way to do it.

[Transcript missing]

I'm sorry, that's Wednesday afternoon. Wednesday afternoon, I believe it's the last session of the day, so it's 5:00 PM. We have a performance tuning for OpenGL, and that session will talk about the multi-threaded OpenGL engine and how to turn it on. And I suggest, again, that some apps, depending on your CPU load, can really benefit by that. Finally, one thing you want to note is in OpenGL, they're not normally VBL synchronized. So if you do want to synchronize yourself with a vertical blank, you want to turn that on.

Drawable. This is really, this actually is pretty simple. It's just your pixels in RAM or VRAM. It actually represents your screen or your window or that kind of thing. So it could be full-screen, it could be a view, it could be an off-screen, that kind of thing. So let's move a little bit on to a little bit about architecture. Now I've covered all the data types.

I've covered kind of how these pieces fit together. Let's talk about the architecture. So you've seen this kind of diagram before. So this is Mac OS X user experience applications all the way down the kind of complete stack. So what are we talking about right here? We're talking about the space between OpenGL and kind of the application frameworks. What's the architecture there? And it's pretty straightforward actually. It looks a little bit complicated.

But I think if you understand that you kind of have, it's like a kind of a menu. On the side with the gray box, you actually pick one of those kind of interfaces. Those are the different system interfaces. We have a GLUT, which is a very high-level interface. We have NSOpenGL view. We have AGL as a Carbon interface. And we have CGL as a really low-level interface that things are built on top of.

And then also you obviously have the green side, which is the OpenGL. Your application will talk to pixel formats and context via one of the gray pieces. And you'll talk to OpenGL via the green side. So that's kind of, you kind of have a piece that is the application windowing system API. And you have another piece that's actually OpenGL itself. And those both talk to the OpenGL engine.

Four interfaces I'm going to talk about. NSOpenGL, CGL, AGL and GLUT. I think I already talked about it. NSOpenGL is the Cocoa interface. So that's the windowing system interface that's set up for OpenGL and Cocoa. CGL is our low-level interface. You probably want to use it if you're a full-screen app only.

AGL is the Carbon interface and GLUT is a kind of a high-level, source-level cross-platform interface that has some event handling. It's a pretty simple interface. So NSOpenGL, Cocoa interface. This is an NSOpenGL view. It's a subclass of NSView and you probably want a subclass NSOpenGL view for your own application. Contains a single pixel format and context. And the reason that's important is if you find you want to do multiple contexts, multiple windows, you realize you probably don't want to use NSOpenGL view directly.

What you probably want to do is we have a sample that shows you how to basically replicate that capabilities and extend it. So you can use the sample as a basis to extend NSOpenGL view in a custom direction. You can create it via Nib in interface builder. There's, like I said, there's some special cases with context and pixel formats. And there's a lot of sample code using this so it's really simple to instantiate. So why don't we go to the demo machine. And I'm going to show you how to do that.

And we'll talk about how to use, how to set up your first OpenGL application. No tricks, nothing up my sleeves. There's nothing, I've done nothing to the demo machine. So I'm gonna, this is, after the session, this is exactly what you can do. So you can launch Xcode. We'll create a new project. A Cocoa application. We'll call it OpenGL Getting Started.

So this is my OpenGL application, but it really doesn't do anything now, obviously. So the first thing we want to do... Outstanding! Love that! No, we don't want to. Luckily that's not my part. Let's just call it GL. Maybe it likes two letters better than a C. Maybe we're better this time.

Didn't like me resizing probably before. So the first thing we'll look at is we'll look at our nib. The way this starts out, you have an empty window kind of thing in your nib, and you really need to put something in it that represents OpenGL. So what we have is this is your window right here, and over in your library you have an OpenGL view, which represents the NSOpenGL view. So we can drop it in here. We'll resize it out to be a reasonable size for your window. And then we'll go up to the inspector here and do a few things. First, let's make it a subclass.

So it's my... So we do my NSOpenGL view and additionally we'll go into here and we will look at this first pane of the NSOpenGL. This first pane is a lot of those things I talked about in pixel formats. You notice there's a double buffer, there's stereo, there's multi-sample, default render, allow offline. All those things are things you can specify. So in this case I'm going to go default color and what's at a depth buffer of 24-bit just so we have it and we'll make it double buffered.

So that's basically my pixel format definition if you want to look at it that way. So I do that and the last thing is we want to make it so it kind of actually looks nice when we zoom around. So we'll make it so it expands with the window. We'll save that and we will write the class files.

Don't want to do Ruby, we want to do Objective-C. And there we go. We'll add it to our project. So if you notice in the background we've got some things added to our projects. We'll quit that and if you notice now we have these two NSOpenGL view. They're very empty though so it's not particularly interesting.

So let's make that a little bit bigger. So this is the Vue.M. It doesn't do anything. Now here's my little trick that you probably have seen before. Obviously, we have a little bit of pieces here. But what's interesting is to draw OpenGL, all you need is that piece.

It basically says make my context current, set a clear color, and clear the buffer. So all we're doing is really clearing the buffer. And then at the end, the flush buffer basically pushed my data to the screen. So I'm going to copy that, drop it in here. Save that.

Oh, shoot, I know what I forgot. My app, my project doesn't know anything about OpenGL. So we also need to tell it two things. First, import And we'll do, this is a framework so if you're not familiar with Cocoa it's basically like that. And it's gl.h is the header you want.

And the last thing is, in here when you create an OpenGL view, they want you to specify the subclass. So in this case, it's going to be a NS... Send us OpenGL view subclass. Thank you. Xcode is good about telling me those things too. Now let's see how we're doing. Hmm hmm hmm hmm hmm.

Okay, oh, oh, it's this thing, I have something wrong here, oh. Jail clear. Oh, last thing, I did forget one more thing. Frameworks. So it has some frameworks included, but it does not have the OpenGL framework. So if I have a right click, I do. Let's do this. Linked frameworks. Add existing framework with OpenGL's existing framework. Takes you right there. We'll scroll down.

And add OpenGL framework, add that. Yes, default. There we go. So all this did, very simply, is build a window that clears its OpenGL view to red. But the interesting thing is that's the basic pieces of the code you need. If you did an NS log, you'd see every time I resize it, it actually calls my draw routine, so that's all done for you. You can add normal Cocoa interaction.

You could add a button to that if you wanted to that triggered some action. But really, this is the basis of getting OpenGL up on the Mac. So there's not kind of this black magic, hard to get your application up and running. If you remember to spell things correctly, link the right frameworks in, add the right header files, then you're golden. It's easy. So let's go back to the slides. All right.

So let's talk for a minute about Glut. Glut is a cross-platform source-compatible API. What that means is it's an API that you'll see a snippet of code on the web that says built with Glut. And you can just grab that piece of code, drop it into an NS new Cocoa project, add the Glut framework that we have, and basically it'll work almost out of the box.

So we have, there's a Glut example in the sample code. It's really a simple API. It has some event handling, has window handling, it's callback-based. It really is kind of good for that quick, I want to test something out kind of thing. But as you saw, Cocoa is pretty good for that, too. There's a few things.

If you want to handle a couple multiple windows or you want to handle certain kinds of input, Cocoa may be a little bit longer, but I think I would recommend going with Cocoa if you're writing something yourself. The reason I bring Glut up is there's a lot of code out there that may be a source file that runs in Glut. And to know that you can just create a Cocoa project, add that Glut framework, and add your source code in, you'll get to see how it runs. So we have support for this on the Mac.

So let's talk about OpenGL ES on the iPhone. I'm going to do a very, very light intro into kind of how it fits into this ecosystem of OpenGL. And today at 5 p.m. in Presidio, we're going to talk in depth about building OpenGL ES apps on the iPhone. And I really suggest, if you're interested in that, you go to that session. All of our engineers will be there, and they'll be talking in depth about this topic.

So it's a little bit different. Going back to that same kind of diagram, a little bit different than you saw before. The application has, as we talked about, a native Windows system API, and then it has an OpenGL platform API, which we saw was AGL or NSOpenGL, those kind of things.

And then there's OpenGL ES down there. And they both talk to pieces of the low-level hardware. What does this mean for ES on the iPhone? What it means is we have an API instead of NSOpenGL or AGL. We call it Eagle. Embedded Apple GL is the Windows system API interface there. And we use core animation, actually, instead of, you know, an application.

We call it an AppKit view or something like that as the kind of windowing system API. So those are the two pieces you'll talk to, Eagle and core animation. And it turns out that core animation actually will call back through OpenGL ES for compositing. So it's kind of like the Windows server you think of on the Mac OS X, how it uses OpenGL.

So you'll go through Eagle, you go through core animation, and core animation could go back through the Windows server or the OpenGL for compositing. What this means is two things. First, you can composite layers using OpenGL. The second thing it means, is that your OpenGL applications can actually, will actually run full speed. They're only composited when they need to be. They can run full speed to the native windowing system.

So basically the Eagle defines the OS interface for OpenGL ES as we talked about. It manages your OpenGL ES context so it's the same kind of context idea, the same idea about context supplies. It works with core animation on the iPhone to display content because that really is your Windows server there. And it provides the configuration of your drawables. So it's kind of the same set of operations, a little bit different way of doing it, the same set of operations that you'll see on the desktop you see on the iPhone.

So finally, the section we want to finish up with here is talking about techniques. I'll go through about three different techniques that will help you interface with Mac OS X using OpenGL. First, I'll talk about a few more than three actually. So I'll talk about five, I guess. I'll talk about detecting functionality. I'll talk about drawing with vertex buffers. I'll talk about texturing. And lastly, I'll talk a little bit about shaders. You may have heard of OpenGL shading language and show you kind of where it fits into the puzzle.

So first detecting functionality. We talked about OpenGL, broad set of hardware support. You may need to understand what your hardware you're running on is capable of. So you can use the Git string to get GL version. So depending on the version, it defines a set of functionality. You can also check extensions. You can get the extension string and say, hey, I need this certain extension that extends OpenGL capability to make sure that I can run my application. You can do that. And the other thing is the Git integer is a way to check limits.

So you can say, like, how big of a texture can I actually load into the graphics card I'm currently running on? The Git integer tells you those kind of things. All this, again, there is a, I believe there's a Q&A or a tech note specifically on detecting functionality. It goes into a lot of depth on this subject. And I'll point you to that as if you want to read more about it, talking about the different levels of functionality in each version of OpenGL, for example.

So, drawing with vertex buffer objects. Why do I want to tell you about vertex buffer objects? Why am I interested in vertex buffer objects? It actually is a fairly advanced topic. Could be. I mean, it could, there's a lot of information out there. But the reason why is because I don't want you writing this code.

I don't want you writing begin, end with a bunch of vertices in it. This is the first example in the first edition of the Red Book and this is basically what we call immediate mode. This is, the best example I can give is, hey, we all have to go grocery shopping at times.

Immediate mode is, I look at my list at home, I say I need tomatoes. Well, I don't need tomatoes. I can't get tomatoes today. I'll eat cucumbers. So, I'll go get cucumbers. So, I run to the store, cucumbers, run back home. Steak, go to the store, get steak, go back home.

Potatoes. Go to the store, get potatoes. Go back home. As you see, you're spending a lot of time in the car. The immediate mode spends a lot of time in API calls. Spends a lot of time begin-end. And think about it. If you have a thousand triangles you're drawing, you could have a thousand begin-ends.

If you have different state changes, you could have more. Quake 3. So Quake 3 is a 2002 application. It has about 10,000 triangles per frame. Think about that if you did begin-end. There's 10,000 API calls that you need to make just to get those triangles to the screen. Vertex buffer object allow you to encapsulate that in a single call. So your call overhead is significantly less.

And in the end, it's just as easy to use as begin-end. So that's my point today is that I'm going to show you how to use simple vertex buffer objects and say they're just as easy as a begin-end. You can get away from begin-end, start out day one vertex buffer objects, and just stay there.

So, vertex buffer object. What is a VBO? Well, it's an object. So there's some object API in OpenGL. And basically, it's a buffer of vertex attributes. Vertex attributes are vertex position, vertex colors, texture coordinates. Those kind of things are vertex attributes. So it's a buffer of those accessible through an object ID. Really simple to create objects.

First, we have a vertex buffer object. It references a bunch of stuff. And in this case, we have vertices, we have colors, and we have texture coordinates. And think of those as each like a buffer, sub-buffer. Inside what the object points to. So the object is your pointer, and you have a bunch of data that you're pointing to. So setting up data for VBOs. This could be complicated, but it really isn't.

This data you see here is exactly the same data you saw with begin-end. So it's just a, I just declared, you know, vertex data and gave some information to it. You can declare it, it can be dynamic or it can be static. In this case, I just declared it statically. And you can actually simply get access to that and simply draw a triangle using vertex buffer objects instead of going through begin-end.

So what are the steps you need to do to use vertex buffer objects? First, you gen a buffer. The gen, glgen is something you'll learn to use a lot in OpenGL. You do textures, vertex buffer objects, everything, all the objects in OpenGL gets generated in the same way. And then you bind to that buffer.

After you bind to the buffer, say, this is current. This is what I'm working on. Remember, state machine. This is the current buffer I'm working on. I'm going to actually load some buffer data. Look at this. I just use size of the vertex data and a pointer to the vertex data. And I say static draw. Static data, I'm going to want to draw it.

So it's a really simple setup for the vertex buffer. And then the last piece is, which is kind of the little nuance of the vertex buffer object, is you have to specify a vertex pointer that points to the beginning of that data and says, here's what I'm going to draw.

So again, we take the type, which is three component. It's float. And we have an offset of zero. So basically, we're saying at the beginning of the data, I have three components per vertex. I have floating point data. That's what you're going to draw with. And finally, drawing, you bind the buffer, you enable it, and you draw with it. Really simple. You can get away from begin, end, forever.

So let's talk about texture loading a little bit. Moving on to a different topic, talking about this more Mac OS X specific. So texture loading, two ways to do it. Either purely through our Cocoa API or through Quartz and Image.io. Through Cocoa, basically, you take a bitmap representation of a view or of an image. And that's pretty simple, straightforward Cocoa code here.

For Image.io, it's a little bit more flexibility, a little bit more code, but gives you a way to look at more like the raw data that you have in the buffer or in the image. So let's jump right in and say, And it's bitmap image rep from NS view. So we have an NS view. So you have an NS view with some content in it, whatever that is, an image or whatever you have. You could have grabbed the view from somewhere else.

Basically, you're going to allocate a bitmap image rep, and then you're going to initialize it with a knit with focus view rec. And what that does is basically says, I have a view, initialize the bitmap contents with the contents of the view, and this bounds. So basically what you're doing is you're stamping down that view onto an actual array of pixels that OpenGL can access. So it's pretty simple again.

Basically, you're going to allocate it, you're going to lock the focus, you're going to knit the view with the rec, and then you unlock the focus. So it's really straightforward kind of Cocoa code. But this gives OpenGL a bitmap that it can actually use for texturing. So what do you do with it then? A few things to learn here about OpenGL. Pixel Store I is a way to set up information to OpenGL about how your data is arranged.

In this case, all you want to say is, "Hey, I'm going to set up a bitmap. "It's really default arrangement." I'm going to say the length of the row of the incoming data is the pixels wide, is a bitmap pixel width. And I'm also going to say the alignment of these pixels are just simply aligned. There's no strange alignment.

There's no skipping or anything like that. So that basically says to OpenGL, it's very simple access. It's very straightforward access. I'm going to gen a texture. Remember that gen statement we showed earlier? This gives me a gen a texture, and I'm going to bind to that texture. I make it current. So it's my current texture that I'm working with. It's a state machine thing.

When we go back, all I'm going to do here is do the text to image 2D. And the text image 2D call is the thing that takes the bitmap, basically, and grabs it and uses it for OpenGL. The samples that will show how to do this, but I wanted to show you this code to say, basically, you're going to have a view or an image or whatever. You draw into a bitmap.

You basically set your striding up of what OpenGL's current striding is so it understands the way your pixels are laid out. You create a texture, and you draw into the texture, or you create the whole GL text image 2D. And then you can release a bitmap. You don't need the bitmap anymore because you've captured that data in OpenGL.

So let me jump back to my demo. I'm going to encapsulate some of the things we talked about. So this is great that we have this app here, but what I really want to do is actually I want to show you the VBO example more. In this case, we're going to keep the same code that we've worked with already. We're going to expand it a little bit.

So this may look interesting to you because this code right here is basically similar to the code we saw on the slides, which is just vertex data. So we're going to grab that. And we're going to go back to our thing. And that's just global...

[Transcript missing]

And then I'm going to jump down here to my draw rec routine.

And actually I'm going to grab all three of these routines at this point and I'll go through each of them exactly what they do and show you... is just covering what we talked about before. So I'm going to replace that simple draw rack with a little bit more complicated one. Okay, so what do we have here? So this first thing is set viewport.

And set viewport is called by the draw routine. And all it really does is get the bounds of the view we have, the NSOpenGL view bounds, and basically calls a GL set viewport. What this does is it scales your OpenGL content to the viewport as it changes. So the only reason I'm doing this is so I can drag the window bigger and smaller and you can actually see the OpenGL content correctly scaling.

You'll know if you didn't do this correctly because your OpenGL content will still be constrained to a kind of a static rectangle in your viewport even as you change sizes. So this is what that GL viewport basically makes a GL viewport respond to the entire size of the view.

So prepare OpenGL is something I've added. It's an override of a class interface prepare OpenGL. And basically it sets a clear color. So it sets a clear color to a color that we did before. It does exactly the buffer generation that we did before. It gens a color buffer. It binds to that. It then puts the data in from the color buffer with the size of the color data. I mean that's what we saw before right on the slides.

And then sets a color pointer to the beginning of it. There's three components in this. They're unsigned byte components. Remember 0 to 255. So that's what I supplied in my color data. For the vertex data buffer, I generate the buffer, bind to it, set the data, and set the vertex pointer.

and my draw rack. A little bit more complicated, but still pretty simple. We saw the beginning of it. Make current context. We saw that last time. There's my set viewport call, so that makes sure my content is scaled to the viewport. We're going to clear our buffer. Since we're double buffered, we want to be clear and have a clear draw surface every time, so we're going to clear our color buffer. We're going to enable client state for GL vertex array and color array, so we're going to do that. And then we're going to call draw arrays with triangles, and we have six points in there to draw.

And so that's the size. So remember, these are enabling the client state that we just talked about, the vertex buffer object, then we disable the client state, and we swap. So pretty straightforward code. Things we saw on the slides, and we're going to see now if this actually works and draws something that's slightly more interesting than red. So that looks good to me. So what we have here is, very simply, we just did two triangles, and let's actually prove that we did two triangles. Let me see if I can do this without breaking everything.

So if I only draw three of the points, I have a single triangle. So we specify the colors for those three triangles. We specify the vertex points for each of those triangles. The viewport ensures that our view scales well when we drag. And now you can actually write apps that do not require begin end and you can use vertex buffer objects. Hop back to the slides.

So we talked about one kind of texturing. Now I'm going to talk about a different kind of texturing. So this is texturing with Quartz and ImageIO. So we talked about the kind of pure Cocoa version of it. In this case, it's a little bit different using mostly Core Graphics calls.

We see Core Graphics image source create with URL as a call. We see the create image and index. And the key here is the CG data provider copy data. So why would I want to use this? Calls a little bit longer, maybe a little bit more complicated code, vice using the NS version of it.

The reason why I want to use this is because that CG data provider call, that data provider call says I just want kind of a raw copy of that data. You have to understand what the format is, but basically you're going to get just a raw copy of the data.

So there's no pre-multiplied alpha. So if you're using, for example, shaders, and when you actually stamp the image down in Cocoa, you're actually drawing it and you're drawing into that bitmap. So you actually have the alphas pre-multiplied through to get the values in the bitmap. This preserves the native pixels you have.

So in some cases, especially with shaders, you want to use this kind of algorithm to do it. And then you get the data by a byte pointer to the data. So you just get a basically pointer to the data. And kind of the rest is pretty much the same as we saw before.

In this case, you're just going to use the CG things to get the image width. You're going to unpack row length, the width. You're going to set the alignment the same, gen textures and text image 2D. So it's exactly the same kind of setup. The only beginning is that CG data provider call. So I'm going to go back to it.

CG data provider copy data. That is the key for this. I think we have it in our documentation. And I think there's at least one sample that uses this technique. So if you need to preserve your component data or have strange data, kind of a strange format, you want to get it directly, this is the way to do it.

So let's move on and talk about shaders a little bit. So shaders are kind of more of an advanced topic in OpenGL, but there's an interesting use for it, even if you're kind of beginning OpenGL or just getting into it. The fact is that you can do kind of direct manipulation of your drawing without writing a lot of code or without understanding the nuances of a fixed function pipeline.

So what is GLSL, OpenGL Shading Language? It's a high-level, it's a C-like language for shading. It's integrated into the OpenGL API and really simplifies the pipeline. That diagram I showed earlier had a lot of boxes on it and had some vertex data and pixel data coming in. Well, with shading, you really simplify it to you have texture data on the side that's available to your shaders, and you have those vertex attributes. Remember we talked about those.

Those are vertex position, colors, texture cords. Those kind of things come in. You go through a vertex shader. You can go through a geometry shader if you want. You can go through a fragment shader, and you go out to the screen. All pieces are optional. So for example, you can have an application that did the normal 3D transform. You drew some 3D object. You do all that in OpenGL in the fixed function, and you just put a fragment shader on the back end to do some special operation with the pixels itself. All right.

So vertex shader. So vertex shader replaces that, again, that front-end piece. So it's transformation, texture coordinate generation, and the lighting parts of the OpenGL API. So if you look at this piece of code up here, again, it looks like C. It's pretty straightforward. It has a main. And really what it's saying is it does two things. First, it defines a color. So it takes some information that was sent in and defines a color. The color is defined as a varying, which means in GLSL parlance, it means it's an output of a vertex shader.

And then the other thing is it uses a built-in function called ftransform to transform the position. So this is kind of your simplest kind of vertex shader. But what this does, it gets you, if you don't use lighting or anything like that, if you're just using, just want to transform your things, it actually kind of gets you from the basic shader usage and you can get to your fragment shader next if you want to do some things in this.

This would be fine for someone who's using, just wants that basic piece of the transform 3D to 2D part of the pipeline. The fragment shader, actually, it's... It's a very simple view in life. What it needs to do in life is actually take the inputs from the vertex shader and actually write one fragment.

So remember we talked at the very beginning, we talked about OpenGL taking a bunch of stuff and writing one fragment out. That's what the fragment shader does. You know, there's a frag color. You define frag color. A fragment shader does not define frag color or optionally depth if you have a depth buffer.

It's basically undefined. So for a fragment shader, in almost every case, you want to define frag color. Remember that little chameleon shot in the background? Yeah. Yeah. beginning, how it walks across each pixel. The fragment shader is actually executed on each one of those pixels. So if you think about it, your job in life as a fragment shader is to color that pixel a certain color. Could be based on a texture, could be based on a lot of things, but in general, it's to color that pixel. So let's go back to the demo machine, and I'll do one more demo.

In this case, I'm going to open our new shader builder. And I'll go find it. So we have Shader Builder is new for Snow Leopard. I believe it will be in a Leopard update also, but it definitely is on your seed for Snow Leopard. And the simple thing I'm going to do here is just open two shaders.

And I'll talk you through it because they're a little bit small on the side here. But basically the first one you create if you do command N is a vertex shader and the second one is a fragment shader. So if I pull off the rendering view here, what these shaders do is actually render this thing and say, well, how do I know that renders this thing? Well, let's do this.

Let's just say, this is my fragment shader. I'll say vec4. The red means it didn't compile. I'm going to say 1, 0. I'm going to say vec4 of white, basically. So as you can see, I just typed in here and as I was typing, I'm actually changing the output of the shader. One interesting thing you can see here is how you can actually affect something. Let's say this is basically what you want to do. You want to have an application that draws a texture and then color-opticates. You want to put some kind of coloring onto it.

Well, what that means is that I want to do some kind of colorization. So that means I probably want to multiply by some factor. We'll call it color here. And obviously I have to define color. We'll make it a vec4 so I can even control alpha and we'll do vec4 color. Actually, I don't want to put it there. I want to put it at the top. We'll make it a uniform qualifier.

And now I don't get anything. Oh, that's... Okay, hold on. Uniforms. Okay, uniforms. Uniforms are things that are sent in from the program. And when I added uniform to a fragment shader, it actually appeared in the shader builder in this kind of API, so you can actually change it. You can change this programmatically normally in a program, but for development's sake, I'll turn the alpha up a little bit. Turn these on. And let's animate these.

So basically what this is is kind of one line of code which now I'm controlling the actual kind of color output. What you saw is that one line wants to set a fragment color. The fragment color does a texture lookup, multiplies by GL's current color, and then I've added the fact that it multiplies by that color that I can set in a uniform.

The fact that these animations are going is really all it is is a single call in your application that says GL uniform, set it to this value. So you can imagine that if you have an application, for example, that wants to do some kind of exposure control for example on images. You could do that very simply in a fragment shader. You have the image loaded as a texture. We showed you how to do that.

You do the normal OpenGL pipeline and you create your own fragment shader that all it does is say texture and then multiplies by some kind of exposure control. You can do lots of algorithms too. There's a lot of image manipulation algorithms or kind of vertex manipulation algorithms you can do. So that's just a simple intro to what shading languages can do, direct manipulation of the OpenGL pipeline and ShaderBuilder, which is one of our tools. So what that really does is take me to, if you can go back to slides, the last section of our talk.

Let me say, for further information on shading, on the shading language, the Orange Book is available. Great book. And it really takes you from the beginning to the end of shading languages. Shows a lot of examples and also has a good reference material in it. So looking at ShaderBuilder takes me right into tools. So we have five tools for you, for developers that work with OpenGL. The first one is the OpenGL Profiler. I mentioned it.

The OpenGL Profiler we talked about in the Wednesday 5 p.m. tuning session, and we'll go into detail of using the OpenGL Profiler, and I really recommend you looking at that. It's on Leopard, it's on Snow Leopard, and it's been one of them. We built it because it's a tool that we needed to use, and I think you'll find that you can break on OpenGL commands, you can look at your buffers and see their content, you can look at textures, you can look at object IDs, all these kind of things you can do in the Profiler. You can go look at your resources, you can look at that shader. So you can break on a command in OpenGL, you can look at what your shader is, and you can change the shader on the fly.

So you can debug your application, changing the shader on the fly, without having to pull the shader out into a different environment. The Driver Monitor. Driver Monitor is more GPU-centric. It talks about the GPU, shows how much VRAM you have free, shows the number of contacts and surfaces that are going, shows how busy the GPU is. So it's a little bit more of a deep-level tool, but it's something to keep in your hip pocket just in case you need it. Shader Builder, we just saw that.

Shader Builder is a great place. We've improved it a lot to support both the early version of Fragment Programs and also the new version, kind of the shaders, and you can integrate the two together, and you have the ability to use textures, cube maps, those kind of things. It's a great place to play around with shaders and start developing shaders.

Shark. Everyone needs to learn about Shark. Shark is a tremendous profiling tool. It'll show you where your time, where your time is being spent, whether it's in OpenGL, whether it's in your app, and you'll be able to see exactly what your app is doing. It's really critical when you're debugging, profiling, and looking at the time spent in your app. You start with Shark, make a data-centric approach, really learn what your app's doing before you start making guesses.

So Shark is a great tool to do that. And finally, instruments. Many of the things, for example, that's in Driver Monitor are now in instruments. You can compare what your app's doing at certain times to what the GPU's doing. You can tie those things together. Instruments is another great app to look at how your app's behaving and understand how you can get better performance out of it.

So where do you go from here? I divide this in three categories. If you're learning OpenGL, let's start with the Redbook, start with some tutorials online. That's a great place to go. There's some examples in there. Start with the basic kind of NS Cocoa OpenGL app. If you're coming to the Mac, you know OpenGL, but you don't know Mac stuff very well, the OpenGL programming guide on developer.apple.com slash OpenGL, that is the place you want to go next.

That's that take some time this evening or on the plane back or in the car sometime, not when you're driving. Someone else is driving. And read through it. Download the PDF. Have it at your side because that really talks about kind of the texturing thing, talks about virtual screens, talks about a lot of those things that you may want to know that you didn't know and it'll give you that good background to make good decisions. And also make sure you use our tools.

Make sure you got the right tools there. If you're expanding your knowledge, so if you've been in this session and you're kind of, hey, I know most of this stuff, but I learned a nuance or two, I hope it was worth your time, but I'll point you to shading, obviously.

Let's look at the Orange Book and Shading Language. Look at the compute sessions. Look at how your app, you had a typical app that was an OpenGL app, but you're really doing numerical computing and you may want to move more to a compute aspect. And finally, look back at the OpenGL programming guide.

Look at the details. Understand the details. Understand that off-screen thing, the offline renders so you can get that full computing power out of the box and you can support someone putting additional cards in their machine. That would be a great thing to add more robustness to your app. So a lot of different directions to go for different types of people. And where you stand in your development. And I hope you have a great week.

For more information, we have a mailing list. Mac at mac-opengl at list.apple.com. We have, obviously, the documentation and sample code. And finally, for specific questions, you can send an email to Alan Schaefer, our graphics and media technology evangelist. His name is aschaefer at apple.com. And I really thank you for your time. Let me just point you to some of the sessions I mentioned.

Today and this afternoon at 5, we have the ES iPhone app development. Tomorrow, if you look at those, it's kind of like 3.30 and 5, so they're following each other in SOMA. So we have the two more advanced OpenGL sessions. And then the OpenCL sessions are Thursday morning in Russian Hill, two sessions, one following each other, 9 a.m. and 10.30 a.m. The lab for all these things is in three different times. The ES lab is Wednesday at 10.30 a.m. in the morning.

The OpenGL for the Mac lab is at 2.00. And at the same time, the OpenCL is also at 2.00 on Thursday. So we have OpenCL and OpenGL, two different labs just across the hall from each other. All the engineers will be there to answer your questions. The ES lab will be on Wednesday, the day before, in the morning, and the engineers will be there.