This is about as simple as a textured shader can be. If you're not familiar with writing fragment shaders, here's a quick rundown of the above code. In the Properties section at the top, we declare one texture property, _MainTex. This section only declares the property for the material inspector, so you can see _MainTex is declared again in the actual shader code between the CGPROGRAM and ENDCG keywords.

We've defined two functions, vert and frag. The vert function will be called once for each vertex in the mesh that we are drawing. Its purpose is to prepare the data that we'll need to draw the faces which include that vertex. The frag function is responsible for taking the interpolated data from the vert function and calculating the color for each pixel that the mesh face will occupy. We've also defined two structs. The first, appdata, contains the data that Unity's rendering engine will provide to our shader for each vertex. Since our shader is so simple, we only need the position of the vertex and its UV coordinate. The second struct, v2f, contains the data that we will calculate in our vertex function and pass to our frag function. Again, our shader is very simple, so we still only need the position and UV coordinate of the vertex. It's important to keep in mind that when rendering meshes, it is usually the case that there will be many more fragments (or pixels) than vertices, so the actual data we get in the v2f parameter in our fragment function is automatically interpolated based on the fragment’s position relative to the vertices that define the face being rendered.

With that out of the way, let's look at what our shader is doing. For each vertex, we convert the vertex position from object space to clip space, as well as transform the vertex UV position by the Tiling and Offset values input into the material inspector (which are provided to us in the _MainTex_ST vector). That data is then automatically interpolated and passed to the fragment function, which simply uses the UV coordinate to lookup the color in our texture.

Configuring our Texture, Material, and Renderer

We'll assume for now that our grid starts at the bottom-left corner of our texture and flows upwards, looping to the right until the end is reached, then loops back to the bottom left, as shown by the numbered grid below (we'll ignore A-E for now).