Войти
ПрограммированиеФорумГрафика

Проблема с усечением Frustum области другим Frustumом (2 стр)

Страницы: 1 2 3 48 Следующая »
#15
10:07, 9 дек. 2020

m210
> > Драйвер за тебя все отбракует в лучшем виде.
> Постоянно читаю подобные ошибочные представления о всемогучести видеокарт...ну
> смотрите:

Согласен. Это еще зеркал нет. С зеркалами без отсечения все видюхи сразу отмирают...


#16
10:39, 9 дек. 2020

ssa1973
Спасибо, буду разбираться :)

Если будут какие-то результаты, напишу тут...ну или о столкнувшихся проблемах))

Работы правда много, заниматься кодом не дают :P, так что не могу обещать оперативного ответа

#17
(Правка: 10:53) 10:51, 9 дек. 2020

m210

Celeron J4100
это жестоко... но там - это подобие видеокарты.

Изначально надо отбросить всё то, что не попадает на экран (в поле зрения), а после этого изголятся, если надо будет. Отбросив всё то, что не попадает на экран вообще, уже большую часть данных не надо будет обрабатывать видеокарте.

А вообще, надо вообще знать, с помощью чего выводится всё? Движок используется? Прямой вывод? (в Java нет прямого вывода вроде). Какой версии OpenGL используется?

Многие движки, при прорисовке в режиме ожидания находятся и не дают дальше ни чего делать, пока не прорисуется кадр. (sleep + windows? - не удивительно, что движок тормозит, отдавая процессорное время работе прикладных программ).

Тут можно долго гадать, но я думаю, что запустив Квейк на своём слабеньком компьютере, я даже без ограничения области вывода буду спокойно играть в неё. Так что, я думаю искать проблему надо на начальных этапах.

#18
10:54, 9 дек. 2020

ssa1973
> Алгоритм Сазерленда-Ходжмана режет порталы. Но надо учитывать, что из 4-х
> угольника, после резки, может получиться пятиугольник.
А можно пример?
Я пока расчитываю на то, что фрустумы порталов всемгда смотрят вперед, левая и правая поверхность всегда вертикальные, а нижняя и верхняя - всегда горизонтальны, т.к. порталы всегда имеют 4 вершины, а из трапеции всегда можно сделать прямоугольник.

Поэтому идея такая, чтобы отсекать левой гранью левую видимую стену, правой  - правую и т.д...т.к. наклонов нет, то и 5-угольника вроде бы не должно получиться

#19
11:00, 9 дек. 2020

Mirrel
Использую LWJGL2, движок - порт движка Build Engine, но он сейчас значения не имеет.
Начиналось все с фреймворка Libgdx, который я в итоге переписал под себя и сейчас, можно сказать, использую LWJGL.
OpenGL хочу использовать 2.0, но пока оставляю возможность использования GL1.5 (все-таки у меня не ААА проект и люди в мой проект (BuildGDX) играют на 3х пнях и на WinXP. И Celeron я взял не случайно...дома на i9 не очень то понятно, на сколько эфективен алгоритм)))

Mirrel
> ограничения области вывода буду спокойно играть в неё
У меня дома RTX2060, я тоже думаю, что кадров 50-60 она даст...но "надо делать хорошо, а плохо и само получится"

#20
(Правка: 11:07) 11:04, 9 дек. 2020

Да кстати, весь код приводить здесь как то неудобно, его достаточно много, но тело алгоритма вот:

int stat;
    portqueue[(pqtail++) & queuemask] = new WallFrustum().set(sectnum);
    WallFrustum pFrustum = portqueue[pqhead];
    gotviewport[sectnum] = pFrustum;

    while (pqhead != pqtail) {
      sectnum = pFrustum.sectnum;

      if (!pFrustum.handled) {
        pFrustum.handled = true;
        int startwall = sector[sectnum].wallptr;
        int endwall = sector[sectnum].wallnum + startwall;
        for (int z = startwall; z < endwall; z++) {
          WALL wal = wall[z];
          int nextsectnum = wal.nextsector;
          if ((stat = WallCheck(cam, wal, sectnum)) == 0)
            continue;

          // XXX Calc min and max
          int fz = sector[sectnum].floorz;
          int cz = sector[sectnum].ceilingz;

          if (sectnum == globalcursectnum || pFrustum.wallInFrustum(wal, fz, cz)) {
            if (nextsectnum != -1 && (stat == 2 || !wal.isOneWay() || wal.isTransparent())) {
              WallFrustum wallFrustum = new WallFrustum().set(wal, nextsectnum, fz, cz);
              if (!wallFrustum.fieldOfViewClipping(pFrustum)) {
                continue;
              }

              if (gotviewport[nextsectnum] == null) {
                portqueue[(pqtail++) & queuemask] = wallFrustum;
                gotviewport[nextsectnum] = wallFrustum;
              } else {
                WallFrustum nextp = gotviewport[nextsectnum];
                if ((nextp = nextp.fieldOfViewExpand(wallFrustum)) != null) {
                  if ((handled[nextsectnum >> 3] & pow2char[nextsectnum & 7]) != 0) {
                    portqueue[(pqtail++) & queuemask] = nextp;
                  }
                }
              }
            }

            gotwall[z >> 3] |= pow2char[z & 7];
          }
        }
      }

      if (pFrustum.next != null)
        pFrustum = pFrustum.next;
      else
        pFrustum = portqueue[(++pqhead) & queuemask];

      handled[sectnum >> 3] |= pow2char[sectnum & 7];
    }

