2017-01-20 19 views
1

Я пытаюсь реализовать вершинный шейдерный код для достижения поведения «рекламного щита» на заданной вершинной сетке. Я хочу, чтобы определить сетку в обычном режиме (например, 3D-объект), а затем всегда смотреть на камеру. Мне также нужно, чтобы он всегда имел одинаковый размер (по экрану). Эти два «эффекты» должно произойти:Как преобразовать вершины в вершинном шейдере, чтобы получить 3D-рекламный щит

Billboard in which the size is preserved despite the camera being far awayBillboard in which the rotation is fixed despite rotating the camera

Единственное различие в моем случае является то, что вместо 2-D бар а, я хочу иметь 3D-объект.

Для этого я пытаюсь следовать альтернативе 3 в this tutorial (то же самое, где сделаны снимки), но я не могу понять многие предположения, которые они сделали (возможно, из-за моего отсутствия опыт работы с графикой и OpenGL).

Мой шейдер применяет общий стек преобразования к вершинам, т.е .:

gl_Position = project * view * model * position; 

position Где является входным атрибутом с расположением вершин в мировом пространстве. Я хочу иметь возможность применять моделирование (например, перевод, масштаб и поворот), чтобы изменить ориентацию объекта относительно камеры. Я понимаю понятия, описанные в учебнике, но я не могу понять, как это применимо в моем случае.

То, что я пытался это следующее (извлеченный из этого answer, и похож на учебник):

uniform vec4 billbrd_pos; 
... 
gl_Position = project * (view * model * billbrd_pos + vec4(position.xy, 0, 0)); 

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

Is можно сделать это в вершинном шейдере?

+0

Что бы я сделал, это масштабировать модельную матрицу на '(view * center) .z', поэтому размер на экране всегда один и тот же. Для фактической матрицы ориентации она должна быть транспонирована из матрицы вида (поэтому они оба отменяются). – pleluron

ответ

2
uniform vec4 billbrd_pos; 
... 
vec4 view_pos = view * model * billbrd_pos; 
float dist = -view_pos.z; 
gl_Position = project * (view_pos + vec4(position.xy*dist,0,0)); 

Таким образом, глубины фрагмента все еще правильно (на billbrd_pos глубине), и вы не должны следить за соотношением сторон экрана (как связанный учебник делает). Однако это зависит от матрицы проекции.

+1

Спасибо, что решил проблему. Интересно, однако, какова основная математика этой операции. Почему расстояние до камеры (которое, как мне кажется, представляет переменная 'dist'), должно быть умножено на координаты ___x___ и ___y___ каждой вершины? –

+2

Перспектива делает объекты меньше на расстоянии, поэтому вам просто нужно масштабировать их относительно этого расстояния. Также это может быть 'vec4 (position.xyz * dist, 0)', как вы сказали, у вас есть 3D-объект для рендеринга. – pleluron