1
00:00:01,002 --> 00:00:02,002
- [Instructor] Previously, we looked at

2
00:00:02,002 --> 00:00:04,002
building a particle system.

3
00:00:04,002 --> 00:00:07,003
In this video, we'll learn
about programmable pipeline

4
00:00:07,003 --> 00:00:08,006
and shaders.

5
00:00:08,006 --> 00:00:11,005
We will then code a fragment
and a vortex shader.

6
00:00:11,005 --> 00:00:14,000
We will also add shaders
in our game and load them.

7
00:00:14,000 --> 00:00:17,005
Finally, we will update and
draw a shader in each frame.

8
00:00:17,005 --> 00:00:21,009
Open Graphics Library, OpenGL,
is a programming library

9
00:00:21,009 --> 00:00:24,009
that handles 2D and 3D graphics.

10
00:00:24,009 --> 00:00:28,009
OpenGL works on all major
desktop operating systems.

11
00:00:28,009 --> 00:00:31,006
And there's also a version, OpenGL ES,

12
00:00:31,006 --> 00:00:34,002
that works on mobile devices.

13
00:00:34,002 --> 00:00:37,009
OpenGL was originally released in 1992.

14
00:00:37,009 --> 00:00:41,005
It has been refined and improved
over more than 20 years.

15
00:00:41,005 --> 00:00:44,000
Furthermore, graphics cards manufacturers

16
00:00:44,000 --> 00:00:48,002
design their hardware to make
it work well with OpenGL.

17
00:00:48,002 --> 00:00:51,001
The point of telling you this
is not for the history lesson,

18
00:00:51,001 --> 00:00:54,000
but to explain that it
would be a fools errand

19
00:00:54,000 --> 00:00:56,003
to try and improve upon OpenGL,

20
00:00:56,003 --> 00:00:59,003
and using it in 2D and
3D games on the desktop,

21
00:00:59,003 --> 00:01:00,006
especially if you want your game

22
00:01:00,006 --> 00:01:04,003
to run on more than just
windows, is the obvious choice.

23
00:01:04,003 --> 00:01:09,002
We are already using OpenGL
because SFML uses OpenGL.

24
00:01:09,002 --> 00:01:11,009
Shaders are programs that
run on the GPU itself,

25
00:01:11,009 --> 00:01:14,009
so let's find out more about them next.

26
00:01:14,009 --> 00:01:17,008
The programmable pipeline
in shaders through OpenGL

27
00:01:17,008 --> 00:01:21,006
we have access to what is
called a programmable pipeline.

28
00:01:21,006 --> 00:01:24,005
We can send our graphics
off to be drawn, each frame,

29
00:01:24,005 --> 00:01:26,008
with the RenderWindow draw function.

30
00:01:26,008 --> 00:01:29,004
We can also write code
that runs on the GPU,

31
00:01:29,004 --> 00:01:31,000
which is capable of manipulating

32
00:01:31,000 --> 00:01:35,001
each and every pixel independently,
after the call to draw.

33
00:01:35,001 --> 00:01:37,007
This is a very powerful feature.

34
00:01:37,007 --> 00:01:40,001
This extra code that runs on the GPU

35
00:01:40,001 --> 00:01:42,001
is called a shader program.

36
00:01:42,001 --> 00:01:44,006
We can write code to
manipulate the geometry

37
00:01:44,006 --> 00:01:48,004
position of our graphics in
what is called a Vertex shader.

38
00:01:48,004 --> 00:01:50,009
We can also write code that
manipulates the appearance

39
00:01:50,009 --> 00:01:53,001
of each and every pixel individually,

40
00:01:53,001 --> 00:01:55,003
in code called a Fragment shader.

41
00:01:55,003 --> 00:01:56,008
Although we will not be exploring shaders

42
00:01:56,008 --> 00:01:58,001
in any great depth,

43
00:01:58,001 --> 00:02:01,003
we will write some shader code using GLSL.

44
00:02:01,003 --> 00:02:04,002
And we'll get a glimpse of
the possibilities offered.

45
00:02:04,002 --> 00:02:08,004
In OpenGL, everything is a
point, a line, or a triangle.

46
00:02:08,004 --> 00:02:11,001
In addition, we can
attach colors and textures

47
00:02:11,001 --> 00:02:12,006
to this basic geometry.

48
00:02:12,006 --> 00:02:14,005
And we can also combine these elements

