Алгоритм (упрощенный):Все делается во фрагментном шейдере
1. Переходим в осесимметричное пространстве (вычитаем из точки центр)
2. Считаем, куда мы попадем, масштабируя этот вектор коэффициентом от полинома по его длине
3. Переходим обратно в нормальные координаты (прибавляем центра)
4. Сэмплим входную текстуру по этим новым координатам
Можно сделать несколько итераций [3] для большей точности. Ну и не забывайте соотношение сторон учитывать, чтоб не получить оптику странной геометрии)))
Функция для радиальной дисторсии:
static inline float2 radial_distort(float2 uv, constant Parameters& params) {
float2 scale = params.aspect;
float2 xd = (uv - params.center) * scale;
// Brown–Conrady in aspect-corrected space
float r2 = dot(xd, xd);
float r4 = r2*r2;
float r6 = r4*r2;
float radial = 1.0 + params.k1*r2 + params.k2*r4 + params.k3*r6;
float2 xu = xd / radial;
return params.center + xu / scale;
}
https://www.desmos.com/3d/i7v1yl7s5y