#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 — это переменная, которую шейдер фрагментов использует для отображения текстуры.