49
00:02:14,005 --> 00:02:16,008
to make the complex graphics that we see

50
00:02:16,008 --> 00:02:19,000
in today's modern games.

51
00:02:19,000 --> 00:02:21,007
These are collectively
known as primitives.

52
00:02:21,007 --> 00:02:24,002
We have access to OpenGL primitives

53
00:02:24,002 --> 00:02:27,000
through the SFML primitives
and vertex array,

54
00:02:27,000 --> 00:02:30,006
as well as the sprite and
shape classes we have seen.

55
00:02:30,006 --> 00:02:34,004
In addition to primitives,
OpenGL uses matrices.

56
00:02:34,004 --> 00:02:36,005
Matrices are a method and structure

57
00:02:36,005 --> 00:02:38,003
for performing arithmetic.

58
00:02:38,003 --> 00:02:39,006
This arithmetic can range

59
00:02:39,006 --> 00:02:42,004
from extremely simple high
school level calculations,

60
00:02:42,004 --> 00:02:46,000
to move, translate a coordinate,
or it can be quite complex,

61
00:02:46,000 --> 00:02:48,002
to perform more advanced mathematics,

62
00:02:48,002 --> 00:02:51,000
such as converting our
game world coordinates

63
00:02:51,000 --> 00:02:55,003
into OpenGL screen coordinates
that the GPU can use.

64
00:02:55,003 --> 00:02:57,001
Fortunately, it is this complexity

65
00:02:57,001 --> 00:03:00,007
that SFML handles for
us behind the scenes.

66
00:03:00,007 --> 00:03:04,007
SFML also allows us to
handle OpenGL directly.

67
00:03:04,007 --> 00:03:07,000
If you want to find out more about OpenGL,

68
00:03:07,000 --> 00:03:09,000
you can get started here,

69
00:03:09,000 --> 00:03:11,007
learnopengl.com.

70
00:03:11,007 --> 00:03:15,003
If you want to use OpenGL
directly alongside SFML,

71
00:03:15,003 --> 00:03:18,000
you can read the article at this link.

72
00:03:18,000 --> 00:03:20,005
An application can have many shaders.

73
00:03:20,005 --> 00:03:22,000
We can then attach different shaders

74
00:03:22,000 --> 00:03:25,002
to different game objects to
create the desired effects.

75
00:03:25,002 --> 00:03:26,006
We will only have one vertex

76
00:03:26,006 --> 00:03:28,009
and one framentshader in this game.

77
00:03:28,009 --> 00:03:31,005
We will apply it, each
frame, to the background.

78
00:03:31,005 --> 00:03:33,005
However, when you see
how to attach a shader

79
00:03:33,005 --> 00:03:36,004
to a draw call, it will be
plain that it is trivial

80
00:03:36,004 --> 00:03:38,008
to add more shaders.

81
00:03:38,008 --> 00:03:40,007
We will follow these steps.

82
00:03:40,007 --> 00:03:42,008
First of all, we need
the code for the shader

83
00:03:42,008 --> 00:03:45,000
that will be executed on the GPU.

84
00:03:45,000 --> 00:03:47,005
Then we need to compile that code.

85
00:03:47,005 --> 00:03:49,003
Finally, we need to attach the shader

86
00:03:49,003 --> 00:03:51,001
to the appropriate draw call

87
00:03:51,001 --> 00:03:53,007
in the draw function of our game engine.

88
00:03:53,007 --> 00:03:56,005
GLSL is a language in its own right.

89
00:03:56,005 --> 00:03:58,000
And it also has its own types,

90
00:03:58,000 --> 00:04:01,008
and variables of those types
can be declared and utilized.

91
00:04:01,008 --> 00:04:03,001
Furthermore, we can interact

92
00:04:03,001 --> 00:04:07,003
with the shader programs
variables from our C++ code.

93
00:04:07,003 --> 00:04:13,002
As we will see, GLSL has some
syntax similarities to C++.

94
00:04:13,002 --> 00:04:15,002
Coding a fragment shader.

95
00:04:15,002 --> 00:04:18,002
Here is the code from the
rippleShader.frag file

96
00:04:18,002 --> 00:04:19,007
in the shaders folder.

97
00:04:19,007 --> 00:04:20,008
You don't need to code this,

98
00:04:20,008 --> 00:04:23,004
as it is available in
the assets we added back

