Подизображения OpenGL с использованием пиксельных координат

#c #opengl #glsl #shader

#c #opengl #glsl #шейдер

Вопрос:

Я проработал несколько руководств из серии breakout по learnopengl.com , так что у меня есть очень простой 2D-рендерер. Однако я хочу добавить к нему функцию субизображения, где я могу указать vec4 для своего рода «исходного прямоугольника», поэтому, если бы vec4 был (10, 10, 32, 32) , он отображал бы только прямоугольник размером 10, 10 с шириной и высотой 32, примерно так, как работает средство визуализации SDL.

Способ настройки средства визуализации заключается в том, что все спрайты используют четырехъядерный VAO, который содержит координаты текстуры. Изначально я думал, что мог бы использовать массив VAO для каждого спрайта, каждый с разными координатами текстуры, но я хотел бы иметь возможность изменять исходный прямоугольник до того, как спрайт будет нарисован, чтобы упростить такие вещи, как анимация… Моя вторая идея состояла в том, чтобы передать отдельный однородный vec4 в шейдер фрагмента для исходного прямоугольника, но как мне отобразить этот раздел только в пиксельных координатах?

Комментарии:

1. Решена ли проблема?

Ответ №1:

Используйте тип GL_TRIANGLE_STRIP примитива или GL_TRIANGLE_FAN для рендеринга квадрата. Используйте целочисленные одномерные координаты вершин вместо координат вершин с плавающей запятой. Координаты вершин являются индексами четырехугольных углов. Для a GL_TRIANGLE_FAN они:

 vertex 1: 0
vertex 2: 1
vertex 3: 2
vertex 4: 3
  

Задайте определение прямоугольника (10, 10, 32, 32) в вершинном шейдере, используя однородную переменную типа vec4 . С помощью этой информации вы можете вычислить координату вершины в вершинном шейдере:

 in int cornerIndex;
uniform vec4 rectangle;

void main()
{
    vec2 vertexArray[4] = 
        vec2[4](rectangle.xy, rectangle.zy, rectangle.zw, rectangle.xw);
    vec2 vertex = vertexArray[cornerIndex];

    // [...]
}
  

Вершинный шейдер предоставляет встроенный ввод gl_VertexID , который определяет индекс обрабатываемой в данный момент вершины. Эта переменная может использоваться вместо cornerIndex в этом случае. Обратите внимание, что для вершинного шейдера не обязательно иметь какой-либо явный ввод.

Ответ №2:

В итоге я сделал это в вершинном шейдере. Я передал в vec4 качестве формы вершинному шейдеру, а также размер изображения и использовал приведенный ниже расчет:

 // convert pixel coordinates to vertex coordinates
float widthPixel = 1.0f / u_imageSize.x;
float heightPixel = 1.0f / u_imageSize.y;

float startX = u_sourceRect.x, startY = u_sourceRect.y, width = u_sourceRect.z, height = u_sourceRect.w;
v_texCoords = vec2(widthPixel * startX   width * widthPixel * texPos.x, heightPixel * startY   height * heightPixel * texPos.y);
  

v_texCoords — это переменная, которую шейдер фрагментов использует для отображения текстуры.