Abstract shader compiler into ShaderProgram struct …
This simplifies things slightly and better encapsulates the shared logic of shaders.