Shaders | Difference between CPU & GPU


Shader is a code that is executed by your Graphics Processing Unit, (GPU) . If you are a programmer who is planning to write his first shader, or a designer, who feels like taking some additional control over visuals, here is one way to understand the computational power you have at your disposal:

CPU Think of your processor, Central Processing Unit, as a very fast guy, who has a calculator and can do almost everything he is told to do. But he can do one single thing at a time. When you hear that a CPU has a bunch of cores it means that there are actually a bunch of guys there. But they can't really help each other, they can't do the same work.


GPU Now the GPU is a different story. We have a monitor, and that monitor has lots of pixels. Let's say 1920×1080 = 2.073.600 pixels. And your CPU can do one thing at a time, so there may be two million or more operations he'll need to do to paint stuff on your FULL-HD screen. Your monitor basically reads a picture from the memory of your computer. And CPU can fill that picture with colours, lines, letters... And that was is basically happening right now. Even though you have a GPU, it doesn't mean that your browser and all your applications are using it - some of them do, to some extent, some of them don't. CPU is good at doing one thing after another very fast, and in most scenarios, it's what we need. But when it comes to graphics, when we are painting lots of stuff to the screen, it's not really necessary to finish painting one pixel to paint the next one. Because, unless we are doing some Blur effect, we don't care what is in the pixel before this one, or the one below. So GPU is like a big factory with millions of guys, who are not as fast, and not as flexible, and not as smart. Let's say there are monkeys. A factory with millions of monkeys. It takes some time to show monkeys what to do, and they can remember only a limited number of operations. And you can't give individual assignments, there is one "Teacher" who will tell them all what to do.

*This is not an actual GPU architecture. Modern GPUs may be a bit more flexible than this description, but the analogy still holds. So a big factory of monkeys, they don't talk to each other, each of them is given a small amount of work to do, same kind of work. They are slower, but there is just so many of them that the job gets done faster. In the case of 3D rendering, it is what we need - the same simple set of operations to be done for each pixel. A texture, multiplied by the colour of light in the scene - one example of the things a shader does.

Shaders

Usually, the shader is 2 functions: one calculates stuff for every vertex of a mesh, and the second function calculates for every pixel on the screen where the mesh triangles are rendered. It's called a fragment function. If you want a shader that simulates some wind shaking, then, in the vertex function, you should change a position of a point. If you want to add fog, you will change colour based on distance from the camera in fragment (pixel) function. So again: The vertex function prepares data for the fragment function, and that data is interpolated automatically: if one vertex provides a white color and the second - black, pixels on the screen between those points will gradually go from white to grey to black. Using my Playtime Painter for some examples:

In this image, it may seem like it's going to write too fast. That is because I use Linear colour space - a correct colour space.

Our eyes are better at telling difference between darker shades and less sensitive to changes in brighter colours so computer graphics compress data to give more detail to those darker shades. And very often, in shaders, we don't bother to decompress it.

This video provides a great explanation:

Materials

In GPU you have code and data. The Data is usually Textures(pictures), and code - Shaders. A Material is usually a way you combine those two + some other parameters. Material is a way to manage Shaders and the input data they use.


Mesh

A mesh is a shape, it's a collection of triangles. Mesh is actually simpler than you may imagine. A square would be 4 dots. And triangles will be 6 indexes: 3 indexes for the first triangle and 3 for the second.

And it's as simple as it sounds:

mesh.triangles = new int[] {1,2,3,4,3,2} . A small note: some Shaders draw only triangles that are facing the camera. And to know if the triangle is facing the camera it checks if indexes are clockwise with respect to the camera, this is why the last 3 indexes are 4,3,2. Indexes 4,2,3, or 2,3,4 would have made the triangle invisible from this side: (ignore white numbers 2 and 1/2, focus on the painted ones)

Object

Different Materials can use the same Shader, only different textures. Different meshes could use the same material (for example, different walls could have a different shape, but still use the same shader and texture). Objects are usually a combination of a Material and a Mesh ... and usually all the other stuff (colliders, physics etc.).

Conclusion

CPU can do one thing after another very fast, GPU can complete the same task many times, for different segments of your screen. It's better used for smaller tasks and it is slow at changing the task itself. And CPU is used to give GPU commands on what to do. In the application for 3D development, you will usually not worry about this technical part. In Unity you place objects in the Scene, decide which mesh and Material they will use, apply shader and texture to the materials, choose where the camera is positioned, and at the end of each frame, all triangles and draw calls will be sent to the GPU. So every frame almost everything is redrawn from scratch.