Расчет усеченного поля зрения для PerspectiveCamera

В настоящее время у меня есть экран, состоящий из двух областей:

(Значения просто предполагаются для этого конкретного примера и могут, конечно, меняться в зависимости от экрана).

В целом экран имеет разрешение 1080x1432px (WxH) и состоит из двух областей, каждая из которых обрезана с использованием glViewPort, Это потому, что я хочу, чтобы область (1) не заполняла экран при масштабировании.

  1. Игровая зона. Может быть увеличено Размер 1080x1277px (WxH) и расположен в верхней части.
  2. HUD (FYI-объекты отсюда можно перемещать в область (1). Не масштабируется. Размер 1080x154 (WxH).

У обоих есть свои камеры.

Ширина области (1) равна 15f, а высота больше 15f (не имеет значения, если она составляет не менее 15f).

Я хочу, чтобы область (2) была 7f по ширине и 1f по высоте (для удобства). Таким образом, я хочу установить камеру соответственно. Я попытался сделать это путем расчета FOV:

float size = 1f;
float halfHeight = size * 0.5f;
halfHeight *= (float) 154 / (float) 1080;
float fullHeight = 2 * halfHeight;
float halfFovRadians = MathUtils.degreesToRadians * camera.fieldOfView * 0.5f;
float distance = halfHeight / (float) Math.tan(halfFovRadians);

camera.viewportWidth = 1080;
camera.viewportHeight = 154;
camera.position.set(0f, 0, distance);
camera.lookAt(0, 0, 0);
camera.update();

И я создаю объект:

ModelBuilder builder = new ModelBuilder();
builder.begin();
builder.node();
MeshPartBuilder meshBuilder = builder.part("lattice", GL20.GL_TRIANGLES,
        VertexAttributes.Usage.Position,
        new Material(ColorAttribute.createDiffuse(Color.GRAY)));

BoxShapeBuilder.build(meshBuilder, 0f, 0f, 0f, 7f, 1f, 0f);
Model model = builder.end();
mHudModel = new ModelInstance(model);

Если я вручную попытаюсь установить расстояние до 1f, я все равно смогу увидеть окно, но если я опустюсь ниже 1,0f, окно не будет отображаться. И вычисляемое расстояние составляет примерно 0,76f.

Я пытаюсь использовать ту же концепцию, что и https://xoppa.github.io/blog/a-simple-card-game/ для расчета FOV. Это прекрасно работает для области (1).

Могу ли я не использовать камеру, как это? Я правильно рассчитываю FOV? Почему мой объект исчезает, когда я опускаюсь ниже 1f на расстоянии?

Благодарю.

1 ответ

Решение

Матрица проекции описывает отображение от трехмерных точек сцены к двухмерным точкам области просмотра. Он преобразуется из пространства глаза в пространство клипа, а координаты в пространстве клипа преобразуются в нормализованные координаты устройства (NDC) путем деления на w компонент координат клипа. НДЦ находятся в диапазоне (-1,-1,-1) - (1,1,1).
Каждая геометрия, которая находится вне НДЦ, обрезается.

Объекты между ближней и дальней плоскостями усеченной камеры отображаются в диапазон (-1, 1) НЦД.
(Смотрите далее Как линейно рендерить глубину в современном OpenGL с gl_FragCoord.z во фрагментном шейдере?)

Это означает, что если вы хотите видеть объекты, которые ближе, чем 1.0, то вам нужно установить расстояние до ближней плоскости меньше, чем 1.0.

Обратите внимание, что ближняя и дальняя плоскости должны быть как можно ближе к сцене, чтобы повысить точность вычислений и избежать z-боя, но они должны включать в себя все, что вы хотите увидеть со сцены.

Другие вопросы по тегам