На счёт статистики FPS - по-хорошему надо сделать какой-то режим бенчмарка - с запрограммированной траекторией камеры, чтобы результаты были сравнимы между запусками.
Динамические тени есть от динамических источников света - через карты теней. Но пока в них не рисуются модели из треугольников, что просто не реализовано, хотя практически вполне возможно.
С тенями от статического света всё не так хорошо. Можно рисовать тёмную кляксу-декаль под ногами, как делалось в Quake III Arena, это просто и быстро. Можно делать фейки, как в Quake II, когда модель проецируется на уровень пола и рисуется чёрным цветом с полупрозрачностью, это чуть сложнее, но тормознутее. В конце концов можно даже находить честное пересечение проекции треугольников модели с геометрией уровня, что будет давать весьма хороший результат, но будет жутко тормозить.
Ну а на счёт стенсильных теней в стиле Doom 3 - такое маловероятно. Для них нужно строить буфер глубины и держать стенсил-буфер, кроме того, надо строить теневые объёмы для моделей, что мало того что медленно, так ещё и требует особой топологии моделей (модели с дыркаи будут отбрасывать кривые тени).
Если возникнет такая потребность - могу изменить лицензию. Как автор, я могу себе такое позволить.
На счёт ECS: я с этим сильно не заморачивался, ибо движок имеет мало перспектив использования. Если будут перспективы, можно будет улучшать околоигровой код (и не только).
На счёт других замечаний по коду - опять же, некоторые моменты сделаны в спешке, лишь бы было. Потом можно будет сделать по-нормальному, если проект получит развитие.
В Doom и играх на движке Build воксельные модели смотрятся хорошо, т. к. там освещение посекторное. Там же, где освещение более реалистичное (через светокарты) воксельные модели будут смотреться плоско, ибо у них нету никаких нормалей, через которые бы можно было бы сделать вариативность освещения.
Не думаю, что вне ВР в этой технологии имеется особый смысл. К тому же артефакты её использования могут смотреться весьма некрасиво.
Ну и в случае программного рендеринга даже вычисление репроекции весьма накладно. Лучше тогда использовать иные методы достижения плавности, если это необходимо, например, динамически варьировать разрешение экрана и разрешение поверхностей.
Код под GNU GPL - потому, что я сторонник свободного ПО.
Стиль кода такой - по привычке.
hecs потому - что это была первая из рассмотренных мною библиотек, которая более-менее подошла под мои нужды. Возможно, и что-то другое подошло бы, но до них я не добрался. В целом вопрос использования ECS библиотеки в этом проекте не самый важный.
Интринсики используются потому, что проще было их самому напрямую заиспользовать, чем искать библиотеки-обёртки.
1) Анимации моделей из треугольников "дружить" с BSP не требуется. Сейчас при рисовании моделей решительно всё равно, как получены координаты их вершин. Поэтому сейчас возможны произвольные анимации, хоть ragdoll. Сортировки треугольников разных мешей между собою нету, это было бы слишком накладно. В большинстве случаев это и не нужно - объекты ведь друг в друга не должны проникать чисто из физических соображений. Да, в такой схеме нельзя будет двух обнимающихся NPC корректно отобразить, но это и не сильно нужно. А если вот прям совсем надо - можно две модели сделать одной.
2) На счёт изложенных вами трюков растеризации: растеризация не вдоль линий (по столбцам и диагоналям) может навредить локальности записи в память. Я конечно это не проверял, но может так выйти, что в итоге производительность будет только хуже.
Ну так и не строится для моделей с анимацией BSP-дерево. Для неё используется просто сортировка. В статье это упомянуто.
Про коррекцию перспективы я в статье упомянул. У меня используется честное попиксельное деление. Трюки с кусочно-линейной перспективной проекцией (с делением каждые N пикселей в линии) не используются.
Кроме того есть ещё один трюк, который я не упомянул - в зависимости от ориентации полигона может использоваться версия функции растеризации с линейной интерполяцией текстурных координат вдоль всей линии. Это возможно, если глубина в линии близка к постоянной. Обычно это условие наблюдается для полигонов пола и потолка.
Ещё есть функция растеризации вовсе без перспективной проекции, которая употребляется для очень далёких полигонов, на которых отсутствие перспективной коррекции не будет заметно.
Все переменные, когда-либо поименованные в программе
Все локальные переменные, ссылки, а также промежуточные переменные и ссылки.
Должны ли быть ими не имеющие отдельного собственного имени элементы массива
Единица контроля для переменных - одна стековая аллокация.
Остается ли узел тем же самым, если его переменной что-либо присвоили?
Узел остаётся тем же самым. Возможно только добавляются связи
что будет с графом, если начать поочередно снимать комментарии со строк 4-7
Пока что связи могут только добавляться. Связи удалятся вместе с окончанием жизни переменной.
a->next->next = a
А так вообще нельзя, пока что. Не позволено иметь более одного уровне косвенности на уровне типа - ссылка в структуре не может быть типа, который имеет ссылки внутри. Чисто технически это можно обойти через сырые указатели и создать библиотечный класс связанного списка, но при этом все элементы такого списка будут считаться частью переменной списка.
Возможно, что-то прояснить поможет документацитя. Но даже если прояснения не наступит, то это не страшно. На практике полного понимания внутреннего устройства компилятора не нужно, чтобы писать на языке что-либо.
Граф ссылок - слишком сложная абстракция для восприятия, да.
Если в кратце, то узлы этого графа - это переменные/ссылки, а рёбра - связи между ними. При этом связь эта родовая - а не указывающая, что означает, что один узел является производным от другого (порождён им). Иллюстрации в моём предыдущем комментарии как раз показывают подобные связи.
Быть может, у Вас граф ссылок хранит все связи, какие только были замечены, не только существующие единомоментно?
Граф ссылок таки хранит связи, которые логически были созданы. Если ссылка a указывает на переменную b, но не на c, то будет существовать только связь из a в b.
Не согласен с тезисами, изложенными в данной статье. Аналогия транспортных сетей и сетей обмена информацией - ложна. Слишком разный масштаб. Оптоволоконный кабель с умопомрачительной пропускной способностью стоит в пересчёте на километр на порядки меньше самой простой догори с твёрдым покрытием. Есть также проблема занимаемого пространства - в городах иногда бывает просто негде проложить дорогу, приходится за большие деньги строить эстакады или рыть тоннели. Поэтому изложенный в статье подход к транспорту не работает. Чтобы выжать максимум эффективности, придётся оптимизировать всю систему целиком, не получится за разумные бюджеты построить универсальную инфраструктуру, которую было бы удобно использовать широкому кругу транспортных средств. Универсальная инфраструктура по определению не может быть оптимальной, для оптимальности придётся делать её неуневерсальной - пускать где надо трамвай, где надо троллейбусы, где-то рыть метро а где-то и ограничивать движение личного транспорта.
линтер, который делал бы все те же проверки и запрещал бы ровно то же
Это ограниченное решение. В некоторой степени доработка инструментария существующих языков может принести пользу. Но некоторые проблемы таким способом решить будет не возможно, ну или возможно, но очень сложно. Вон, статический анализатор C++ - PVS-Studio целая компания в течении многих лет разрабатывает и он всё ещё не идеален.
Но с практической точки зрения, вот вы лет 5 уже на это потратили, а пользоваться этим вряд ли кто-то когда-то будет.
Популяризация языка является не единственной целью его разработки. Да, это было бы желательно, но это не обязательно. Даже без этого я в процессе получил много опыта и (если можно так выразиться) развлекался этим.
Нет, не верно. Тип Iterator это нечто вроде такого: struct Iterator { T* data; size_t size; }
В статье речь идёт немного о другом - не о том, куда и как указывают какие ссылки/указатели во время выполнения, я о том, как во время компиляции это всё учитывается внутри компилятора. И одно не совсем совпадает с другим.
Давайте продемонстрирую сказанное диаграммой. В начале функции граф ссылок выглядит как-то так:
А что с вызовами функций из разделяемых библиотек? Ведь нету гарантии, что они будут загружены в нижние 4Гб адресного пространства, а значит нужно будет делать вызовы через восьмибайтные указатели.
Чисто в теории я действительно не силён, я больше практик. Поделитесь ссылкой на алгоритм преобразование НКА в ДКА и/или на литературу по теме, с удовольствием почитаю.
без бэктрекинга
Я знаю такой способ, в нём входная строка просто обходится посимвольно и никогда не происходит отката назад. А вместо хранения стека состояний там хранится стек т. н. потоков. Смотреть здесь, раздел Thompson's Implementation. Но, насколько я понимаю, такой алгоритм в реальности не самый быстрый, да и компилируется в нативный код он весьма плохо.
Дело ведь в том, что если не будет отката назад, не будет возможности искать сопоставление для некоторых регулярных выражений, где эта самая квадратичность нужна. Но там, где она не нужна, компилятор и так во многих случая может заменить последовательность вложенных вызовов набором последовательных операций (в рамках одной функции).
Вывод конфигурации сцены - однозначно стоит.
На счёт статистики FPS - по-хорошему надо сделать какой-то режим бенчмарка - с запрограммированной траекторией камеры, чтобы результаты были сравнимы между запусками.
Динамические тени есть от динамических источников света - через карты теней. Но пока в них не рисуются модели из треугольников, что просто не реализовано, хотя практически вполне возможно.
С тенями от статического света всё не так хорошо. Можно рисовать тёмную кляксу-декаль под ногами, как делалось в Quake III Arena, это просто и быстро. Можно делать фейки, как в Quake II, когда модель проецируется на уровень пола и рисуется чёрным цветом с полупрозрачностью, это чуть сложнее, но тормознутее. В конце концов можно даже находить честное пересечение проекции треугольников модели с геометрией уровня, что будет давать весьма хороший результат, но будет жутко тормозить.
Ну а на счёт стенсильных теней в стиле Doom 3 - такое маловероятно. Для них нужно строить буфер глубины и держать стенсил-буфер, кроме того, надо строить теневые объёмы для моделей, что мало того что медленно, так ещё и требует особой топологии моделей (модели с дыркаи будут отбрасывать кривые тени).
Если возникнет такая потребность - могу изменить лицензию. Как автор, я могу себе такое позволить.
На счёт ECS: я с этим сильно не заморачивался, ибо движок имеет мало перспектив использования. Если будут перспективы, можно будет улучшать околоигровой код (и не только).
На счёт других замечаний по коду - опять же, некоторые моменты сделаны в спешке, лишь бы было. Потом можно будет сделать по-нормальному, если проект получит развитие.
В Doom и играх на движке Build воксельные модели смотрятся хорошо, т. к. там освещение посекторное. Там же, где освещение более реалистичное (через светокарты) воксельные модели будут смотреться плоско, ибо у них нету никаких нормалей, через которые бы можно было бы сделать вариативность освещения.
Не думаю, что вне ВР в этой технологии имеется особый смысл.
К тому же артефакты её использования могут смотреться весьма некрасиво.
Ну и в случае программного рендеринга даже вычисление репроекции весьма накладно. Лучше тогда использовать иные методы достижения плавности, если это необходимо, например, динамически варьировать разрешение экрана и разрешение поверхностей.
Код под GNU GPL - потому, что я сторонник свободного ПО.
Стиль кода такой - по привычке.
hecs потому - что это была первая из рассмотренных мною библиотек, которая более-менее подошла под мои нужды. Возможно, и что-то другое подошло бы, но до них я не добрался. В целом вопрос использования ECS библиотеки в этом проекте не самый важный.
Интринсики используются потому, что проще было их самому напрямую заиспользовать, чем искать библиотеки-обёртки.
1) Анимации моделей из треугольников "дружить" с BSP не требуется. Сейчас при рисовании моделей решительно всё равно, как получены координаты их вершин. Поэтому сейчас возможны произвольные анимации, хоть ragdoll.
Сортировки треугольников разных мешей между собою нету, это было бы слишком накладно. В большинстве случаев это и не нужно - объекты ведь друг в друга не должны проникать чисто из физических соображений. Да, в такой схеме нельзя будет двух обнимающихся NPC корректно отобразить, но это и не сильно нужно. А если вот прям совсем надо - можно две модели сделать одной.
2) На счёт изложенных вами трюков растеризации: растеризация не вдоль линий (по столбцам и диагоналям) может навредить локальности записи в память. Я конечно это не проверял, но может так выйти, что в итоге производительность будет только хуже.
Ну так и не строится для моделей с анимацией BSP-дерево. Для неё используется просто сортировка. В статье это упомянуто.
Про коррекцию перспективы я в статье упомянул. У меня используется честное попиксельное деление. Трюки с кусочно-линейной перспективной проекцией (с делением каждые N пикселей в линии) не используются.
Кроме того есть ещё один трюк, который я не упомянул - в зависимости от ориентации полигона может использоваться версия функции растеризации с линейной интерполяцией текстурных координат вдоль всей линии. Это возможно, если глубина в линии близка к постоянной. Обычно это условие наблюдается для полигонов пола и потолка.
Ещё есть функция растеризации вовсе без перспективной проекции, которая употребляется для очень далёких полигонов, на которых отсутствие перспективной коррекции не будет заметно.
Статья конечно интересная, но мне так и не понятно, каким образом в будущем у меня будет появляться Open-Source хлеб и электроэнергия по лицензии MIT.
"Мем про парня и двух девушек"
Я имел в виду этот:
и композиционно оно даже как-то похоже.
Не увидел в описании ничего про выделение памяти, сборку мусора. Про ленивые списки тоже ничего не сказано. Это всё реализовано, или ещё нет?
Мне кажется, после C++14 уже перебор вышел с constexpr. Вызывать какие-то функции это ещё нормально, но вот выделять/освобождать память - это перебор.
Ещё не понял, зачем нужен
constexpr!
для функций, если можно использоватьconstexpr
для результата её вызова.Все локальные переменные, ссылки, а также промежуточные переменные и ссылки.
Единица контроля для переменных - одна стековая аллокация.
Узел остаётся тем же самым. Возможно только добавляются связи
Пока что связи могут только добавляться. Связи удалятся вместе с окончанием жизни переменной.
А так вообще нельзя, пока что. Не позволено иметь более одного уровне косвенности на уровне типа - ссылка в структуре не может быть типа, который имеет ссылки внутри. Чисто технически это можно обойти через сырые указатели и создать библиотечный класс связанного списка, но при этом все элементы такого списка будут считаться частью переменной списка.
Возможно, что-то прояснить поможет документацитя. Но даже если прояснения не наступит, то это не страшно. На практике полного понимания внутреннего устройства компилятора не нужно, чтобы писать на языке что-либо.
Граф ссылок - слишком сложная абстракция для восприятия, да.
Если в кратце, то узлы этого графа - это переменные/ссылки, а рёбра - связи между ними. При этом связь эта родовая - а не указывающая, что означает, что один узел является производным от другого (порождён им). Иллюстрации в моём предыдущем комментарии как раз показывают подобные связи.
Граф ссылок таки хранит связи, которые логически были созданы. Если ссылка
a
указывает на переменнуюb
, но не наc
, то будет существовать только связь изa
вb
.Не согласен с тезисами, изложенными в данной статье.
Аналогия транспортных сетей и сетей обмена информацией - ложна. Слишком разный масштаб. Оптоволоконный кабель с умопомрачительной пропускной способностью стоит в пересчёте на километр на порядки меньше самой простой догори с твёрдым покрытием. Есть также проблема занимаемого пространства - в городах иногда бывает просто негде проложить дорогу, приходится за большие деньги строить эстакады или рыть тоннели.
Поэтому изложенный в статье подход к транспорту не работает. Чтобы выжать максимум эффективности, придётся оптимизировать всю систему целиком, не получится за разумные бюджеты построить универсальную инфраструктуру, которую было бы удобно использовать широкому кругу транспортных средств. Универсальная инфраструктура по определению не может быть оптимальной, для оптимальности придётся делать её неуневерсальной - пускать где надо трамвай, где надо троллейбусы, где-то рыть метро а где-то и ограничивать движение личного транспорта.
Это ограниченное решение. В некоторой степени доработка инструментария существующих языков может принести пользу. Но некоторые проблемы таким способом решить будет не возможно, ну или возможно, но очень сложно. Вон, статический анализатор C++ - PVS-Studio целая компания в течении многих лет разрабатывает и он всё ещё не идеален.
Популяризация языка является не единственной целью его разработки. Да, это было бы желательно, но это не обязательно. Даже без этого я в процессе получил много опыта и (если можно так выразиться) развлекался этим.
Нет, не верно. Тип
Iterator
это нечто вроде такого:struct Iterator
{
T* data;
size_t size;
}
В статье речь идёт немного о другом - не о том, куда и как указывают какие ссылки/указатели во время выполнения, я о том, как во время компиляции это всё учитывается внутри компилятора. И одно не совсем совпадает с другим.
Давайте продемонстрирую сказанное диаграммой.
В начале функции граф ссылок выглядит как-то так:
Потом так:
А после присваивания it = it_next, так:
А что с вызовами функций из разделяемых библиотек? Ведь нету гарантии, что они будут загружены в нижние 4Гб адресного пространства, а значит нужно будет делать вызовы через восьмибайтные указатели.
Чисто в теории я действительно не силён, я больше практик. Поделитесь ссылкой на алгоритм преобразование НКА в ДКА и/или на литературу по теме, с удовольствием почитаю.
Я знаю такой способ, в нём входная строка просто обходится посимвольно и никогда не происходит отката назад. А вместо хранения стека состояний там хранится стек т. н. потоков.
Смотреть здесь, раздел Thompson's Implementation. Но, насколько я понимаю, такой алгоритм в реальности не самый быстрый, да и компилируется в нативный код он весьма плохо.
Дело ведь в том, что если не будет отката назад, не будет возможности искать сопоставление для некоторых регулярных выражений, где эта самая квадратичность нужна. Но там, где она не нужна, компилятор и так во многих случая может заменить последовательность вложенных вызовов набором последовательных операций (в рамках одной функции).