У меня есть следующая проблема: я рисую 2D-сцену, используя opengl, который содержит набор точек. Каждая точка указана, так как это XY-координаты. Я бы хотел использовать символ маркера - нечто вроде треугольника, креста или квадрата для визуализации точек. Проблема в том, что размер маркера должен быть постоянным на экране при масштабировании сцены - что-то вроде использования GL_POINTS
. Поэтому каждый раз, когда я меняю масштаб, мне приходится пересчитывать координаты своих маркеров, и это не удобно - я бы хотел сделать это один раз, когда получаю новую позицию точки рендеринга. Есть ли проблемы?OpenGL 2D-маркерный символ
ответ
Простейший подход, вероятно, состоит в том, что у вас есть текстуры с вашими символами, а затем рисуйте их с помощью точечных спрайтов. Если вам нужна помощь с этим подходом, мой ответ здесь объясняется, как использовать точечные спрайты:
Render large circular points in modern OpenGL
Другой подход, который приходит на ум, что вы применить масштабирование геометрии в вершинном шейдере после всех были применены другие преобразования, включая проекцию.
Самого лучшего, что приходит на ум сразу, что вы передаете два атрибута для каждой вершины в вершинном шейдере:
- центр маркеров, который имеет то же значение для всех вершин одного маркеров.
- Относительное смещение от центра маркера.
Затем в вершинном шейдере, то применяются все обычные преобразования, вплоть до и включая преобразование проекции, к центру только. Затем вы добавляете относительное смещение.
набрасывать вершинный шейдер, он может выглядеть следующим образом:
in vec3 centerPos;
in vec2 relativePos;
uniform mat4 ModelViewProj;
...
void main() {
...
vec4 projCenterPos = ModelViewProj * vec4(centerPos, 1.0);
gl_Position = vec4(
projCenterPos.xy + projCenterPos.w * relativePos,
projCenterPos.zw);
}
Поскольку относительное смещение применяется после того, как проекции, вы должны принять во внимание, что мы теперь имеем однородные координаты, где x
, y
, а z
будет разделен на w
как часть обработки фиксированной функции после вершинного шейдера. Чтобы сделать размер постоянным после этого перспективного деления, приведенный выше код умножает смещение на w
.
С relativePos
по существу применяется в НДЦ (координаты нормализованных устройств), где диапазон в х- и у-направлениях равен [-1,0, 1,0], значения должны быть довольно малы. Например, смещение 0,02 соответствует 1% от размера окна.
Если вы хотите, чтобы размер был более гибким, вы могли бы передать другой масштабный коэффициент для управления размером спрайта и умножить relativePos
на коэффициент выше. Затем вы можете сохранить относительные позиции, например. в пределах диапазона [-1,0, 1,0], а затем соответствующим образом масштабировать их:
...
uniform float spriteSize;
...
gl_Position = vec4(
projCenterPos.xy + spriteSize * projCenterPos.w * relativePos,
projCenterPos.zw);
Большое вам спасибо за ваш ответ! –