Самый первой метод "WallCheck" как раз проверяет стены на первый фрустум (от камеры), а дальше уже строятся фрустумы порталом, если ои попали во фрустум камеры. Дальше по циклу происходит повторение, но для следующего портала с такой же проверкой через фрустум камеры (возможно лишнее) и через фрустум портала

Загвоздка у меня здесь:
wallFrustum.fieldOfViewClipping(pFrustum)

Вот код клиппинга для левой и правой поверхностей

public boolean fieldOfViewClipping(WallFrustum frustum) {
    if (frustum.isFullAngle)
      return true;

    final float precise = 0.00001f;
    // XXX Vertical clipping and check

//    float cx = Math.signum(globalposx - wal.x);
//    float cy = Math.signum(globalposy - wal.y);
//
//    float dotv1 = planes[3].normal.x * frustum.planes[2].normal.x - planes[3].normal.y * frustum.planes[2].normal.z
//        + planes[3].normal.z * frustum.planes[2].normal.y;
//
//    float dotv2 = planes[2].normal.x * frustum.planes[3].normal.x + planes[2].normal.y * frustum.planes[3].normal.z
//        - planes[2].normal.z * frustum.planes[3].normal.y;
//
//    float dotv3 = planes[3].normal.x * frustum.planes[3].normal.x - planes[3].normal.y * frustum.planes[3].normal.z
//        + planes[3].normal.z * frustum.planes[3].normal.y;
//
//    float dotv4 = planes[2].normal.x * frustum.planes[2].normal.x + planes[2].normal.y * frustum.planes[2].normal.z
//        - planes[2].normal.z * frustum.planes[2].normal.y;
//
//    if (frustumInFrustum(dotv1, dotv2, dotv3, dotv4, false)) {
////      if (dotv1 >= -precise && dotv2 >= -precise) {
////        System.err.println(sectnum + " is frustum in frustum");
////      } don't do something
//    } else {
//      if (dotv1 < 0 || dotv2 < 0) {
//        System.err.println(sectnum + " is not visible");
//        return false;
//      } else {
//        if (dotv4 < precise) {
//          planes[2].set(frustum.planes[2]);
//          System.err.println(sectnum + " is up clip");
//        }
//
//        if (dotv3 < precise) {
//          planes[3].set(frustum.planes[3]);
//          System.err.println(sectnum + " is down clip");
//        }
//      }
//    }

    // frustum left testPoint by plane right
    float dot1 = planes[1].normal.x * frustum.planes[0].normal.y - planes[1].normal.y * frustum.planes[0].normal.x;
    // frustum right testPoint by plane left
    float dot2 = planes[0].normal.y * frustum.planes[1].normal.x - planes[0].normal.x * frustum.planes[1].normal.y;
    // frustum left testPoint by plane left
    float dot3 = planes[0].normal.x * frustum.planes[0].normal.y - planes[0].normal.y * frustum.planes[0].normal.x;
    // frustum right testPoint by plane right
    float dot4 = planes[1].normal.y * frustum.planes[1].normal.x - planes[1].normal.x * frustum.planes[1].normal.y;

    boolean isGreater180 = this.isGreater180();
    boolean frustumIsGreater180 = frustum.isGreater180();
    if (!isGreater180) {
      if (frustumInFrustum(dot1, dot2, dot3, dot4, isGreater180)) {
        if (!frustumIsGreater180) {
//          if (sinA <= precise && cosA <= -1.0f + precise) {
          if (sinA + frustum.sinA < precise) {
            float dirx = planes[0].normal.x + planes[1].normal.x;
            float diry = planes[0].normal.y + planes[1].normal.y;
            float frdirx = frustum.planes[0].normal.x + frustum.planes[1].normal.x;
            float frdiry = frustum.planes[0].normal.y + frustum.planes[1].normal.y;

            if ((dirx * frdirx + diry * frdiry) < 0) // 180 vs 180
              return false;
          }

          if (dot1 >= -precise && dot2 >= -precise) {
            set(frustum);
            return true;
          }
        }
      }

      if (frustumInFrustum(dot2, dot1, -dot3, -dot4, frustumIsGreater180))
        return true;

      // contact check
      if (dot1 >= -precise && dot3 >= -precise) {
        planes[0].set(frustum.planes[0]);
        calcCosinA();
        return true;
      } else if (dot2 >= -precise && dot4 >= -precise) {
        planes[1].set(frustum.planes[1]);
        calcCosinA();
        return true;
      }
    } else {
      // frustum.frustumInFrustum(this)
      if (frustumInFrustum(dot2, dot1, -dot3, -dot4, frustumIsGreater180)) {
        if (dot1 >= -precise && dot2 >= -precise && dot3 <= precise && dot4 <= precise) {
          return true;
        }
      }

      // this.frustumInFrustum(frustum)
      if (frustumInFrustum(dot1, dot2, dot3, dot4, isGreater180)) {
        if ((!frustumIsGreater180 && (dot3 >= -precise || dot4 >= -precise))
            || (frustumIsGreater180 && (dot1 <= precise || dot2 <= precise))) {
          set(frustum);
          return true;
        }
      }

      // contact check
      if (dot1 <= precise && dot3 <= precise && (dot2 >= -precise || dot4 >= -precise)) {
        planes[1].set(frustum.planes[1]);
        calcCosinA();
        return true;
      } else if (dot2 <= precise && dot4 <= precise && (dot1 >= -precise || dot3 >= -precise)) {
        planes[0].set(frustum.planes[0]);
        calcCosinA();
        return true;
      }
    }

    return false;
  }

