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

Сортировка по материалам и эффективное переключение стейтов.

Advanced: Тема повышенной сложности или важная.

Страницы: 1 2 Следующая »
#0
13:04, 16 апр. 2015

Доброго времени!

Учитывая что материал может быть абсолютно разным и содержать разное кол-во параметров, разные типы параметров и кол-во текстур. Вопрос сортировки таких материалов существенно усложняется.
Но если отсортировать ещё более-менее реально, то генерация необходимых стейтов, точнее очереди из них совсем тяжко мне даётся. Точнее даже не знаю с чего начать.

Существует ли статьи, книги, рекомендаций Как правильно организовать всё это используя ООП?

ЗЫ: Сейчас у меня отрисовка каждого объекта влечёт установку всех(!) юниформов шейдера независимо от уже установленных и в большинстве случаев точно таких же в предыдущих объектах.
ЗЗЫ: Отметил Тема повышенной сложности хотя для вас возможно это и не так ;)


#1
13:16, 16 апр. 2015

ЗЫ
Какой хоть графический АЙПИ ?

ЗЫ :)
ЗЗЫ :)

#2
14:14, 16 апр. 2015

> Какой хоть графический АЙПИ ?
Ой. Забыл сказать. OpenGL 3.3 core

#3
15:12, 16 апр. 2015

snake32
Ой. Забыл сказать. Я же не знаю OpenGL 3.3 core :)

+ Показать
#4
15:14, 16 апр. 2015

ronniko
так распиши для мантла, яка разница =)

#5
15:29, 16 апр. 2015

snake32
А зачем сортировать то?

Я избавлялся от лишних биндов так:
1. Где-то прячем список (1) _всех_ материалов на сцене. Добавление/удаление из списка производится автоматически при присвоении материала объекту(чтобы неиспользуемые материалы в списке не были).
2. Каждый элемент списка (1) указывает на материал и список моделей в видеопамяти (2), использующих этот материал
3. Каждые элемент списка (2) указывает на модель в видеопамяти(VBO) и список объектов (3), которые используют модель.
При рендере:
1. Идешь по списку (1), биндишь материал
2. Открываешь список (2), для текущего материала, биндишь модель(VBO)
3. Открываешь список (3), передаешь в шейдер актуальные только для конкретного объекта данные
4. Рисуешь
5. ???
6. Профит

В пункте 3. можно использовать инстансинг, а если совсем уж часто данные повторяются, то можно проверять различаются ли новые данные от данных с предыдущего прохода.

#6
15:31, 16 апр. 2015

Да, кстати, тип GAPI для меня сейчас не особо важен. Подойдёт любой, где есть шейдеры и юниформы(dx9,dx10,dx11). Хотел понять общий принцип алгоритма выуживания изменений, дабы лишний раз их не устанавливать и разгрузить CPU.

#7
16:17, 16 апр. 2015

The Player
>А зачем сортировать то?
Может я не правильно понимаю абстракцию Материал?
В моём понимании Материал это - один слинкованный шейдер с конкретными значениями его юниформов. Изменился шейдер или хотябы одно значение его юниформа, то это уже другой материал.
Таким образом, отсортированный по материалам массив объектов при последовательном просмотре гарантирует что изменений будет минимум(как по шейдерам так и по юнифрмам).

Следующий шаг - извлечение разницы материалов и формировании из них нового массива для последующего многократного "рендера" этого массива.
Вот здесь у меня проблемы. По мимо "разниц материалов" в этот же массив необходимо вставлять "геометрические данные"(набор VBO(VAO) и glDrawElements ) каждого объекта. Очевидно, класс "разница материалов" и "геометрические данные" объекта должны иметь общего предка, иначе полиморфизм не возможен. В итоге стремлюсь к такому результату:
[pas]for obj in DiffMaterialAndGeometryData_List do
  obj.Apply;[/pas]

#8
17:08, 16 апр. 2015

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

#9
17:23, 16 апр. 2015

kipar
>Тем более если ты буферы юниформ используешь, то вообще нет смысла ловить "разницу материалов" - изменился и изменился, ставим другой буфер.
нет. UBO я ещё не использовал. У меня пока тупо идёт цикл по всем активным юниформам шейдера для каждого объекта.

procedure TGLProgramObject.SetUniforms( const Uniforms:TUniforms );
  var i:integer;
begin
  for i:=0 to Length( FActiveUniforms )-1 do
    Uniforms[ FActiveUniforms[i].enum ].Apply( FActiveUniforms[i].location );
end;

