Russian Qt Forum
Ноябрь 22, 2024, 10:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Код "на будущее"  (Прочитано 9933 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Август 25, 2020, 18:30 »

Добрый день

Сейчас занимаюсь портированием кода рисования на OpenGL 3.3, сделал примерно 75%, но еще много осталось. Весьма вероятно что для OSX потребуется еще портинг на "metal", возможно еще до окончания текущего. На бздошном Вындоуз, напротив, маловероятно, но в принципе возможно захотят "vulcan". В любом случае вырисовывается мрачное будущее с поддержкой кросс-платформенности "руками" Плачущий

Ну и как же мне планировать код рисования "в преддверии" новых портирований? Ни "metal" ни "vulcan" никогда не видел и ничего не читал. Видел ссылку (возможно дали на этом форуме) на проект что "автоматом" переводит с OpernGL 3.3 на metal. Вряд ли покатит, но обнадеживает.

Что можете порекомендовать (можно и "настоятельно")? Ну там использовать PIMPL и все такое... Или же "нужно знать задачу" и сначала почитать metal, а там видно будет (может быть)?

Спасибо
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #1 : Август 25, 2020, 19:01 »

для метала есть прослойка из вулкана: https://github.com/KhronosGroup/MoltenVK
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Август 27, 2020, 10:34 »

для метала есть прослойка из вулкана: https://github.com/KhronosGroup/MoltenVK
Спасибо конечно, но как-то мне  "не с руки". Это выходит нужно сначала переться на vulkan (который пока не нужен) а потом уж... Боюсь меня просто не хватит на 2 новых API

По поводу прослоек такого рода. Пользовался подобными, и сам пару раз лепил. Хорошее дело для "быстрого старта" но рано или поздно все равно все сводилось к "полному" ручному портингу.

Собсно вопрос/тема весьма общие, чисто "покалякать" (в чем нет ничего плохого) как "подстелить соломки" зная что скоро портинг будет. Ну ясно не разбрасывать вызовы OpenGL по всей хате, а сосредоточить их в одном или неск файлах, сделать обертки. Что еще можно сделать?

Теоретики/эрудиты, ну где же Вы ?  Улыбающийся
Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #3 : Август 27, 2020, 19:59 »

OpenGL 5.0 вышел? Что-то гуглится.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Август 28, 2020, 12:40 »

OpenGL 5.0 вышел? Что-то гуглится.
Зачем за этим следить? Портирование - тупая, но неизбежная работа, она Вас сама найдет
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #5 : Сентябрь 01, 2020, 14:53 »

Вопрос:

Что еще можно сделать?

Ответ:

Ну ясно не разбрасывать вызовы OpenGL по всей хате, а сосредоточить их в одном или неск файлах, сделать обертки.

Улыбающийся

Ну от себя еще добавлю, если надо будет портировать на "то не знаю что", то можно заранее попробовать в качестве "нового АПИ" сделать какой-нибудь фейк на базе чего-то уже известного, например, любой Software Renderer. Таким образом, будет уже 2 реализации - СофтвароФейк и OpenGL, плюс вырисуется "общий АПИ" и порешаются некоторые нюансы. Потом и на вулкан будет легче идти...
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Сентябрь 02, 2020, 12:08 »

Ну от себя еще добавлю, если надо будет портировать на "то не знаю что", то можно заранее попробовать в качестве "нового АПИ" сделать какой-нибудь фейк на базе чего-то уже известного, например, любой Software Renderer. Таким образом, будет уже 2 реализации - СофтвароФейк и OpenGL, плюс вырисуется "общий АПИ" и порешаются некоторые нюансы. Потом и на вулкан будет легче идти...
А этот вариант уже был Улыбающийся Потом снес, но кое-какие прокладки остались. Приложение намного старше OpenGL, сначала рендерили сами. Правда на приличных сценах скорость падала до 1-2 fps и ниже, а об AA и мечтать не могли. Когда появился OpenGL - очень обрадовались. Пусть он много чего не делал (или делал хреново), но это списывалось на молодость системы, а волшебные fps искупали все! Увы, OpenGL так и "остался молодым", напр несчастную phong transparency так и не дождались. Ну может с metal получше будет, хз

Реально проблемы возникают когда одна "engine" имеет фичи которых нет у другой. Напр soft render мог рисовать адаптивно, а OpenGL нет. Ну ясно надо лепить метод типа "Engine::CanDrawAdaptive" и потом по всему тексту.. ох и гемор Плачущий
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #7 : Сентябрь 10, 2020, 16:19 »

Реально проблемы возникают когда одна "engine" имеет фичи которых нет у другой. Напр soft render мог рисовать адаптивно, а OpenGL нет. Ну ясно надо лепить метод типа "Engine::CanDrawAdaptive" и потом по всему тексту.. ох и гемор Плачущий

Это да Грустный Ну, или эмулировать как получится.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #8 : Сентябрь 10, 2020, 16:41 »

Кутешники по слухам работают над подобной абстракцией в qt6. Как и вы наступили на грабли "опенгл хватит всем"
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Сентябрь 11, 2020, 13:13 »

Ну почему "грабли"? Это нормальный процесс эволюции.

Предлагаю поговорить об архитектуре рисования. Шансов на успех мало - как всегда с архитектурой, но тут еще труднее, требуются познания в OpenGL, пусть минимальные. Но все же попробуем. Собсно процесс рисования в OpenGL выглядит так:

1) "забиндить" vao и активный шейдер. При этом какой шейдер сейчас должен юзаться - нужно долго разбираться  в зависимости от того что хотим рисовать