99
00:04:23,004 --> 00:04:26,001
while learning abstraction
and code management.

100
00:04:26,001 --> 00:04:28,004
The first four lines, excluding comments,

101
00:04:28,004 --> 00:04:31,003
are the variables that the
fragment shader will use.

102
00:04:31,003 --> 00:04:34,000
However, they are not ordinary variables.

103
00:04:34,000 --> 00:04:36,000
The first type we see varying.

104
00:04:36,000 --> 00:04:39,005
These are variables which are
in scope between both shaders.

105
00:04:39,005 --> 00:04:42,000
Next, we have the uniform variables.

106
00:04:42,000 --> 00:04:43,005
These variables can be manipulated

107
00:04:43,005 --> 00:04:46,002
directly from our C++ code.

108
00:04:46,002 --> 00:04:48,001
We will see how we do this soon.

109
00:04:48,001 --> 00:04:50,008
In addition to the
varying and uniform types,

110
00:04:50,008 --> 00:04:53,007
each of the variables also
has a more conventional type,

111
00:04:53,007 --> 00:04:55,007
which defines the actual data.

112
00:04:55,007 --> 00:04:58,006
Vec4 is a vector with four values.

113
00:04:58,006 --> 00:05:00,008
Vec2 is a vector with two values.

114
00:05:00,008 --> 00:05:03,002
Sampler2D will hold a texture float

115
00:05:03,002 --> 00:05:06,002
is just like a float in C++.

116
00:05:06,002 --> 00:05:08,000
The code inside the main function

117
00:05:08,000 --> 00:05:10,000
is what is actually executed.

118
00:05:10,000 --> 00:05:12,001
If you look closely at the code in main,

119
00:05:12,001 --> 00:05:14,007
you will see each of the variables in use.

120
00:05:14,007 --> 00:05:16,004
Exactly what this code does

121
00:05:16,004 --> 00:05:18,005
is beyond the scope of this course.

122
00:05:18,005 --> 00:05:22,004
In summary, however, the
texture coordinates, vTexCoord,

123
00:05:22,004 --> 00:05:25,009
and the color of the pixels,
fragments gl_FragColor,

124
00:05:25,009 --> 00:05:27,003
are manipulated by a number

125
00:05:27,003 --> 00:05:30,000
of mathematical functions and operations.

126
00:05:30,000 --> 00:05:33,001
Remember that this executes
for each and every pixel

127
00:05:33,001 --> 00:05:34,005
involved in the draw call

128
00:05:34,005 --> 00:05:37,001
on each and every frame of our game.

129
00:05:37,001 --> 00:05:39,004
Furthermore, be aware that uTime

130
00:05:39,004 --> 00:05:42,007
is passed in as a different
value each and every frame.

131
00:05:42,007 --> 00:05:46,006
The result, as we will soon
see, will be a rippling effect.

132
00:05:46,006 --> 00:05:49,005
Now let's code for a vertical shader.

133
00:05:49,005 --> 00:05:52,009
Here is the code from
the vertShader.vert file.

134
00:05:52,009 --> 00:05:54,003
You don't need to code this,

135
00:05:54,003 --> 00:05:55,009
as it was in the assets we added

136
00:05:55,009 --> 00:05:59,000
back in abstraction and
code management section.

137
00:05:59,000 --> 00:06:02,003
First of all, notice the
two varying variables.

138
00:06:02,003 --> 00:06:03,008
These are the very same variables

139
00:06:03,008 --> 00:06:06,005
that we manipulated back
in the fragment shader.

140
00:06:06,005 --> 00:06:07,006
In the main function,

141
00:06:07,006 --> 00:06:11,000
the code manipulates the position
of each and every vertex.

142
00:06:11,000 --> 00:06:13,009
How the code works is beyond
the scope of this book.

143
00:06:13,009 --> 00:06:16,002
But there is some quite in depth math

144
00:06:16,002 --> 00:06:18,008
going on behind the scenes,
and if it interests you,

145
00:06:18,008 --> 00:06:21,008
then exploring GLSL will be fascinating.

146
00:06:21,008 --> 00:06:25,002
Now we have two shaders,
one fragment and one vertex.

147
00:06:25,002 --> 00:06:27,002
We can use them in our game.

148
00:06:27,002 --> 00:06:29,005
Adding shaders to the engine class.

149
00:06:29,005 --> 00:06:35,002
First you have to open the Engine.h file.

