Вращение точечных спрайтов OpenGL во фрагментном шейдере - PullRequest
4 голосов
/ 30 января 2012

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

Попробуйте повернуть точечные спрайты на 45 градусов, изменив фрагментный шейдер.

Тамнет никаких намеков на подобные вещи ни в этой главе, ни в предыдущих.И я не нашел никакой документации о том, как это сделать.Это мои вершинные и фрагментные шейдеры:

Vertex Shader

#version 140

attribute vec2 coord2d;

varying vec4 f_color;

uniform float offset_x;
uniform float scale_x;
uniform float point_size;

void main(void) {
    gl_Position = vec4((coord2d.x + offset_x) * scale_x, coord2d.y, 0.0, 1.0);
    f_color = vec4(coord2d.xy / 2.0 + 0.5, 1.0, 1.0);
    gl_PointSize = point_size;
}

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

#version 140

varying vec4 f_color;

uniform sampler2D texture;

void main(void) {
    gl_FragColor = texture2D(texture, gl_PointCoord) * f_color;
}

Я думалнасчет использования матрицы 2х2 в ФС для поворота gl_PointCoord, но я понятия не имею, как заполнить матрицу для ее выполнения.Должен ли я передать его напрямую в ФС в форме?

Ответы [ 3 ]

8 голосов
/ 30 января 2012

Традиционный метод - передать матрицу шейдеру, будь то вершина или фрагмент. Если вы не знаете, как заполнить матрицу вращения, Google и Wikipedia могут помочь.

Главное, с чем вы столкнетесь, это простой факт, что двухмерного вращения недостаточно. gl_PointCoord идет от [0, 1]. Чистая матрица вращения вращается вокруг начала координат, которое находится слева внизу в пространстве координат точек. Таким образом, вам нужно больше, чем просто матрица вращения.

Вам нужна матрица 3х3, в которой есть поворот и перемещение детали. Эта матрица должна быть сгенерирована следующим образом (используя GLM для математических операций):

glm::mat4 currMat(1.0f);
currMat = glm::translate(currMat, glm::vec3(0.5f, 0.5f, 0.0f));
currMat = glm::rotate(currMat, angle, glm::vec3(0.0f, 0.0f, 1.0f));
currMat = glm::translate(currMat, glm::vec3(-0.5f, -0.5f, 0.0f));

Затем вы передаете currMat шейдеру в виде матрицы 4x4. Ваш шейдер делает это:

vec2 texCoord = (rotMatrix * vec4(gl_PointCoord, 0, 1)).xy
gl_FragColor = texture2D(texture, texCoord) * f_color;

Я оставлю это для вас в качестве упражнения о том, как перевести перевод из четвертого столбца в третий и как передать его в виде матрицы 3х3. Конечно, в этом случае вы сделаете vec3(gl_PointCoord, 1) для умножения матрицы.

2 голосов
/ 29 июля 2015

Я тоже застрял в той же проблеме, но нашел учебник, в котором объясняется, как выполнить двухмерное вращение текстуры в том же фрагментном шейдере только с передачей значения поворота ( vRotation ).

#version 130

uniform sampler2D tex;
varying float vRotation;
void main(void)
{

    float mid = 0.5;
    vec2 rotated = vec2(cos(vRotation) * (gl_PointCoord.x - mid) + sin(vRotation) * (gl_PointCoord.y - mid) + mid,
                        cos(vRotation) * (gl_PointCoord.y - mid) - sin(vRotation) * (gl_PointCoord.x - mid) + mid);

    vec4 rotatedTexture=texture2D(tex, rotated);
    gl_FragColor =  gl_Color * rotatedTexture;
}

Возможно, этот метод медленный, но только для того, чтобы доказать / показать, что у вас есть альтернатива для выполнения 2D-поворота текстуры внутри фрагментного шейдера вместо передачи матрицы.

Примечание: vRotation должно бытьв радианах.

ура,

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

Вы правы - матрица вращения 2x2 будет делать то, что вы хотите.

Эта страница: http://www.cg.info.hiroshima -cu.ac.jp / ~ miyazaki / Knowledge / Teche31.html показывает, как рассчитать элементы.Обратите внимание, что вы будете вращать координаты текстуры, а не позиции вершин - результат, вероятно, будет не таким, как вы ожидали - он будет вращаться вокруг координаты текстуры 0,0, например.

Вы можете такженужно умножить point_size на 2 и уменьшить gl_PointCoord на 2, чтобы убедиться, что вся текстура вписывается в точечный спрайт при вращении.Но сделайте это как второе изменение.Обратите внимание, что прямая шкала координат текстуры перемещает их к началу координат текстуры, а не к середине спрайта.

Если вы используете матрицу с более высокой размерностью (3x3), тогда вы сможете комбинировать смещение, масштаби вращение в одну операцию.

...