2) Передать данные (индексы, вертексы, нормали, цвет, текстуры и.т.п) также забиндив их. Ну и конечно установить матрицы (столь любимые нами)

3) Установить окно/контекст и вызвать команду рисования, их немного (обычно glDrawElements или glDrawArrays).

4) Культурно "отбиндить" все, иначе нарвемся на неприятности

Все это кажется очень простым, если бы не "мелочи" или "детали". Одна команда рисования выводит примитивы одного типа (напр только тр-ки), а рисуемый объект может иметь mixed геометрию (напр и точки, и тр-ки и..). Многие (но не все) рисуемые имеют "материал" (фундаментальное понятие). Напр char обычно имеет разные текстуры для головы, рук, body и т.п. Также рисовать требуется всяко-разно - c текстурами, без, wireframe, силуэт и.т.п

Ну ладно, первый шаг очевиден: нужен класс "Engine" который "инкапсулирует" (мы знаем вумные слова) работу с OpenGL - а в перспективе и с др "back-end'ом' (правильно?). Ну попробуем что-то написать

Код
C++ (Qt)
void MyWindow::DrawObject( Object * obj,           // рисуемый объект (напр сфера)
                  TDrawStyle style )   // стиль рисования (напр phong)
{
 m_engine->SetupShaders(...);   // установили нужный шейдер
 
// установка данных
 switch (style) {
   case style_Phong:
 
// устанавливаем текстуры
     auto maps = obj->GetMaps2Draw();
     for (const auto & m : maps)
      m_engine->AddTexture(m);
 
// устанавливаем вертексы
      m_engine->SetVertices(obj->GetVertices());
 
// устанавливаем нормали
...
// устанавливаем ..
...
     break;
 }
 m_engine->Draw();     // рисуем
 m_engine->ReleaseShaders();   // культурно уходим
}
Код установки занимает много страниц, и, вероятно, будет еще расти. Др моменты (SetupShaders и Draw) здесь не показаны, но, как мы знаем, там тоже все не так просто. Также заметно что хотя OpenGL в явном виде здесь нет - многое все равно на него завязано.

Вопрос: достаточно ли такого взаимодействия Window <-> Engine или нужны еще классы? Если да то какие, и что они должны делать?

Спасибо


« Последнее редактирование: Сентябрь 11, 2020, 13:14 от Igors » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Сентябрь 11, 2020, 14:57 »

Ну ответы вряд ли последуют, здесь реально трудно (хотя буду рад ошибиться). Попробую чуть продолжить. Что плохо в приведенном псевдокоде?

Плохо что это "god-method" (хотя слышал только gpd-class). Метод неприятно велик и использовать его повторно не удается. Да, он обеспечивает рисование 3D объектов, но, помимо них, надо еще много чего рисовать (оси, стрелки, сетки, регионы всякие и.т.п). Как-то сделать базовый класс и подсунуть его первым аргументом - захлебнемся в if'ах на установке. Приходится выписывать ф-ции рисования и для всего остального. А поскольку требуются все новые и новые отрисовки - это становится проблемой. Я постоянно вынужден писать/переписывать разнообразные Draw
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Сентябрь 12, 2020, 10:28 »

