1 00:00:02,310 --> 00:00:04,295 - In the final video segment of this lecture 2 00:00:04,295 --> 00:00:06,265 we'll consider shaders, 3 00:00:06,265 --> 00:00:09,186 and in particular the initialization of shaders 4 00:00:09,186 --> 00:00:12,065 need for the mytest1 program. 5 00:00:12,065 --> 00:00:16,065 Let us first look at the entire OpenGL pipeline. 6 00:00:18,975 --> 00:00:23,142 We start with the geometry specified by the user program, 7 00:00:24,058 --> 00:00:26,381 that is acted upon by a vertex shader 8 00:00:26,381 --> 00:00:28,890 which we will be considering in this course, 9 00:00:28,890 --> 00:00:31,420 and a number of other shaders that we will not be 10 00:00:31,420 --> 00:00:33,119 immediately talking about here, 11 00:00:33,119 --> 00:00:35,395 including the tessellation control shader, 12 00:00:35,395 --> 00:00:37,856 and tessellation evaluation shader, 13 00:00:37,856 --> 00:00:40,943 to tessellate primitives like spline patches, and 14 00:00:40,943 --> 00:00:45,235 a geometry shader that can generate additional geometry. 15 00:00:45,235 --> 00:00:49,648 Thereafter this comes to the rasterization part of OpenGL, 16 00:00:49,648 --> 00:00:52,787 which sets up the primitives, does some basic clipping, 17 00:00:52,787 --> 00:00:56,270 and does rasterization, which essentially takes the 18 00:00:56,270 --> 00:01:00,031 triangles and determines which pixels they should 19 00:01:00,031 --> 00:01:02,364 correspond to on the screen. 20 00:01:04,183 --> 00:01:06,881 In this course we cover programmable vertex 21 00:01:06,881 --> 00:01:08,855 and fragment shaders. 22 00:01:08,855 --> 00:01:13,009 OpenGL at this time effectively only specifies 23 00:01:13,009 --> 00:01:15,773 the rasterizer, which is non-programmable; 24 00:01:15,773 --> 00:01:19,273 everything else is determined by the user. 25 00:01:20,256 --> 00:01:24,871 Finally, that information comes to the fragment shader, 26 00:01:24,871 --> 00:01:28,522 once OpenGL decides which pixels to turn on and off; 27 00:01:28,522 --> 00:01:30,844 where a triangle goes in the 2D screen. 28 00:01:30,844 --> 00:01:34,490 Fragment shaders are called for those corresponding pixels, 29 00:01:34,490 --> 00:01:37,365 and you can also give it input information such as textures 30 00:01:37,365 --> 00:01:41,198 or image data, and you get the final color. 31 00:01:43,127 --> 00:01:46,819 As I said before, besides vertex and fragment shaders, 32 00:01:46,819 --> 00:01:50,488 modern OpenGL also involves tessellation of spline patches, 33 00:01:50,488 --> 00:01:53,693 and geometry shaders that can generate, or remove, 34 00:01:53,693 --> 00:01:55,360 geometry from the scene. 35 00:01:56,758 --> 00:01:59,493 However those are not covered in this course, 36 00:01:59,493 --> 00:02:02,493 and we consider exclusively programmable vertex 37 00:02:02,493 --> 00:02:04,243 and fragment shaders. 38 00:02:05,744 --> 00:02:07,903 To summarize the simplified pipeline, 39 00:02:07,903 --> 00:02:11,801 the user specified vertices, via vertex arrays, 40 00:02:11,801 --> 00:02:15,328 are processed in parallel by the vertex shader. 41 00:02:15,328 --> 00:02:18,604 Semantically, OpenGL is calling the vertex shader, 42 00:02:18,604 --> 00:02:21,438 the same vertex shader, separately for each of 43 00:02:21,438 --> 00:02:23,293 the different vertices. 44 00:02:23,293 --> 00:02:25,945 In fact, this high level of parallelism is one reason 45 00:02:25,945 --> 00:02:30,032 why graphics hardware is so fast and has now been adapted 46 00:02:30,032 --> 00:02:33,004 for a number of tasks that are not immediately 47 00:02:33,004 --> 00:02:35,337 relevant to graphics itself. 48 00:02:36,673 --> 00:02:39,869 The vertex shader transforms the vertex 49 00:02:39,869 --> 00:02:42,436 by applying the ModelView or the Projection matrix, 50 00:02:42,436 --> 00:02:45,431 as well as other operations. 51 00:02:45,431 --> 00:02:48,473 Thereafter, for each primitive OpenGL rasterizes, 52 00:02:48,473 --> 00:02:51,771 determines which pixels on the screen it corresponds to, 53 00:02:51,771 --> 00:02:54,511 and generates a fragment for each pixel 54 00:02:54,511 --> 00:02:57,108 that the primitive covers. 55 00:02:57,108 --> 00:03:00,594 And then, again in parallel for each of the fragments 56 00:03:00,594 --> 00:03:04,094 you apply the fragment shader in parallel. 57 00:03:05,842 --> 00:03:10,649 This will typically do shading and lighting calculations, 58 00:03:10,649 --> 00:03:14,689 and OpenGL also handles the z-buffer depth test by default, 59 00:03:14,689 --> 00:03:18,195 although it can be overwritten by the user. 60 00:03:18,195 --> 00:03:21,669 Let's now talk about the shader setup. 61 00:03:21,669 --> 00:03:24,986 Shaders must be initialized just like any program; 62 00:03:24,986 --> 00:03:27,591 effectively they are a program. 63 00:03:27,591 --> 00:03:29,519 This involves a sequence of steps. 64 00:03:29,519 --> 00:03:31,932 First you have to be able to create the shader, 65 00:03:31,932 --> 00:03:33,582 vertex and fragment. 66 00:03:33,582 --> 00:03:36,090 You have to be able to compile the shader. 67 00:03:36,090 --> 00:03:39,271 You have to be able to attach the shader to the program, 68 00:03:39,271 --> 00:03:43,104 link the program, and finally use the program. 69 00:03:45,509 --> 00:03:48,698 Note that in OpenGL, the shader source 70 00:03:48,698 --> 00:03:51,317 is just a sequence of strings. 71 00:03:51,317 --> 00:03:53,807 In fact the strings can be specified in this part 72 00:03:53,807 --> 00:03:55,640 of the OpenGL program. 73 00:03:57,402 --> 00:04:00,146 Thereafter the strings are compiled on the fly 74 00:04:00,146 --> 00:04:04,146 while the program is running, and the same steps 75 00:04:05,672 --> 00:04:09,016 that you would use to compile a normal program 76 00:04:09,016 --> 00:04:11,433 are used to compile a shader. 77 00:04:13,492 --> 00:04:16,818 Here is the shader initialization code. 78 00:04:16,818 --> 00:04:19,344 I have this command initshaders. 79 00:04:19,344 --> 00:04:21,762 Type is vertex or fragment, 80 00:04:21,762 --> 00:04:25,218 and filename is the file from which I'm reading the shader. 81 00:04:25,218 --> 00:04:28,540 But note that this is simply my convention, 82 00:04:28,540 --> 00:04:31,841 that I have the shaders in a file, I read the file 83 00:04:31,841 --> 00:04:34,720 and I specify them to the OpenGL program. 84 00:04:34,720 --> 00:04:37,576 You could as well, as far as OpenGL is concerned, 85 00:04:37,576 --> 00:04:40,613 have the shaders specified as part of the source text 86 00:04:40,613 --> 00:04:43,939 for the program. All it is doing is compiling the strings 87 00:04:43,939 --> 00:04:46,272 corresponding to the shader. 88 00:04:47,187 --> 00:04:50,202 So I create a shader of the appropriate type, 89 00:04:50,202 --> 00:04:54,456 I read the filename. This is my own text file read command, 90 00:04:54,456 --> 00:04:57,592 and I put it into a single string. 91 00:04:57,592 --> 00:05:01,509 Then I have a character pointer to that string, 92 00:05:02,441 --> 00:05:06,806 and I define the shader source for this given shader 93 00:05:06,806 --> 00:05:10,889 with one string, and with this cstr variable. 94 00:05:12,058 --> 00:05:14,681 Thereafter I compile the shader. 95 00:05:14,681 --> 00:05:18,931 OpenGL allows me to check if the compilation is correct, 96 00:05:18,931 --> 00:05:21,532 and actually give me a number of flags 97 00:05:21,532 --> 00:05:23,761 corresponding to the shader value. 98 00:05:23,761 --> 00:05:25,967 So I can check the compiled status, 99 00:05:25,967 --> 00:05:29,379 which I will put in the variable compiled. 100 00:05:29,379 --> 00:05:34,303 If compiled was fine, I actually print out a message 101 00:05:34,303 --> 00:05:36,834 saying that the compilation was fine 102 00:05:36,834 --> 00:05:38,459 and the shader can be used, 103 00:05:38,459 --> 00:05:40,572 I haven't shown the cout here 104 00:05:40,572 --> 00:05:43,029 in the interests of space. 105 00:05:43,029 --> 00:05:45,448 But if the compilation failed, 106 00:05:45,448 --> 00:05:48,351 then I will tell you what errors it encountered 107 00:05:48,351 --> 00:05:52,434 and I throw an exception, which ends the program. 108 00:05:53,366 --> 00:05:57,917 Here is the code for linking the shader program. 109 00:05:57,917 --> 00:06:00,982 So I'm given a vertex shader and a fragment shader, 110 00:06:00,982 --> 00:06:03,490 I want to link them together and use them 111 00:06:03,490 --> 00:06:05,766 in the shader program. 112 00:06:05,766 --> 00:06:08,883 First, I need to create a new program, 113 00:06:08,883 --> 00:06:12,082 then I have this variable linked. 114 00:06:12,082 --> 00:06:15,338 I attach the vertex shader to the program, 115 00:06:15,338 --> 00:06:17,331 the fragment shader to the program. 116 00:06:17,331 --> 00:06:19,587 Remember, both of these shaders are initialized 117 00:06:19,587 --> 00:06:22,763 and created by the function we saw earlier. 118 00:06:22,763 --> 00:06:24,346 I link the program, 119 00:06:25,456 --> 00:06:27,598 and just as I can get the errors 120 00:06:27,598 --> 00:06:29,549 for the compilation of the shader, 121 00:06:29,549 --> 00:06:31,569 I can get errors in linking, 122 00:06:31,569 --> 00:06:34,351 which I put in the linked variable. 123 00:06:34,351 --> 00:06:36,468 If the variable is linked, 124 00:06:36,468 --> 00:06:39,092 I use the program directly, 125 00:06:39,092 --> 00:06:42,059 otherwise I say what errors are there 126 00:06:42,059 --> 00:06:44,340 and throw an exception. 127 00:06:44,340 --> 00:06:47,266 And finally, I print out that the shader program 128 00:06:47,266 --> 00:06:49,349 is successfully attached and linked. 129 00:06:50,609 --> 00:06:53,692 Here is my basic no op vertex shader. 130 00:06:54,649 --> 00:06:57,598 This is written in GLSL, which is the high level 131 00:06:57,598 --> 00:07:00,848 shading language used to write shaders. 132 00:07:02,567 --> 00:07:05,911 The output values from the vertex shader 133 00:07:05,911 --> 00:07:09,487 will be interpolated by the rasterizer and sent 134 00:07:09,487 --> 00:07:13,040 to the fragment shader by OpenGL. 135 00:07:13,040 --> 00:07:16,873 Notice that I am doing this now in OpenGL 3.1, 136 00:07:17,916 --> 00:07:20,214 and GLSL version 330. 137 00:07:20,214 --> 00:07:24,023 So the first line I specify is the version I'm using, 138 00:07:24,023 --> 00:07:26,190 which is version 330 core. 139 00:07:27,738 --> 00:07:30,849 If you modify it to something older, it will not work, 140 00:07:30,849 --> 00:07:34,214 because the syntax is no longer relevant. 141 00:07:34,214 --> 00:07:36,585 Here are the shader inputs. 142 00:07:36,585 --> 00:07:39,441 So the layout location is 0, 143 00:07:39,441 --> 00:07:41,358 input vec3 of position. 144 00:07:42,506 --> 00:07:45,731 So remember that earlier we parsed the position and color 145 00:07:45,731 --> 00:07:50,401 to the shader. This is how it interfaces with the shader. 146 00:07:50,401 --> 00:07:52,560 That means there will be a position and a color 147 00:07:52,560 --> 00:07:55,692 associated with each vertex. 148 00:07:55,692 --> 00:07:58,110 The shader output is this Color, 149 00:07:58,110 --> 00:07:59,781 remember the case is sensitive, 150 00:07:59,781 --> 00:08:02,198 and so this is capital Color. 151 00:08:03,079 --> 00:08:06,376 The shader also has uniform variables which are the same 152 00:08:06,376 --> 00:08:07,810 for each vertex. 153 00:08:07,810 --> 00:08:10,486 Remember that these are effectively varying variableS 154 00:08:10,486 --> 00:08:13,036 that change for each vertex, 155 00:08:13,036 --> 00:08:15,823 but there are also uniform variables that can be stored 156 00:08:15,823 --> 00:08:18,279 only once for all the vertices, 157 00:08:18,279 --> 00:08:21,442 which are simply the modelview and projection matrices. 158 00:08:21,442 --> 00:08:25,599 Just like normal C code, it starts with the main routine, 159 00:08:25,599 --> 00:08:27,152 and within the main routine 160 00:08:27,152 --> 00:08:29,358 it's doing something very simple. 161 00:08:29,358 --> 00:08:33,444 The gl_Position, which is the position of the vertex, 162 00:08:33,444 --> 00:08:37,371 is just given by the position variable coming in 163 00:08:37,371 --> 00:08:39,415 for the vertex information, 164 00:08:39,415 --> 00:08:42,503 gets multiplied by the projection matrix. 165 00:08:42,503 --> 00:08:44,543 times the modelview matrix, times the position variable 166 00:08:44,543 --> 00:08:47,210 that I specified for the vertex, 167 00:08:48,999 --> 00:08:50,950 made into homogeneous coordinates; 168 00:08:50,950 --> 00:08:52,743 that's what the vec4 is doing, 169 00:08:52,743 --> 00:08:55,432 you have the x, y, z of the position and the w 170 00:08:55,432 --> 00:08:57,265 which is equal to one. 171 00:08:58,357 --> 00:09:01,540 Finally, the color is just passed through from the vertex 172 00:09:01,540 --> 00:09:03,680 to the fragment shader. 173 00:09:03,680 --> 00:09:06,629 So this is a very basic no op vertex shader. 174 00:09:06,629 --> 00:09:09,969 Note that I need to explicitly specify the multiplication 175 00:09:09,969 --> 00:09:13,839 by the projection and modelview matrices. 176 00:09:13,839 --> 00:09:17,078 Let us now look at the fragment shader. 177 00:09:17,078 --> 00:09:20,788 Again I have specified version 330 core. 178 00:09:20,788 --> 00:09:23,579 The input is just the color that came from 179 00:09:23,579 --> 00:09:25,339 the vertex shader. 180 00:09:25,339 --> 00:09:27,341 There are no uniform variables, 181 00:09:27,341 --> 00:09:30,378 and there is an output, which is the fragment color 182 00:09:30,378 --> 00:09:33,633 which will be actually displayed on the screen. 183 00:09:33,633 --> 00:09:36,234 And all that I say is that this fragment color 184 00:09:36,234 --> 00:09:37,952 is the input color, 185 00:09:37,952 --> 00:09:41,830 and I made it from RGB to RGBA simply by setting 186 00:09:41,830 --> 00:09:43,374 the alpha variable equal to one.