Graphics and Media • 58:26
One of the most exciting developments in OpenGL is the advent of the OpenGL Shading Language (GLSL). GLSL gives you high-level C-like access to programmable GPUs. With GLSL, you have programmatic control over vertex and fragment processing, allowing you to accelerate complex renderings, create spectacular visual effects and enable new graphics capabilities. Come learn about GLSL and its incredible capabilities and how to use it in your application.
Speakers: Nick Burns, Rav Dhiraj
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Hello everybody and welcome to session 216. I'm Nick Burns as the voice of God just said. I work on GLSL and the OpenGL team at Apple. It's really fun, really exciting. I hope you guys can learn something from it today. So, before we get started, the next slide that I'm going to show you is a GLSL vertex shader. We're going to delve right into it. Now, a lot of you may not understand this at first, but I hope after this session, you will understand what's going on. So, bam! Here is a rather simple GLSL vertex shader.
For those who are not familiar with GLSL, you may not understand what the words attribute, uniform and varying mean. Well, those are just qualifiers that qualify the vertex B variable, weight, text score. I didn't name these variables. Somebody else did. Anyway. So hopefully at the end of this session, beginners will understand this a little bit more. Anyway, let's go on.
So, many of you are probably wondering what GLSL is. So, for a very simple, quick introduction, GLSL allows you to program the GPU to replace certain parts of the pipeline that I will show you later and actually put your own control in there. So you can do your own operations instead of the fixed function TCL and fixed function fragment processing, you can do pretty much whatever you want, experiment, have fun.
We'll talk about this a little bit more and show you some demos. Just to get you started, So GLSL is the path forward for OpenGL. OpenGL ES 2.0 is very shader-centric. So why don't we go on and see what it's all about. Maybe it's cool, maybe it's not.
We'll see. Hopefully, hopefully cool. So what you'll learn, what I hope you'll learn in this session, for the beginners among us, I hope you'll start to understand what GLSL is. I'll give you a quick introduction and I'll point you to some references and some examples that we have that are already on the seed and they've been out there since Xcode 2.3.
I will give you some hints for working with hardware. Hardware is fun to work with. Think of it that way. It's not hard and mean and punch you in the stomach and the back, those types of things. Anyway, I'll give you some tips and tricks to keep yourself alive when you're working with hardware. And lastly, I'll hand off to Raav from ATI, who will present the Toy Shop demo and some of the technologies behind it, such as the HLSL to GLSL conversion.
What are shaders? Shaders are made up of a few parts. They're encapsulated within objects. We have shader objects and we have program objects. And these objects take certain inputs, they produce certain outputs, and you can replace certain bits of the pipeline, which I will show you later, I promise.
The inputs to the vertex shader are vertices that aren't transformed and some uniform values such as any uniforms that you provide, generic ones, or the built-in ones that are provided by the fixed function pipeline, matrices, and other fun uniforms and such. There are also attributes for vertex data. Any data that you want to pass in with the vertices, such as weighting for vertices for vertex skinning and a whole bunch of other stuff, you can use them for generic purposes.
We'll go into that a little bit more later. Vertex Shaders produce outputs, transformed vertices. Seeing as it replaced the fixed function pipeline, you have to actually do what the fixed function pipeline did. It took vertices in, transformed them, did some lighting calculations, interpolated some values across variances for the fragment shader.
So you just have to do the work that it did, or whatever work you want to do, and then it just goes on to the fragment shader. So the fragment shader then takes these vertices that are transformed and variances that were interpolated across the face of the polygon and outputs a fragment color, a fragment depth, whatever you want to the frame buffer and any associated depth buffers, anything attached to it.
The program object is just an encapsulator for the vertex and fragment shaders. It's not very complicated. It's just a way for the programmer to access GLSL in a very easy, intuitive way. So we'll go into this a little bit more, but first let's go with a more realistic example. You've been giving me, say, all these fancy words like attribute and varying and uniform and ooh.
So here is the fixed function pipeline. I'll build it slowly. You've probably seen this from the Red Book. So let's take a look, Sean. As I said before, we have incoming vertex data and pixel data. This is then transformed and lit by the vertex processing stage. The values that are produced from the vertex processing stage are interpolated across the face of the polygon, sent to the fragment stage, which then rasterizes and produces the fragments that go to the frame buffer and other stuff happens to. But we're not concerned with that right now. You can't program that yet.
The vertex shader replaces the transform clipping and lighting stage, like I said before, and the fragment shader replaces the rasterization stage. So you can control the rasterization aspects, the transformation aspects, you can do a whole bunch of, just a world of effects and cool things like you saw in my colleague Alex Eddy's demos and whatnot.
And if any of you have tried Showpiece, it's there too, along with a bunch of cool teapots. None of those bunnies. This is a zero bunny demonstration here. No bunnies. I'm not harming any bunnies either, so... But there are giant lizards, okay? If you're gonna kill the bunnies, you have to get giant lizards instead.
So here is a nice giant gecko lizard-y thingy from Modo. They provided this nice image for us. Why don't we take a look at it? This is a more realistic example instead of attributes and vertices and blah, blah, blah. So here we have a mesh that has some texture coordinates.
Why don't we put the mesh on it? Here you can see the scope of how many vertices we have in this case. I mean, there are probably thousands of vertices for this scene. I haven't counted each one of them up, but if one of you guys want to do that and give me the number in a second, go for it. Now, why don't we zoom in a little bit? Take a look at his palette here.
You can see that you have a lot of vertices that are getting transformed here, and there are also a lot more fragments and vertices in this case. So why don't we take a little closer look here. So keep in mind that the vertex shader is going to be running once per each vertex. So whatever you write to replace the vertex shader portion of the pipeline will be run once per all these thousand vertices. Now let's get an idea of where the scope hits for fragment shaders.
Zoom in a little bit. Okay, there we go. Now, you can see a nicely pixelated version of this triangle on the palette of this giant gecko. Why don't we take a look at how many fragments potentially are in this, at least in one scan line. So here you can get, maybe you'll get an idea of how many fragments are actually being rasterized for this gecko.
As I said before, there are probably thousands of vertices in this scene. Well, there are probably millions of fragments. A thousand times the number of vertices in this scene. The fragment shader is going to be run once per each of those. The variances are going to be interpolated for each fragment.
So any of the varying output values, such as text coordinates, that's why you can see the texture varying instead of just like one solid color per triangle. It actually varies across the face of the polygon. It does that with variances and text cords. So why don't we take a look at that, shall we? Ooh, look at this snazzy blue line.
So, now you get a little introduction of what GLSL is, you probably want to know where you can actually use it. Well, it turns out it's actually been around since Tiger. So, take a look in Tiger, use it, try it out. There you have GLSL 1.10 and in Leopard, we plan on getting OpenGL 2.1 support along with GLSL 1.2. Well, GLSL 1.2 has just been recently announced, that's why it's not in the seed right now. There's a lot of work for me to do and I'll try to get it done for you people.
Now you get an idea of where it's all-- what's all going on and where it's supported. Why don't we just jump into a little, small, simple demo. This is the Hello GLSL demo. We will hopefully have it available soon for developers on a-- on the developer examples, maybe with the next release of Xcode. We'll figure that whole thing out later. So now I want to switch to that machine. There we go. No, wrong machine. Uh, this is A. There we go.
Lots of fun demos. All right, let's take a look at Hello GLSL. Right now, I am drawing a triangle, just a blue triangle. Nothing fancy, and it's blue. Nobody really likes blue, especially this shade of blue. Don't know what Kent was thinking. Anyway, so here's our blue triangle. This is going through the fixed function pipeline, just drawing a triangle, nothing fancy. Now I'm going to press space.
Boom. Now we're using a shader. Now we're not doing anything really fancy with the shader, but you can see that we're perturbing the colors of this triangle using varings. So why don't we delve into this a little bit more and switch back to the other machine. Um, switch back to the other machine. Slides, please.
All right. Now you saw that simple example. Let's go in behind the scenes a little bit and I'll show you what's actually going on here. So you've seen the triangle. You saw how it went from that blue to an awesome multicolored psychedelic triangle. How do we actually do that? Let's take a look at the steps that are required to get GLSL into your application and then go through how to actually do each of those six steps.
The first step you're going to want to do to get GLSL in, please check for extensions. You have to do this. Make sure the extension that you want is on the renderer that you have chosen. If you don't do this, you will... stuff bad will happen. Bad. Check for extensions. Then we want to make some shaders. The shaders that we used for that Hello GLSL example, I'll show you and walk you through them step by step. Next we'll show how to compile them, link them, and use them at the end.
Here is the vertex shader that was used for Hello GLSL. It's really not very complicated. It's actually simpler than the one you saw before. It has variances like we were talking about. And you'll notice that we have a varying VEC3 color. That's the output of this vertex shader to the fragment shader. So this color will be interpolated across the fragments of the polygon.
You'll see that we have a function called main. That main will be executed for each vertex. Keep that in mind if you have a really vertex-heavy or really vertex-not-heavy application. Same for the fragment shader. We'll go into that a little bit more later. Now, you can see that the color is a function of the incoming vertex value. Now, the vertices in that example went from 0 to 1 and 0 to 1. That's why we saw colors, you know, going in, in this case, red and blue.
And lastly, we transform the position, like I said we had to do before, and put that into-- we transform the incoming vertex and put that into GL position. That's the output position of this. I'll show you some more examples of this later, but-- That's that for now. Now, the Fragment Shader is even simpler.
It's just one line. It takes the incoming varying value from the Vertex Shader, interpolated it across the face of the polygon, and puts it into the Fragment Color. That might sound all fancy and crazy, but it's just setting a color. But it does it once per fragment, keep in mind.
Now we have some shaders. Two awesome shaders. Three lines total. Wow. Let's compile these shaders, shall we? Let's make some shader objects, use them, and draw that awesome little triangle that we saw. So in order to compile your shaders, all you have to really do is send the source to GL, tell it to compile your shader, That's pretty much it. Check for some errors and be a nice, good GL citizen. Next, we want to set up the program object.
First, we create a program object. Then we attach both vertex and fragment shader that we just compiled previously to this program object. This allows us to easily use this GLSL program that we made. It'll activate it when we turn it on, and it will deactivate it when we turn it off.
Next, we want to link the program. This is even easier than the other steps. Just link. Check for errors again. Make sure everything's hunky-dory. Lastly, now that we have this awesome shader, compiled, linked, we've got a program object, everything's all together, let's use it and draw a triangle.
So all you have to do is use program object, the program object you just made, draw some triangle, GLBegin, GLVertex, or use a VBO. It will be activated and replace those portions of the fixed function pipeline that I showed you earlier. Then when you're done, deactivate the shader. That's it.
I showed you in the original shader that I didn't really go over in the Hello GLSL example are the Uniform and Attribute API. So you can set the generic uniform values, basically constants in your program. To do this, you just have to make a uniform in your shader like the original one showed. So it would be like uniform float A. Now here, you would just go get uniform location of A. Then it gives you the location, which would be some number. You don't really care. Don't look at the numbers. Behind the scenes, you know, ignore the number.
And then you just set the value of that uniform. So in this case, it's setting a vec4, but you could set other values. Please look at the uniform API in the orange book. Similarly, you do the same type of thing with attributes, except attributes are per vertex data.
[Transcript missing]
www.nickbruns.com/subs.htm www.nickbruns.com/subs.htm www.nickbruns.com/subs.htm
[Transcript missing]