150
00:06:35,002 --> 00:06:37,009
Add this code, which adds
an SFML shader instance

151
00:06:37,009 --> 00:06:42,000
called m_RippleShader to the engine class.

152
00:06:42,000 --> 00:06:45,001
We will add this instance
after texture here.

153
00:06:45,001 --> 00:06:47,002
The engine object and all its functions

154
00:06:47,002 --> 00:06:50,005
now have access to m_RippleShader.

155
00:06:50,005 --> 00:06:52,008
Note that an SFML shader object

156
00:06:52,008 --> 00:06:55,009
will be comprised of
both shader code files.

157
00:06:55,009 --> 00:06:58,000
Open the Engine.cpp file

158
00:06:58,000 --> 00:07:00,001
and add this code to the constructor.

159
00:07:00,001 --> 00:07:01,008
Loading the shaders.

160
00:07:01,008 --> 00:07:03,002
Add some code which checks

161
00:07:03,002 --> 00:07:05,007
whether the players
GPU can handle shaders.

162
00:07:05,007 --> 00:07:07,008
The game will quit if it can't.

163
00:07:07,008 --> 00:07:09,008
Next we will add an else clause

164
00:07:09,008 --> 00:07:11,001
that actually loads the shaders,

165
00:07:11,001 --> 00:07:13,000
if the system can handle them.

166
00:07:13,000 --> 00:07:16,006
Now we are nearly ready to see
our ripple effect in action.

167
00:07:16,006 --> 00:07:19,001
Updating and drawing the
shader in each frame.

168
00:07:19,001 --> 00:07:21,005
Open the Draw.cpp file.

169
00:07:21,005 --> 00:07:24,000
As we discussed when we coded the shaders,

170
00:07:24,000 --> 00:07:25,006
we will update the uTime variable,

171
00:07:25,006 --> 00:07:28,008
directly from our C++ code, each frame.

172
00:07:28,008 --> 00:07:36,002
We do so with the uniform function.

173
00:07:36,002 --> 00:07:37,003
Add the highlighted code

174
00:07:37,003 --> 00:07:46,005
to update the shaders uTime variable.

175
00:07:46,005 --> 00:07:50,000
And change the call draw
for m_BackgroundSprite

176
00:07:50,000 --> 00:07:54,004
in each of the possible drawing scenarios.

177
00:07:54,004 --> 00:07:56,007
We have to also change the call here.

178
00:07:56,007 --> 00:08:19,004
Include the lines of
code being written here.

179
00:08:19,004 --> 00:08:21,008
It would be best to actually
delete the lines of code

180
00:08:21,008 --> 00:08:23,006
that I have shown commented out.

181
00:08:23,006 --> 00:08:25,009
I just did it this way to make it clear

182
00:08:25,009 --> 00:08:28,007
which lines of code are being replaced.

183
00:08:28,007 --> 00:08:29,007
Run the game

184
00:08:29,007 --> 00:08:33,001
and you get an eerie kind
of molten rock effect.

185
00:08:33,001 --> 00:08:35,002
Experience with changing
the background image

186
00:08:35,002 --> 00:08:37,002
if you want to have some fun.

187
00:08:37,002 --> 00:08:38,002
That's it.

188
00:08:38,002 --> 00:08:41,002
Our third and final game is done.

189
00:08:41,002 --> 00:08:44,004
In this video, we have
learned about OpenGL,

190
00:08:44,004 --> 00:08:46,006
shaders, and GLSL.

191
00:08:46,006 --> 00:08:49,003
In the grand finale, we
explored the concepts

192
00:08:49,003 --> 00:08:51,005
of particle systems in shaders.

193
00:08:51,005 --> 00:08:52,007
Although we looked at probably

194
00:08:52,007 --> 00:08:55,003
the simplest possible case for each,

195
00:08:55,003 --> 00:08:57,009
we still managed to
create a simple explosion

196
00:08:57,009 --> 00:09:01,000
and an eerie molten rock effect.

197
00:09:01,000 --> 00:09:03,002
This was really a big journey.

198
00:09:03,002 --> 00:09:05,000
And, hopefully, you have a good insight

199
00:09:05,000 --> 00:09:07,009
in how to build games in C++.

200
00:09:07,009 --> 00:09:16,009
I wish you all the best, keep gaming.

201
00:09:16,009 --> 00:09:19,000
(typing)