Сверху этого блока закомментированный код проверки для верхней и нижней поверхности но она не работает

#21
11:14, 9 дек. 2020

m210
> У меня дома RTX2060, я тоже думаю, что кадров 50-60 она даст...но "надо делать
> хорошо, а плохо и само получится"
Кажется меня не поняли. Я буду использовать видеокарту 128 Мб, которая ещё AGP. А так же могу ту же программу проверить на ноутбуке, где один Celeron 900, где один процессор.

Я посмотрел движок BUILD2, я так понимаю, вы его переделываете?

Я заглянул в его исходники. И возможно, вы не совсем понимаете, но тот движок вообще ни как не использует OpenGL. Точнее методы прорисовки надо в корне менять именно на то, что использует OpenGL и выкинуть из движка массу ненужных вычислений.

Я буду надеяться что я не прав...

#22
11:17, 9 дек. 2020

исходный код можете выложить архивом или ещё как?

#23
12:25, 9 дек. 2020
Я посмотрел движок BUILD2, я так понимаю, вы его переделываете?

Я заглянул в его исходники. И возможно, вы не совсем понимаете, но тот движок вообще ни как не использует OpenGL. Точнее методы прорисовки надо в корне менять именно на то, что использует OpenGL и выкинуть из движка массу ненужных вычислений.

Нет, я работаю с 1й версией этого движка, мои исходники можно посмотреть тут:
https://gitlab.com/m210/BuildGDX

А тут сайт с проектом:
https://m210.duke4.net/

Но проект с рендером у меня сейчас находится в привате, поэтому выкладываю исходники zip архивом.

src

Там много чернового кода и почти нет коментариев, так что не знаю даже, дадут ли исходники что-нибудь Вам)))

Смотреть нужно файлы FrustumCulling, OcclusionCulling3D, WallFrustum
также в файле OcclusionCulling3D две реализации определения видимости - с помощью frustumа (метод process) и метод process2 - с помощью проецирования порталов на экран, создание из проекции aabb и определение пересечения aabb в дальнейшем.

Пишу новый рендер как замену существующего рендера Polymost, ну и поэтому я не могу допустить чтобы мой рендер работал медленнее оригинала, а иначе зачем он нужен?

На данный момент мой рендер работат в 3-4 раза быстрее, поддерживает взгляд вверх/вниз и меньше проблем с z-fightingом, но вот проблема - он недоделан :) Но я думаю, что в любом случае будет быстрее оригинала, предпосылки к этому есть. Ну и да, я планирую в будущем завести все это дело на Android.

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

