Ответ прост: вы меняете их между каждым вызовом розыгрыша. Установите шейдер, нарисуйте чайник, установите другой шейдер, нарисуйте другой чайник.
Для более сложных вещей, где вам нужно применить несколько шейдеров только к одному объекту, например размытие, свечение и так далее. Вы в основном все визуализируете в текстуру (ы). Затем вы визуализируете квад по всему экрану с этой текстурой, примененной во время использования другого шейдера.
Например, если вы хотите визуализировать эффект свечения, сначала вы должны визуализировать вашу обычную не светящуюся сцену, затем визуализировать только цветной силуэт материала, который вы хотите свести на текстуре, затем вы переключаетесь на затенение размытия и визуализируете Квадрат с этой текстурой, прикрепленной к вашей не светящейся сцене.
Существует еще один метод, называемый отложенным затенением, при котором вы визуализируете сцену без освещения и применяете ее позже в пространстве экрана. Основная цель состоит в том, чтобы уменьшить затраты на пиксельное освещение.
Обычно вы визуализируете цветной буфер, который помещается на экран. При использовании отложенного затенения вы визуализируете буфер цвета, а также буфер нормалей и глубины за один проход шейдера (вы можете сохранить векторы нормалей и глубину в текстуре, как при отображении нормалей и высот).
Это означает, что для каждого пикселя вы знаете положение ближайшего фрагмента непрозрачной геометрии (глубина или расстояние от глаза), цвет и нормаль. По этой причине вы можете применять освещение к каждому пикселю на экране, а не к каждому видимому пикселю каждого объекта, который вы визуализируете. Помните, что некоторый объект будет нарисован поверх других объектов, если сцена не отрисована в идеальном порядке.
Для теней вы фактически визуализируете только буфер глубины с точки зрения вашего света, а затем используете эту информацию о глубине, чтобы определить, где свет падает. Это называется отображением теней (есть также другой подход, называемый теневыми объемами, который определяет силуэт геометрии и выдавливает ее, но вы все равно будете использовать шейдеры.).
С более современным OpenGL (3.0+) вы используете объект Framebuffer с прикрепленными объектами Renderbuffers. С рендерингами буфера можно обращаться как с текстурой. Вы можете сделать что-то вроде рендеринга 1 шейдера для нескольких различных буферов рендеринга (так что вам не нужно рендерить текстуру, а не нормали, а затем компоненты свечения), но основная практика остается той же.
Также желательно максимально сократить количество шейдерных переключателей, чтобы сэкономить на накладных расходах. Поэтому некоторые движки сгруппируют все из одного и того же материала, чтобы все можно было нарисовать одновременно.