У меня 1005 шейдеров для рендера планет и кораблей :) Для каждого случая жизни свой отдельный шейдер:
- от 0 до 4 лайтов
- есть/нет текстура
- есть/нет карта нормалей
- есть/нет детальная текстура
- есть/нет детальная карта нормалей
- есть/нет блик
- есть/нет прозрачность
- есть/нет самосвечение
- есть/нет атмосфера
- есть/нет тени затмений
- есть/нет тени от колец
Если загружать все шейдере при старте движка, он грузится больше минуты минут пять грузятся одни только шейдеры, всё остальное - 20-30 секунд. Как бы сократить? Может ну его, сделать один убер-шейдер на все случаи жизни, где переключать эффекты if-ами и перебирать лайты в цикле? Как в играх обычно делают?
Neptune
> убер-шейдер
Да.
Шейдер со всеми возможными комбинациями дефайнов скомпилировать заранее, в оффлайне.
С собой таскать файл со скомпилированными бинарниками.
Это если D3D.
Я хз, можно ли такое сделать с OGL...
Nikopol
> Шейдер со всеми возможными комбинациями дефайнов скомпилировать заранее, в оффлайне.
Если дефайнами, то в памяти один фиг будет 1000 шейдеров, и время загрузки соответствующее.
Nikopol
> С собой таскать файл со скомпилированными бинарниками.
> Это если D3D.
> Я хз, можно ли такое сделать с OGL...
В OGL можно только с 4 версии, т.е. железо младше ~2010 выпадает.
- OpenGL можно предварительно собрать в ассемблер - он быстрее грузится
- отложенная загрузка
- фоновая компиляция (сложность - нужно шарить контекст
На мой взгляд самое разумное - кэш из ассемблерных шейдров
Neptune
> Если дефайнами, то в памяти один фиг будет 1000 шейдеров, и время загрузки соответствующее.
Погодь, в чем состоит твоя проблема?
У тебя вызовы CreateVertex(Pixel)Shader() дофига времену занимают,
или CreateVertex(Pixel)Shader() + D3DXCompileShader() в сумме?
Если второе, то я как раз и предлагаю избавиться от вызовов D3DXCompileShader в рантайме.
Neptune
> Может ну его, сделать один убер-шейдер на все случаи жизни, где переключать
> эффекты if-ами и перебирать лайты в цикле?
Через uniform bool, да - и цикл с MAX_LIGHTS делать, но с if внутри - либо с дефайнами.
На последнем железе - динамик линкадж, или бинарники.
Впрочем, если всё укладывается в sm2.0 - можно Cg в офлайне компилить в 1000 шейдеров (arbvp\fp) - очень быстро грузяться ( можно и по требованию грузить )
Еще вариант - один "толстый" шейдер на все случая жизни и shaderLOD при удалении
Еще вариант - мультипассы
Neptune
> У меня 1005 шейдеров
2^10 * 2^2 это не 1005 :)
Neptune
Если ты добавишь функцию "Сгенерировать кубемап" с текущей позиции в указанном разрешении, чтобы можно было делать себе космические скайбоксы с помощью твоего движка - это сильно прибавит ему популярности.
Как тебе идея?
RPG
> - OpenGL можно предварительно собрать в ассемблер - он быстрее грузится
про какой ассемблер идет речь? arbvp/arbfp ? если да то это врядли возможно с OpenGL 3.3 и выше. glEnable(GL_ARB_*_PROGRAM); даст GL_INVALID_OPERATION
и это уже очень устарело.
Если GL_NV_vertex_program4/GL_NV_fragment_program4 и выше то по возможностям это потянет, но опять таки не уверен насчет работоспособности, ну и это только nVidia. Компилить в asm через Cg скорей всего.
т.е. с совместимостью будут проблемы. Единственное использовать старый контекст со современными расширениями.
Mikle
> Если ты добавишь функцию "Сгенерировать кубемап" с текущей позиции в указанном
> разрешении, чтобы можно было делать себе космические скайбоксы с помощью твоего
> движка - это сильно прибавит ему популярности.
> Как тебе идея?
Можно ещё и навар с этого иметь :)
Andrey
> про какой ассемблер идет речь? arbvp/arbfp ? если да то это врядли возможно с
> OpenGL 3.3 и выше. glEnable(GL_ARB_*_PROGRAM); даст GL_INVALID_OPERATION
> и это уже очень устарело.
И сейчас выходят проекты с sm2.0 ...
Neptune
> Как в играх обычно делают?
А константы у тебя за 1 вызов передаются ? :)
RPG
> - OpenGL можно предварительно собрать в ассемблер - он быстрее грузится
Как? По-моему нельзя.
RPG
> - отложенная загрузка
Именно так пока и делаю, но достали лаги по 0.5 - 1 секунды, когда в поле зрения попадает новый объект, шейдер которого ещё не загружен.
RPG
> - фоновая компиляция (сложность - нужно шарить контекст
Не помогает, лаг всё равно остаётся (при glLinkProgram кажется) - не любит OpenGL многопоточность.
RPG
> На мой взгляд самое разумное - кэш из ассемблерных шейдров
Это решило бы проблему наполовину. Раньше так и было, когда юзал Cg - там можно было сохранить asm код, но не было совместимости с ATI, отказался. В GL 4 наконец-то добавили функцию GetProgramBinary, но у меня например всё ещё GL 3.3 видеокарта (да и у многих).
Nikopol
> Погодь, в чем состоит твоя проблема?
> У тебя вызовы CreateVertex(Pixel)Shader() дофига времену занимают,
> или CreateVertex(Pixel)Shader() + D3DXCompileShader() в сумме?
> Если второе, то я как раз и предлагаю избавиться от вызовов D3DXCompileShader в
> рантайме.
У меня GL, и всё равно раги неизбежны, если грузить asm шейдеры в рантайме.
innuendo
> На последнем железе - динамик линкадж, или бинарники.
Вот от динамик линкадж и хочу избавиться. Точнее, от лагов при этом. Если бы оно хотя бы во втором потоке не приводило к лагам основного, проблем бы не было.
innuendo
> 2^10 * 2^2 это не 1005 :)
Ну там всё несколько сложнее, одновременно блика и прозрачности не может быть, и т.п.
Mikle
> Если ты добавишь функцию "Сгенерировать кубемап" с текущей позиции в указанном
> разрешении, чтобы можно было делать себе космические скайбоксы с помощью твоего
> движка - это сильно прибавит ему популярности.
> Как тебе идея?
Так давно уже сделано: http://spaceengine.org/forum/14-168-1
innuendo
> А константы у тебя за 1 вызов передаются ? :)
Нет, за много, но вряд ли это причина тормозов при компиляции :)
В общем сделал glGetProgramBinary / glProgramBinary, оно почему-то работает в GL 3.2 контексте на GL 3.3 железе. Шейдеры грузятся раз в 50 быстрее, лаги совершенно не заметны.
Neptune
Оно и должно работать.
Dependencies
OpenGL 3.0 is required.
Written based on the wording of the OpenGL 3.2 compatibility specification.
Neptune
> > На последнем железе - динамик линкадж, или бинарники.
> Вот от динамик линкадж и хочу избавиться. Точнее, от лагов при этом.
динамик линкадж - как бы виртуальный вызов в шейдере
Тема в архиве.