Проблема glTexGen в Open GL ES 2.0 - PullRequest
2 голосов
/ 18 мая 2011

У меня есть проблема, похожая на эту:проблема.

По сути, я хочу отобразить текстуру на двухмерный четырехугольник после настройки ортографической проекции.У меня проблема в том, что текстура искажена, как вы можете видеть на этом рисунке, где я использовал цветной рисунок вместо текстуры:Текстуры остаются прямыми на четырехугольнике, но, как вы можете видеть, они искажены.Я думаю, что мне нужно изменить вершинный шейдер, чтобы координаты текстуры отображали квад, но я не могу понять, как.

Большое спасибо, Джим

1 Ответ

1 голос
/ 20 января 2012

что вам нужно, это другой вид интерполяции (я полагаю, это будет квадратичная интерполяция), потому что в этом случае (длины ребер в пространстве не соответствуют длинам ребер в текстуре), линейная интерполяция не обрезает ее.

Это, к сожалению, довольно сложная задача в OpenGL (хотя и очень просто с использованием растеризации программного обеспечения). Вы пытаетесь найти преобразование произвольного четырехугольника в пространстве экрана в единичный квадрат в пространстве текстуры. Вы можете найти полное решение вашей проблемы здесь: http://alumni.media.mit.edu/~cwren/interpolator/ Это даст вам матрицу, на которую вам нужно умножить координаты пространства экрана, чтобы получить правильные координаты текстуры (в фрагментном шейдере).

Поскольку это связано с довольно неприятной математикой, я бы предложил простое решение, которое на самом деле работает для простых статических случаев (требует ручной настройки). Координата текстуры, рассчитанная в вершинном шейдере, фактически отключена только по центру, остальное правильно. Предполагая, что ваши texcoords (0, 0), (1, 0), (1, 1) и (0, 1), поправочный коэффициент:

u * v // for the first triangle
(1 - u) * (1 - v) // for the second triangle

Вам нужно оценить вектор коррекции, а затем сложить все вместе. Я протестировал с помощью простого приложения C ++ OpenGL, я нарисовал следующее:

Vector2f ta(0, 1), tb(1, 1), tc(1, 0), td(0, 0);
Vector2f a(-.1f, 1), b(1, .7f), c(1, .1f), d(0, 0);
// quad texcoords and vertices

Vector2f t_corr(-.01f, .5f);
// correction for the above quad

glBegin(GL_TRIANGLES);
glMultiTexCoord2f(GL_TEXTURE1, 1, -1); // first triangle
glTexCoord4f(ta.x, ta.y, t_corr.x, t_corr.y);
glVertex2f(a.x, a.y);
glTexCoord4f(tb.x, tb.y, t_corr.x, t_corr.y);
glVertex2f(b.x, b.y);
glTexCoord4f(tc.x, tc.y, t_corr.x, t_corr.y);
glVertex2f(c.x, c.y);

glMultiTexCoord2f(GL_TEXTURE1, 0, 1); // second triangle
glTexCoord4f(ta.x, ta.y, t_corr.x, t_corr.y);
glVertex2f(a.x, a.y);
glTexCoord4f(tc.x, tc.y, t_corr.x, t_corr.y);
glVertex2f(c.x, c.y);
glTexCoord4f(td.x, td.y, t_corr.x, t_corr.y);
glVertex2f(d.x, d.y);
glEnd();

И вершинный шейдер выглядит так:

void main()
{
    gl_Position = ftransform();
    gl_FrontColor = gl_Color;
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_TexCoord[1] = gl_MultiTexCoord1; // just copy coords, nothing else to do
}

Фрагмент шейдера:

uniform sampler2D sam;
void main()
{
    vec2 corr = vec2(gl_TexCoord[1].x + gl_TexCoord[1].y * gl_TexCoord[0].x,
                     gl_TexCoord[1].x + gl_TexCoord[1].y * gl_TexCoord[0].y);
    gl_FragColor = texture2D(sam, gl_TexCoord[0].xy + gl_TexCoord[0].zw * corr.x * corr.y);
}

Это очень просто, но, правильно настроив вектор коррекции, вы можете сделать это следующим образом: http://www.luki.webzdarma.cz/up/deskew.png

Другой вариант - сделать это с реальным квадром в 3D и вручную повернуть его в такое положение, чтобы оно выглядело как ваш 2D квад. Или разработайте текстурные координаты "глубины" для вашего квадра, вычислите 1 / глубину в вершинном шейдере, интерполируйте (u / глубину, v / глубину, 1 / глубину) и поделите на интерполированную 1 / глубину позже в фрагментном шейдере, чтобы получить хорошие значения , Хотя это может показаться простым, обратите внимание, что довольно сложно найти хорошие значения глубины.

...