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

Правильная отрисовка BSP в OpenGL 3.3+ (3 стр)

Страницы: 1 2 3 4 Следующая »
#30
16:40, 24 мая 2015

Моласар
Вот этот твой материал, если я правильно понял:

+ Показать

Некорректна тут запись в буфер глубины. Если после этого материала рисовать ещё что-то, потенциально находящееся сзади, будет фигня. Объект нарисуется за решёткой, но будет закрывать электрический разряд. Если же ничего позади этого материала ничего не рисовать, то и запись в буфер глубины не нужна.
Но всё-же, лучше пусть объект перекроет электроразряд, но не перекроет решётку, чем перекроет всё, вот эту проблему и решил Кармак, добавляя флаг depthWrite в шейдеры. Хотя опять - же, это очень редкий случай - смотреть сквозь такую решётку на динамический объект с прозрачностью.
Если хочешь парится с исправлениями таких артефактов, делай 2 прохода для таких шейдеров. Для остальных же 99% случаев одного прохода хватит.

#31
17:15, 24 мая 2015

Panzerschrek[CN]
Ты просил пример - я привёл пример. В строгом соответствии со спецификациями ку3шных шейдеров. Иными словами, я ответил за слова, а ты - нет, т.к. код GLSL-шейдера в ответ не привёл. Вместо признания неправоты ты начинаешь изобретать отмазки, да ещё и предлагаешь мне "если хочешь - париться с исправлениями". Не вижу смысла продолжать разговор с человеком, который не отвечает за базар.

#32
17:28, 24 мая 2015

Моласар
> код GLSL-шейдера в ответ не привёл
Могу привести код, дающий в Quake III ту-же самую картинку. Но содержимое буфера глубины финального кадра будет отличаться. Так что считай, что всё можно сделать за 1 проход.

#version 330
uniform Sampler2D tex[2];
in vec2 tc[2];
out vec4 color;

void main()
{
     color= vec4(texture(tex[0], tc[0]).xyz, 1.0) * texture(tex[1], tc[1]);
}
#33
18:45, 24 мая 2015

Panzerschrek[CN]
> Могу привести код, дающий в Quake III ту-же самую картинку
Мимо. В первом слое ку3-шейдера glBlendFunc( 1, 1 ), во втором glBlendFunc( 1, 0 ) + альфатест. Не вижу, чтобы твой шейдер это учитывал.

#34
9:26, 25 мая 2015

Моласар
> В общем случае это утверждение неверно. Оптимизация делается не с целью
> ускорить все функции, а с целью ускорить самые медленные. А их надо искать в
> релизе, а не дебаге.
> Приведу всего один пример: оптимизация с использованием SSE-интринсиков в
> дебаге не даёт вообще никакого прироста, а иногда может привести и к падению
> производительности. Но стоит собрать проект в релизе - картина меняется
> кардинально. И то, что раньше было критическим местом, перестаёт им быть.
>
>

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

Моласар
> glBindBuffer или glBindVertexArray? Первое быстрое, второе медленное, почему - я написал постом выше твоего.

SDL_GL_SwapBuffers()

Моласар
> Да, прекрасно. А потом кто-нибудь засунет в движок вот эту ку3-карту:
> http://www.youtube.com/watch?v=QrRwmvLNFGw#t=54
> И всё подохнет даже не на геометрии и не на конском overdraw, а на переключениях текстур, шейдеров и стейтов.

Ну вот, что-то похожее что я пытаюсь получить :) Т.е. нужен вывод карт больше, чем 1-2 комнаты.

#35
10:13, 25 мая 2015

Maris
> SDL_GL_SwapBuffers()
Ну так в это время все рисование фрейма и происходит. Ты разве не знал что видеокарта асинхронно работает?

#36
10:30, 25 мая 2015

Maris
> SSE по-мойму вообще в дебаге не работает
Ну отчего же? Работает. Ассемблерные вставки дают прирост и в дебаге. А вот с интринсиками другая ситуация.

#37
11:11, 25 мая 2015

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

Ну я его кода не видел, чтобы про шаблоны утверждать.

Не исключено, что драйвер буферизует draw calls.

конечно не исключено.

Нарисовать что-нибудь прозрачненькое, а поверх накрыть решёткой.

А ничего, что он с обоих сторон выглядит одинаково? Там же нет сортировки.

#38
13:31, 25 мая 2015

g-cont
> Ну я его кода не видел, чтобы про шаблоны утверждать.
Тогда ты в заведомо проигрышной позиции, и тебе не следовало мне возражать. :)
> А ничего, что он с обоих сторон выглядит одинаково?
По правде говоря, с другой стороны там уже другой полигон.
> Там же нет сортировки.
По расстоянию от камеры - нет, а так есть.

#39
18:24, 25 мая 2015

Тогда ты в заведомо проигрышной позиции, и тебе не следовало мне возражать. :)

Но ты его кода не видел тем более, чтобы предполагать. И про SSE тоже не знаешь есть он там или нет.

По правде говоря, с другой стороны там уже другой полигон.

Это смотря на какой карте.

#40
19:01, 25 мая 2015

g-cont
> Но ты его кода не видел тем более, чтобы предполагать
Почему же? Видел. Я, в отличие от тебя, читаю тему, прежде чем в неё отвечать. :)

#41
19:40, 25 мая 2015