Где Uniforms - глобальный массив всех uniform'ов используемых во всех шейдерах

  
  TUniformEnum = (
    uProjection, uView, uModel, uModelView, uModelViewProjection, uDeltaTime,
    uSampler0, uSampler1, uOffsetX, uColor, uRange, uSelect, uViewport, uBillboard
  );
  TUniformParam = class
  public
    procedure Apply( const location:GLint ); virtual; abstract;
  end;

  TUniforms = array[TUniformEnum] of TUniformParam;

  TUniformType<T:record> = class( TUniformParam )
  public
    Data:T;
  end;

  TUniformMat4 = class( TUniformType<TMat4> )
    procedure Apply( const location:GLint ); override;
  end;

  TUniformVec4 = class( TUniformType<TVec4> )
    procedure Apply( const location:GLint ); override;
  end;
#10
17:39, 16 апр. 2015

snake32
ну, можно закешировать последнее значение, в Apply что-то типа (if lastValue <> Value then begin glUniform...(Value); LastValue := Value end;).
Хотя в драйвере оно, возможно, и так кешируется, но так будет меньше вызовов API. Ну и при смене шейдера все равно все юниформы надо перезагружать.

Суть материалов в том чтобы одним drawcallом рисовать все объекты с одним материалом, а экономия на установке юниформ (все или только половину выставлять) между материалами по сравнению с этим - мизер.

#11
18:03, 16 апр. 2015

kipar
>if lastValue <> Value then begin glUniform...(Value); LastValue := Value end;
У меня сейчас стейты так тестятся

procedure TPassMain.Draw( state:TGLState );
begin
  if state.BindFrameBuffer <> 0 then
  begin
    glBindFrameBuffer( GL_FRAMEBUFFER, 0 );
    state.BindFrameBuffer := 0;
  end;
  if state.ViewPort <> ViewPort then
  begin
    glViewport( ViewPort.x, ViewPort.y, ViewPort.z, ViewPort.w );
    state.ViewPort := ViewPort;
  end;
  if state.ClearColor <> FClearColor then
  begin
    glClearColor( FClearColor.x, FClearColor.y, FClearColor.z, FClearColor.w );
    state.ClearColor := FClearColor;
  end;
  if state.EnableBlend <> true then
  begin
    glEnable( GL_BLEND );
    state.EnableBlend := true;
  end;
  if( state.BlendFuncFactorS <> GL_SRC_ALPHA )or( state.BlendFuncFactorD <> GL_ONE_MINUS_SRC_ALPHA )then
  begin
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    state.BlendFuncFactorS := GL_SRC_ALPHA;
    state.BlendFuncFactorD := GL_ONE_MINUS_SRC_ALPHA;
  end;

  glClear( GL_COLOR_BUFFER_BIT );
  state.Uniforms[uProjection] := proj;
  state.Uniforms[uView] := view;
  state.Uniforms[uViewport] := vp;
  inherited;
end;

>Суть материалов в том чтобы одним drawcallом рисовать все объекты с одним материалом
Дык у всех одинаковоматериальных объектов могут быть разные юниформы и почти всегда разные VBO. Как это можно отрендерить одним drawcallом?

#12
18:07, 16 апр. 2015

snake32
Вот этот подход работает шикарно - http://realtimecollisiondetection.net/blog/?p=86

#13
22:56, 16 апр. 2015

snake32
Ну сортировать по материалам, расстоянию до камеры(для близких к камере объектов) и прозрачности.
Причем если есть прозрачные объекты то от ближним к дальним. с дальнего расстояния лучше сортировать по материалам, так-же с учетом прозрачности. Ведь в далеке затраты на Owerdaw будут минимально, ибо объекты буду иметь размеры в несколько пикселей, и для них переключение материалов будет намного тяжелее.
Cортировка по расстоянию имеет нюансы на некоторых платформах. К примеру на IOS Apple это не рекомендует делать, там используется Tile Based Rendering (TBR).
И наконец для облегчения реализации сортировки по этим условиям все это, пакуется в ключ, как описано в ссылке приведенной StiX

#14
15:31, 20 апр. 2015

Пока не было шейдеров самым дорогим было переключение текстур и как следствие - завязанных на них стейтов. Теперь, соответственно, шейдеры самое дорогое переключение. Но там замкнутый круг - сделаешь один универсальный шейдер с условиями - будет тормозить обработка этих условий. Сделаешь убер-шейдер и рантайм-компиляцию - надо будет сортировать их, чтобы избежать слишком частых переключений. А сортировка тоже небесплатная, особенно когда много полигонов в кадре. У меня были случаи когда на сортировку уходило столько же времени, сколько на переключение шейдеров. Их немного таких случаев, процентов 5 от общего кол-ва, но всё-таки были.

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

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