#24
(Правка: 13:11) 12:29, 9 дек. 2020

m210
> А можно пример?
[Пример | Проблема с усечением Frustum области другим Frustumом

Ну, камера поворачивается и перспектива делает вот так.
На картинке начальный фруструм экрана порезал портал на 6 углов.
Теоретически, каждая секущая плоскость может добавить 1 вершину.

#25
12:30, 9 дек. 2020

m210
> порт движка Build Engine
эх, где год так 97 :)

#26
13:42, 9 дек. 2020

ssa1973
Да, действительно :) Ну тогда мне не подходит такой метод отсечения, т.к. если я сейчас знаю, что у меня plane[0] - это 100% левая сторона, а plane[1] - это 100% правая сторона, то я могу на 100% утверждать, что если правая сторона одного фрустума находится внутри второго фрустума, то фрустумы можно объединить - условие dot1 >= ~0

// frustum left testPoint by plane right
    float dot1 = planes[1].normal.x * frustum.planes[0].normal.y - planes[1].normal.y * frustum.planes[0].normal.x;

А если у меня будет 6 точек, значит уже будет 6 поверхностей и тут уже накроется основная часть алгоритма.

И на самом деле мне поидее не важно куда смотрят фрустумы, я хотел сделать условие, если верхняя поверхность одного фрустума находится ниже верхней поверхности другого фрустума, то первый фрустум отсекается вторым - это значит просто у второго фрустума заменить plane[2] на plane[2] первого фрустума.

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

#27
(Правка: 14:54) 14:52, 9 дек. 2020

m210, я глянул по быстрому проект... Честно говоря, сильно не стал вникать. Но большие ощущения, что до поступления на видеокарту информации, она полностью обрабатыватся на перерасчёт данных, которые так же будут сделаны и на самой видеокарте... (а это не очень хорошо)

Могу посоветовать, для проверки взять какой-нибудь другой проект (более новый?). И сделать маленький примерчик на ней. И сравнить. Если в другом проекте всё будет достаточно быстро работать, то лучше "забить" на этот проект. Потому что тогда его полностью надо переделывать.

В той же юнити можно по быстрому накидать стенок, объектов и прочего и посмотреть как будет работать.
#28
16:26, 9 дек. 2020
Но большие ощущения, что до поступления на видеокарту информации, она полностью обрабатыватся на перерасчёт данных, которые так же будут сделаны и на самой видеокарте... (а это не очень хорошо)

Я сейчас не понял. В выше представленных примерах я показывал карты у которой 4000 стен  и 1000секторов, при этом на расчет видимости обрабатываются не все сектора, а только те, которые видят соседние порталы.

Если запихать все эти 4000 стен в GPU, тогда получаем 4000 drawcalls и 18fps...а если произвести предварительные расчеты, тогда получаем 100 drawcalls и 500 fps.
И конечно я сделал только один VBO буфер, который загоняется в видеокарту один раз при загрузке, а не в каждом кадре...а при рисовании я просто говорю видеокарте - "выведи мне вот этот кусочек своего VBO с вот этой вот текстурой"

Могу посоветовать, для проверки взять какой-нибудь другой проект (более новый?).

eDuke32 чем не другой проект? :) Более того на нем основан Ion Fury, который вышел в прошлом году, чтоли?
Работает на Polymostе и Polymere (названия рендеров) и оба пока еще уступают в производительности моим наработкам, поэтому я не собираюсь останавливаться
#29
17:21, 9 дек. 2020

m210
> Да, действительно :) Ну тогда мне не подходит такой метод отсечения, т.к. если
> я сейчас знаю, что у меня plane[0] - это 100% левая сторона, а plane[1] - это
> 100% правая сторона, то я могу на 100% утверждать, что если правая сторона
> одного фрустума находится внутри второго фрустума, то фрустумы можно объединить
> - условие dot1 >= ~0

Вольному воля. Но алгоритм С-Х плюс построение новых плоскостей отсечения не особо ресурсозатратная задача .Я вот еще и оклюдеры использую. Это фруструм наоборот. И ничего. Только выигрыш заметил. Причем иногда очень и очень существенный... так в некоторых кадрах fps  с 11 поднялся до 150)) Это к вопросу о том, что мол видюха все отрисует сама)) Как бы не так))

Страницы: 1 2 3 48 Следующая »
ПрограммированиеФорумГрафика