Здравствуйте.
Если опустить долгое предисловие, то есть разные версии OpenGL. Начиная с 3.х
оно стало работать быстрее, но отвалилась поддержка старых видеокарт.
По-этому, если хочется, чтобы всё работало как на старых, так и на новых видеокартах, то надо писать два одинаковых проекта. Один с использованием OpenGL ниже 3.x
, другой с 3.x
или выше.
Собственно, я так и сделал. Код уже давно написан. Всё работает.
Но возникла проблема с нумерацией версий. Как обозначить, какую версию использует проект - ниже 3.x
или выше?
Он же в 2008 вышел. Вам точно нужны видеокарты, которым 15 лет?)
Что за проект? Обычно надо только ту часть, которая собственно использует OpenGL (рендеринг, …). Точнее скорее даже не всю часть, они ж не убрали/заменили всё, что было до 3 )
Ну… я же не Крайзис свой собираюсь написать Там особая производительность не требуется.
Скорее всего, я просто забью на поддержку старых видеокарт. Но просто я хочу, чтобы хотя-бы первые версии запускались на относительно старых компьютерах со старой ОС (пусть и с потерей FPS).
Ой…Ой-ёй-ёй Даже не спрашивайте
Это такая большая мега-глупость, что пока дело не дойдёт до чего-то более-менее презентабельного, об этом даже говорить стыдно
То есть? Ведь всё-равно же придётся вести два отдельных проекта.
Если рендеринг нормально изолирован, то просто сделать две реализации этой части с одним интерфейсом (в смысле interface
в C#, или просто функции с одинаковыми параметрами) и автоматически выбирать.
Естественно, я почти ни слова не понял
Это, типо, разные рендереры в разных dll
должны быть?
Да и в одной быть или вообще без длл вроде бы ничего не мешает.
C# и .NET | Применение интерфейсов
Просто присвоить в переменную соотв. реализацию или функцию.
IRenderer renderer = supportsOpengl3 ? new Opengl3Renderer() : new Opengl2Renderer();
renderer.render();
Спокойствие Я знаю, что такое интерфейс. Не всё так плохо
Просто я не представляю, как можно засунуть в интерфейс целый рендеринг Это ведь не просто функция.
В старом и новом OpenGL объекты создаются по-разному. Вертексные буфера создаются по-разному. И рендерить их тоже можно по-разному.
Да и сам контекст OpenGL ведь тоже по-разному создаётся и настраивается.
Так не важно, хоть Вулкан или DirectX, или ASCII )
Это ж всё внутри рендереров. Которые обычно просто показывают состояние приложения.
Вся логика, взаимодействие с пользователем и т.д. останутся теми же, только поменять функцию отрисовки.
Ну с отрисовкой еще как-то более-менее понятно, как её в интерфейс запихать.
А вот с созданием контекста как-то не очень.
Например, для старого OpenGL я просто создаю WinAPI окно, и делаю так:
case WM_CREATE:
hPanelRender = CreateWindow("Static", "OpenGL renderer",
WS_CHILD | WS_VISIBLE | SS_BITMAP | SS_NOTIFY, 0, 0, 0, 0,
wnd, NULL, myInstance, NULL);
SetWindowLong(hPanelRender, GWL_WNDPROC, (long)&PanRenderProc);
dcPanelRender = GetDC(hPanelRender);
SetDCPixelFormat(dcPanelRender);
dcGL = wglCreateContext(dcPanelRender);
wglMakeCurrent(dcPanelRender, dcGL);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 1.0f, 1.0f);
break;
case WM_DESTROY:
wglMakeCurrent(dcPanelRender, 0);
wglDeleteContext(dcGL);
ReleaseDC(hPanelRender, dcPanelRender);
PostQuitMessage(0);
break;
А для нового использую GLFW
(потому что не знаю, как сделать это на WinAPI):
if (!glfwInit())
{
std::cout << "glfwInit() failed!" << std::endl;
return 1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* glfwWindow = glfwCreateWindow(screenWidth, screenHeight,
(char*)"camera test", nullptr, nullptr);
if (!glfwWindow)
{
glfwTerminate();
std::cout << "glfwCreateWindow() failed!" << std::endl;
return 1;
}
glfwMakeContextCurrent(glfwWindow);
glewExperimental = true;
if (glewInit() != GLEW_OK)
{
glfwTerminate();
std::cout << "glewInit() failed!" << std::endl;
return 1;
}
//....и тут ещё куча кода
Можно просто и для старого взять GLFW
)
Да я знаю Но всё-равно пока не особо понятно, как создание в интерфейс запихнуть.
По-идее, должен быть какой-то базовый интерфейс IOpenGlBase
. А от него наследуем два других : IOpenGlNew
и IOpenGlLegacy
В правильном направлении мыслю?
Ну если начинать менять прямо с создания окна, то тогда нужны еще абстракции для этого, как всякие GUI фреймворки типа Qt.
И тогда проще взять Qt и его виджет для OpenGL )
Как вариант можно было бы прицепить GLFW к созданному ранее винапи окну, но GLFW вроде пока не умеет так.
Начинать менять что? Ещё толком и нет ничего, кроме двух полу-рабочих прототипов.
Это я правильно предположил?
Какие абстракции? Для событий окна и клавиатуры с мышью?
Ну если окно всегда одинаково создается, и менять только функцию отрисовки внутри него, то всё просто.
А если окно надо создавать по-разному, и потом еще и взаимодействовать с окном разными способами, то всё сложнее, тогда еще надо создавать абстракции вокруг этого (разные реализации окна, …, типа WinApiWindow
, GlfwWindow
наследующие/реализующие Window
).
Но GLFW
же сам является такой абстракцией. Поэтому
А, ну да, я так и подумал
Это всё, конечно, замечательно. Но задача еще в том, чтобы программа могла работать на Windows XP. Да, я мазохист и мне нечем заняться
А это значит, что никакие новые фреймворки не подойдут. Просто запихнуть рендереры в интерфейсы - ничего не даст. Чтобы работало на ХР, надо писать на Java. Так оно, заодно, и в линуксе нативно запустится. Нафига? Ну вот приспичило. Хочу и всё тут
Собственно, я всё уже давно написал. Работает и на Java и на старом компе с ХР и в линуксе (только код надо отрефакторить и оптимизировать, контроль версий включить).
Осталась только одна проблема. Как-то пометить одну из версий, что она использует старый OpenGL. А ту, которая использует новый, можно оставить вообще без метки.
В интернете видел, что старый OpenGL иногда называют Legacy
(а новый Modern
). Но не знаю, насколько корректно так делать
Получается, что версия будет выглядеть как-то так: MyDreamProject-0.5.2-alpha-legacy