Кажется, вы неправильно рассчитываете вектор преломления. Hovewer, ответ на ваш вопрос уже в заголовке. Если вы смотрите на эллипсоид, лучи от вида охватывают конус, оборачивая эллипсоид. Но после преломления конус может быть намного шире, простираясь за края ваших изображений, поэтому давая координаты текстуры больше 0 - 1 и приводя к наложению текстуры. Поэтому нам нужно позаботиться и об этом.
Во-первых, координата преломления должна быть вычислена в вершинном шейдере следующим образом:
vec3 eyeDirModel = normalize(-vertex * matrix);
vec3 refractDir = refract(eyeDirModel, normal, cRIR);
RefractCoord = normalize((matrix * vec4(refractDir, 0.0)).xyz); // no dehomog!
RefractCoord теперь содержит преломленные векторы пространства глаза. Это рассчитывает на то, что «матрица» будет матрицей вида модели (это не ясно из вашего кода, но я подозреваю, что это так). Вы можете пропустить нормализацию, если хотите, чтобы шейдер работал быстрее, это не должно вызывать заметных ошибок. Теперь немного изменений в вашем фрагментном шейдере.
vec3 refractColor = texture2D(sTexture, normalize(RefractCoord).xy * .5 + .5).rgb;
Здесь использование normalize () гарантирует, что координаты текстуры не приводят к повторению текстуры.
Обратите внимание, что использование 2D-текстуры для преломлений должно быть оправдано только генерацией ее на лету (как, например, Half-Life 2), в противном случае, вероятно, следует использовать текстуру кубической карты, которая выполняет нормализацию и дает вам цвет на основе трехмерного направления - это то, что вам нужно.
Надеюсь, это поможет ... (и, о да, я написал это по памяти, в случае каких-либо ошибок, пожалуйста, комментируйте).