Продолжу монолог Улыбающийся

Вообще если все статычно, то все решается, ну рано или поздно я заткну все дырки в SetupShaders и Draw и получу рабочий вариант. Но дело в том что постоянно требуются новые фичи, и моя архитектура оказывается к ней совершенно не приспособленной. Вот этим летом опять получил по дюнделю - потребовался "instanced" render, т.е. некоторые объекты нужно выводить N раз в одной команде рисования с различными трансформами (матрицами). Мало того что пришлось все шейдеры переписать (с железяки что возьмешь), но и плюсовый код развалился. Ну кое-как собрал, теперь готовлюсь получить на metal  Улыбающийся

Что же я делаю не так, и как надо "правельно"? А заниматься этим никто не хочет. Ну оно и понятно, ведь жрать справочник и обогащать свой багаж знаний куда легче и приятнее. Наверно мне надо было больше "ходить с карандашом и блокнотом" - а то сделал не подумавши, и вот ... Или "завязаться на С++ 17" - оно все решит! Или вообще "изменить архитектуру своего приложения". Умных советов масса (да еще каких!), это я бестолковый  Улыбающийся
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #12 : Сентябрь 14, 2020, 09:54 »

Вам нужно постараться выделить абстрактный уровень, на котором команды отрисовки выглядят вроде MyBigGreenSphere.draw(IDrawContext &dc);
И сделать имплементацию собственно "движка" вроде:

class COpenGLContext: public IDrawContext;
...
class CVulkanContext: public IDrawContext;
...
class CSomeTestBullshitContext: public IDrawContext;
...

Далее каждая (в зависимости от "движка") имплементация MyBigGreenSphere будет реализовать свои методы draw и свои приватные данные.

Получим что то вроде

Код:
class COpenGlMyBigGreenSphere : public MyBigGreenSphere 
{
public:
virtual void draw(COpenGLContext &dc)
{
// специфичный для OpenGL код отрисовки
}
private:
// специфичные для OpenGL методы и данные
...
};

и так для каждого "двига". "god-method" в таком случае распределится между классами объектов.

"По моему так" (с) Винни Пух
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Сентябрь 14, 2020, 13:37 »

Вам нужно постараться выделить абстрактный уровень, на котором команды отрисовки выглядят вроде MyBigGreenSphere.draw(IDrawContext &dc);
И сделать имплементацию собственно "движка" вроде:
Это уже сделано, вернее "так всегда и было", упомянутый m_engine - указатель на абстрактный (базовый) класс.

Код:
class COpenGlMyBigGreenSphere : public MyBigGreenSphere 
{
public:
virtual void draw(COpenGLContext &dc)
{
// специфичный для OpenGL код отрисовки
}
private:
// специфичные для OpenGL методы и данные
...
};
Тут я не понял. Зачем рисуемому объекту COpenGlMyBigGreenSphere иметь методы специфичные для OpenGL? Напротив, нужно стремиться максимально юзать базовый IDrawContext

Собсно сейчас реализована классическая схема: есть "рисовальщик" (Engine или IDrawContext), в принципе тот же QPainter. Он пассивен, что ему сказали - то и рисует (если умеет). Поэтому вся нагрузка ложится на рисующих, тех кто скармливает ему данные рисования. Но, в отличие от QPainter, Engine интенсивно обновляется (даже при одном OpenGL движке). Конечно любое изменение ведет к немедленному обрушению кода зарядки данных и управления рисовальщиком. Это как рисовать гуй с постоянно изменяемым QPainter. Грядущее портирование - по сути та же проблема, только в большем объеме.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #14 : Сентябрь 15, 2020, 14:06 »

Цитировать
Зачем рисуемому объекту COpenGlMyBigGreenSphere иметь методы специфичные для OpenGL?

Ну потому что эта имплементация рисования конкретного типа объектов может иметь специфичные приватные методы и данные.
И чтобы вот это всё не расползалось по "рисовальщику" и не превращало его в God-Object, можно "взять и поделить".
Вместо того, чтобы каждый раз допиливать "рисовальщик" и молиться, что всё будет отрисовываться правильно после этого, можно менять только точечно - тогда риск что-либо сломать намного меньше.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.118 секунд. Запросов: 22.