Моласар
ты про STL что ли? Я думал у него свои какие-то шаблоны.

#42
10:12, 28 мая 2015

g-cont
> ты про STL что ли? Я думал у него свои какие-то шаблоны

Шаблоны есть, но довольно мало. Кстати, скомпилил в релизе, разницы по-сравнению с дебаг версией не получил... Т.е. как прыгает фпс около 500 в дебаге, столько же и в релизе..

Посмотрел исходники q3. На первый взгляд разница только:

1. В ку3 список видимых листьев не пересчитывается, если текущий кластер не меняется. Я в конечном итоге я тоже до этого дошел, и не пересчитываю его.
2. Список видымых поверхностей (индексов) пересчитывается каждый раз. За счет этого можно использовать frustrum culling. У меня же геометрия пересчитывается, только при изменении кластера. Что самое удивительное, как раз это подход ку3 работает судя по-всему шутро, а у меня нет.

В исходниках ioq3 переделали и как-то очень хитро состыковывают эти поверхности, видимо что бы избежать отрисовки некскольких треугольников за один draw call....

/*
================
R_RecursiveWorldNode
================
*/
static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits ) {

  do {
    int      newDlights[2];

    // if the node wasn't marked as potentially visible, exit
    if (node->visframe != tr.visCount) {
      return;
    }

    // if the bounding volume is outside the frustum, nothing
    // inside can be visible OPTIMIZE: don't do this all the way to leafs?

    if ( !r_nocull->integer ) {
      int    r;

      if ( planeBits & 1 ) {
        r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[0]);
        if (r == 2) {
          return;            // culled
        }
        if ( r == 1 ) {
          planeBits &= ~1;      // all descendants will also be in front
        }
      }

      if ( planeBits & 2 ) {
        r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[1]);
        if (r == 2) {
          return;            // culled
        }
        if ( r == 1 ) {
          planeBits &= ~2;      // all descendants will also be in front
        }
      }

      if ( planeBits & 4 ) {
        r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[2]);
        if (r == 2) {
          return;            // culled
        }
        if ( r == 1 ) {
          planeBits &= ~4;      // all descendants will also be in front
        }
      }

      if ( planeBits & 8 ) {
        r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[3]);
        if (r == 2) {
          return;            // culled
        }
        if ( r == 1 ) {
          planeBits &= ~8;      // all descendants will also be in front
        }
      }

    }

    if ( node->contents != -1 ) {
      break;
    }

    // node is just a decision point, so go down both sides
    // since we don't care about sort orders, just go positive to negative

    // determine which dlights are needed
    newDlights[0] = 0;
    newDlights[1] = 0;
    if ( dlightBits ) {
      int  i;

      for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
        dlight_t  *dl;
        float    dist;

        if ( dlightBits & ( 1 << i ) ) {
          dl = &tr.refdef.dlights[i];
          dist = DotProduct( dl->origin, node->plane->normal ) - node->plane->dist;
          
          if ( dist > -dl->radius ) {
            newDlights[0] |= ( 1 << i );
          }
          if ( dist < dl->radius ) {
            newDlights[1] |= ( 1 << i );
          }
        }
      }
    }

    // recurse down the children, front side first
    R_RecursiveWorldNode (node->children[0], planeBits, newDlights[0] );

    // tail recurse
    node = node->children[1];
    dlightBits = newDlights[1];
  } while ( 1 );

  {
    // leaf node, so add mark surfaces
    int      c;
    msurface_t  *surf, **mark;

    tr.pc.c_leafs++;

    // add to z buffer bounds
    if ( node->mins[0] < tr.viewParms.visBounds[0][0] ) {
      tr.viewParms.visBounds[0][0] = node->mins[0];
    }
    if ( node->mins[1] < tr.viewParms.visBounds[0][1] ) {
      tr.viewParms.visBounds[0][1] = node->mins[1];
    }
    if ( node->mins[2] < tr.viewParms.visBounds[0][2] ) {
      tr.viewParms.visBounds[0][2] = node->mins[2];
    }

    if ( node->maxs[0] > tr.viewParms.visBounds[1][0] ) {
      tr.viewParms.visBounds[1][0] = node->maxs[0];
    }
    if ( node->maxs[1] > tr.viewParms.visBounds[1][1] ) {
      tr.viewParms.visBounds[1][1] = node->maxs[1];
    }
    if ( node->maxs[2] > tr.viewParms.visBounds[1][2] ) {
      tr.viewParms.visBounds[1][2] = node->maxs[2];
    }

    // add the individual surfaces
    mark = node->firstmarksurface;
    c = node->nummarksurfaces;
    while (c--) {
      // the surface may have already been added if it
      // spans multiple leafs
      surf = *mark;
      R_AddWorldSurface( surf, dlightBits );
      mark++;
    }
  }

}
#43
10:50, 28 мая 2015

Maris
> видимо что бы избежать отрисовки некскольких треугольников за один draw call
Я думал, в этом-то и состоит главная задача - рисовать максимум треугольников за один draw call.

#44
12:13, 28 мая 2015

Моласар
> Я думал, в этом-то и состоит главная задача - рисовать максимум треугольников
> за один draw call.

Да. Я к тому, что в оригинале Кармак не парился над этим и не пытался треугольники склееть, а у него все довольно шустро работало.

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

Тема в архиве.