Вы можете поместить общие функции в отдельный шейдер. Затем скомпилируйте его только один раз и вставьте в несколько программ.
Это похоже на то, как вы компилируете свои cpp файлы только один раз, чтобы получить статическую или общую библиотеку. Затем вы связываете эту библиотеку с несколькими исполняемыми программами, тем самым экономя время компиляции.
Допустим, у вас есть сложная функция освещения:
vec3 ComputeLighting(vec3 position, vec3 eyeDir)
{
// ...
return vec3(...);
}
Затем для каждого шейдера, где вы хотите использовать эту функцию, сделайте следующее:
vec3 ComputeLighting(vec3 position, vec3 eyeDir);
void main()
{
vec3 light = ComputeLighting(arg1, arg2);
gl_FragColor = ...;
}
Затем вы компилируете отдельно общий шейдер и ваш основной шейдер. Но сделайте сборку обычного шейдера только один раз.