Джек Аллигатор
В теории это могло пригодиться для рисования сразу в несколько каскадов Shadow Map, но на практике в здравом уме это нигде не применяется.
prowkan
innuendo
Понятно. Спасибо.
prowkan
> В теории это могло пригодиться для рисования сразу в несколько каскадов Shadow
> Map,
тени в кубе в UE/CE
prowkan
> Зачем там несколько вьюпортов?
подловил :) с rt перепутал в конце рабочего дня
можно делать несколько видов сразу - типа как в CAD/Editor
кстати, вот про использование gs http://twvideo01.ubm-us.net/o1/vault/gdc09/slides/100_Handout%203.pdf
prowkan
> смотрел разные игры через RenderDoc и Intel GPA
если шейдера открыты можно и без отладчиков
> кстати, у вас тоже https://www.khronos.org/opengl/wiki долго открывается?
Разобрался с этим, если у кого тоже тормозит, добавьте в свой hosts файл строку
127.0.1.1 beta.opengl.org
Джек Аллигатор
Тут наткнулся на glium, пример из которого ты приводил по текстурам. Так вот автор разочаровался в OpenGL враппере и забил на его разработку - https://users.rust-lang.org/t/glium-post-mortem/7063 - тут довольно подробно разжеваны причины. Для тех кто не умеет в английский вкратце:
1) Реализации OpenGL багнутые, разработчики читают спецификации жопой.
2) Слишком много всего нужно реализовывать
3) Пользователи враппера достали с вопросами.
В общем писать враппер над высокоуровневым GAPI (OpenGL, DX < 12) довольно бессмысленная затея.
mr.DIMAS
> автор разочаровался в OpenGL враппере и забил на его разработку
Это его проблемы.
> 1) Реализации OpenGL багнутые, разработчики читают спецификации жопой.
Это проблема выбора API, а не написания под него враппера.
Я пишу под линукс на старом железе, у меня нет другого выбора кроме OpenGL 4.5, и моя текущая задача - изучение OpenGL API.
Пока столкнулся только с одним багом: команда glClearNamedFramebufferfi в одних дровах принимает 4 аргумента, в других 5
> 2) Слишком много всего нужно реализовывать
Прикинь, а я уже почти всё реализовал.
Не знаю сколько там в glium, но в моем враппере не хватает только Texture View.
> 3) Пользователи враппера достали с вопросами.
Ну дак а что он думал, выложит код, нагребет лайков и дело сделано?
Я вот лично для себя это пишу и выкладывать не собираюсь, а допиливаю по мере обнаружения проблем.
> В общем писать враппер над высокоуровневым GAPI (OpenGL, DX < 12) довольно
> бессмысленная затея.
И что ж, удалять теперь всё?
Следующие причины побудили меня заняться враппером:
1. Изучаю апи. Это главная задача, и я серьезно в ней продвинулся.
Если бы умел программировать компьютерную графику, взял бы gfx и уже писал бы игры.
2. Давно уже появился DSA, а все примеры с биндами — это ж уму непостижимо!
3. Переходил с крестов на раст именно ради безопасности, чтобы писать код и не бороться с вылетами. Команды загрузки данных постоянно приводили к вылетам — надо один раз во враппере прописать дополнительные проверки и больше об этом не запариваться.
4. Делаю простой однозначный интерфейс, чтобы не было необходимости за каждой ерундой лезть в мануалы.
Например, glNamedFramebufferTexture прикрепляет mip-уровень текстуры в зависимости от типа текстуры либо просто как изображение, либо как массив(layered).
А ещё есть glNamedFramebufferTextureLayer которая прикрепляет конкретный слой массива.
То есть задачу прикрепления изображения выполяет glNamedFramebufferTextureLayer и частично glNamedFramebufferTexture, а задачу прикрепления layered image - только glNamedFramebufferTexture.
И вот обо всём этом приходится думать при вызове большинства команд.
5. Ну и как я писал в начале, никакого кайфа нет писать вот такое:
glDrawElementsInstancedBaseVertexBaseInstance(mode, count, type, *indices, primcount, basevertex, baseinstance);
Последовал совету Suslik и сделал команду отрисовки через билдер, который сам всё что надо биндит и позволяет указывать только необходимые аргументы:
vao.get_draw_builder(&pipeline) .draw( ); vao.get_draw_builder( &pipeline) .set_indices_offset( 10) .set_indices_num( 12) .set_vertex_offset( 100) .set_instances_offset( 666) .set_instances_num( 333) .draw( );
Джек Аллигатор
> И что ж, удалять теперь всё?
Нет конечно.
Джек Аллигатор
> Пока столкнулся только с одним багом
У него как минимум под сотню активных пользователей (те которые вносят свой вклад в развитие проекта), и багов они нашли порядочно. Один уж точно со всем не столкнешься.
Джек Аллигатор
> Переходил с крестов на раст именно ради безопасности, чтобы писать код и не
> бороться с вылетами.
Я тоже пишу на расте свой двиг, только с минимальными обертками над OpenGL - только необходимое.
Джек Аллигатор
> vao.get_draw_builder(&pipeline)
> .set_indices_offset(10)
> .set_indices_num(12)
> .set_vertex_offset(100)
> .set_instances_offset(666)
> .set_instances_num(333)
> .draw();
в общем и целом не так уж плохо, но тут много тонкостей. например, почему твой vao вообще что-то там знает о пайплайне? почему твой vao знает что-то о инстансах? самое сложное в дизайне подобного кода — определить область влияния, а именно — кто за что должен отвечать и кто о чём дожен знать. разумеется, связей должно быть как можно меньше и иерархия зависимостей должна быть как можно прозрачнее. я смотрел очень мельком, но мне понравился подход, который используется в http://vulkano.rs/guide/device-creation — хоть это и обёртка вокруг вулкана, но общие паттерны использования gapi объектов там реализованы очень неплохо, я считаю. на C++ я не видел gapi обёрток такого качества.
Suslik, спасибо! Буду думать.
> почему твой vao вообще что-то там знает о пайплайне?
1. Изначально имеем следующий код:
glBindProgramPipeline(pipeline_id);
glBindVertexArray(vao_id);
glDrawElements(GL_TRIANGLES, indices_num, GL_UNSIGNED_INT, indices_offset);
2. Сделали обертку над VAO и Pipeline:
pipeline.bind();
vao.bind();
glDrawElements(GL_TRIANGLES, indices_num, GL_UNSIGNED_INT, indices_offset);
3. Не пользуемся устаревшими практиками, а значит команды glDrawElements* подразумевают что какой-то VAO всегда забинден.
Если вместо GL_TRIANGLES будем рисовать GL_TRIANGLE_STRIP, придется соответственно перезалить буфер индексов.
Та же история с типом данных GL_UNSIGNED_INT.
Следовательно, можно эти два параметра указывать во время прикрепления буфера индексов к VAO.
pipeline.bind();
vao.bind();
glDrawElements(vao.mode, indices_num, vao.indices_type, indices_offset);
4. Обертка над командой отрисовки может быть трех видов:
а) спрячем код выше в функцию:
draw(pipeline, vao, indices_num, indices_offset);
б) представим функцию из варианта (а) как метод к pipeline(данный конвейер отрисовывает переданный в качестве аргумента VAO):
pipeline.draw(vao, indices_num, indices_offset);
в) либо как метод к vao(отрисовать данный VAO с использованием переданного в качестве аргумента конвейера):
vao.draw(pipeline, indices_num, indices_offset);
Я выбрал вариант (в).
5. В любом случае придется делать обертки над всеми вариантами команды отрисовки glDrawElements*
Более того, не всегда есть необходимость передавать даже число индексов и сдвиг от начала массива.
Поэтому делаем конструктор команды отрисовки. Получается обертка над glDrawElementsInstancedBaseVertexBaseInstance:
vao.get_draw_builder(&pipeline)
vao.get_draw_builder(&pipeline)
.draw();
.set_indices_offset(10)
.set_indices_num(12)
.set_vertex_offset(100)
.set_instances_offset(666)
.set_instances_num(333)
.draw();
Подобная обретка и для glDrawRangeElementsBaseVertex без аргументов инстансинга.
Без конструктора остаются методы
vao.draw_multiple(pipeline, draw_params);
vao.draw_multiple_vertex_offset(pipeline, draw_params);
vao.draw_indirect(...);
vao.draw_indirect_multiple(...);
Джек Аллигатор
> .set_indices_offset(10)
> .set_indices_num(12)
> .set_vertex_offset(100)
> .set_instances_offset(666)
> .set_instances_num(333)
> .draw();
Мне кажется это неправильно. Ты забудешь вызвать один из set методов и компилятор даже не ругнется.
0xc0de, это опциональные параметры, он и не должен ругаться: The builder pattern
Реализация метода builder.draw():
pub fn draw(self){ let ( draw_mode, indices_type) = self.vao.prepare_to_drawing( self.pipeline); let indices_offset = self.indices_offset.unwrap_or( 0); let indices_num = self.indices_num.unwrap_or_else( || self.vao.indices_num - indices_offset); let instances_num = self.instances_num.unwrap_or( 1); let vertex_offset = self.vertex_offset.unwrap_or( 0); let instances_offset = self.instances_offset.unwrap_or( 0); glDrawElementsInstancedBaseVertexBaseInstance( draw_mode, indices_num, indices_type, get_indices_offset_b( indices_type, indices_offset), instances_num, vertex_offset, instances_offset); }
Заместо отсутствующих аргументов устанавливаются дефолтные.
Надо бы конечно добавить проверки на выход за пределы буферов, но пока и так сойдет.
Тема в архиве.