/
cort
/
the-engine
Обзор
Документация
Войти
/
cort
/
the-engine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
main.cpp
407 строк
13 KB
Дмитрий Диордийчук
Исправлено:
01 дек 2024, 17:03
01 дек 2024, 17:03
6a82ac0
Код
Авторство
О чём код?
#include <bgfx/bgfx.h> #include <bgfx/platform.h> #include <bx/math.h> #include <SDL.h> #include <SDL_syswm.h> #include "bgfx-imgui/imgui_impl_bgfx.h" #include "file-ops.h" #include "imgui.h" #include "sdl-imgui/imgui_impl_sdl2.h" #if BX_PLATFORM_EMSCRIPTEN #include "emscripten.h" #endif // BX_PLATFORM_EMSCRIPTEN struct PosColorVertex { float x; float y; float z; uint32_t abgr; }; static PosColorVertex cube_vertices[] = { {-1.0f, 1.0f, 1.0f, 0xff000000}, {1.0f, 1.0f, 1.0f, 0xff0000ff}, {-1.0f, -1.0f, 1.0f, 0xff00ff00}, {1.0f, -1.0f, 1.0f, 0xff00ffff}, {-1.0f, 1.0f, -1.0f, 0xffff0000}, {1.0f, 1.0f, -1.0f, 0xffff00ff}, {-1.0f, -1.0f, -1.0f, 0xffffff00}, {1.0f, -1.0f, -1.0f, 0xffffffff}, }; static const uint16_t cube_tri_list[] = { 0, 1, 2, 1, 3, 2, 4, 6, 5, 5, 6, 7, 0, 2, 4, 4, 2, 6, 1, 5, 3, 5, 7, 3, 0, 4, 1, 4, 5, 1, 2, 3, 6, 6, 3, 7, }; static bgfx::ShaderHandle create_shader( const std::string& shader, const char* name) { const bgfx::Memory* mem = bgfx::copy(shader.data(), shader.size()); const bgfx::ShaderHandle handle = bgfx::createShader(mem); bgfx::setName(handle, name); return handle; } struct context_t { SDL_Window* window = nullptr; bgfx::ProgramHandle program = BGFX_INVALID_HANDLE; bgfx::VertexBufferHandle vbh = BGFX_INVALID_HANDLE; bgfx::IndexBufferHandle ibh = BGFX_INVALID_HANDLE; bgfx::FrameBufferHandle fbh = BGFX_INVALID_HANDLE; // Frame Buffer Handle bgfx::TextureHandle texture = BGFX_INVALID_HANDLE; // Texture Handle float cam_pitch = 0.0f; float cam_yaw = 0.0f; float rot_scale = 0.01f; int prev_mouse_x = 0; int prev_mouse_y = 0; int width = 0; int height = 0; int texture_width = 0; int texture_height = 0; bool quit = false; // Новые поля для отслеживания изменений размера окна bool window_resized = false; }; void main_loop(void* data) { auto context = static_cast<context_t*>(data); // Обработка событий SDL for (SDL_Event current_event; SDL_PollEvent(¤t_event) != 0;) { ImGui_ImplSDL2_ProcessEvent(¤t_event); if (current_event.type == SDL_QUIT) { context->quit = true; break; } // Обработка события изменения размера окна if (current_event.type == SDL_WINDOWEVENT && current_event.window.event == SDL_WINDOWEVENT_RESIZED) { context->width = current_event.window.data1; context->height = current_event.window.data2; context->window_resized = true; } } // Если окно было изменено, обновляем BGFX if (context->window_resized) { bgfx::reset(context->width, context->height, BGFX_RESET_VSYNC); bgfx::setViewRect(0, 0, 0, context->width, context->height); context->window_resized = false; } // Очистка основного вида BGFX bgfx::setViewClear( 0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000FF, 1.0f, 0); bgfx::setViewRect(0, 0, 0, context->width, context->height); bgfx::touch(0); // Начало нового кадра ImGui ImGui_Implbgfx_NewFrame(); ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); // Начало основного окна ImGui ImGui::Begin("BGFX Render Window"); // Получение размера области содержимого ImVec2 render_window_size = ImGui::GetContentRegionAvail(); // Проверка поддерживаемости текстуры if (!bgfx::isTextureValid( 0, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_RT)) { fprintf(stderr, "Texture format not supported!\n"); ImGui::End(); // Завершение ImGui окна перед возвратом return; } // Проверка и обновление размеров текстуры при изменении размера окна ImGui if (render_window_size.x != context->texture_width || render_window_size.y != context->texture_height) { context->texture_width = static_cast<uint16_t>(render_window_size.x); context->texture_height = static_cast<uint16_t>(render_window_size.y); // Уничтожаем старые текстуры и буфер кадра, если они существуют if (bgfx::isValid(context->fbh)) { bgfx::destroy(context->fbh); } if (bgfx::isValid(context->texture)) { bgfx::destroy(context->texture); } // Создаем новую текстуру context->texture = bgfx::createTexture2D( context->texture_width, context->texture_height, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_RT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP); // Создаем новый буфер кадра bgfx::TextureHandle texture_handles[] = {context->texture}; context->fbh = bgfx::createFrameBuffer( BX_COUNTOF(texture_handles), texture_handles, true); } // Установка вьюпорта BGFX для рендеринга в текстуру (viewId = 1) bgfx::setViewFrameBuffer(1, context->fbh); bgfx::setViewRect(1, 0, 0, context->texture_width, context->texture_height); bgfx::setViewClear(1, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000FF, 1.0f, 0); bgfx::touch(1); // Обновление матриц камеры float cam_rotation[16]; bx::mtxRotateXYZ(cam_rotation, context->cam_pitch, context->cam_yaw, 0.0f); float cam_translation[16]; bx::mtxTranslate(cam_translation, 0.0f, 0.0f, -5.0f); float cam_transform[16]; bx::mtxMul(cam_transform, cam_translation, cam_rotation); float view[16]; bx::mtxInverse(view, cam_transform); float proj[16]; bx::mtxProj( proj, 60.0f, float(context->texture_width) / float(context->texture_height), 0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth); bgfx::setViewTransform(1, view, proj); float model[16]; bx::mtxIdentity(model); bgfx::setTransform(model); bgfx::setVertexBuffer(0, context->vbh); bgfx::setIndexBuffer(context->ibh); bgfx::submit(1, context->program); // Начало дочернего окна для области рендеринга // Используем ImGuiWindowFlags_NoMove и ImGuiWindowFlags_NoResize для дополнительной изоляции ImGuiWindowFlags child_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; ImGui::BeginChild("RenderArea", ImVec2(0, 0), false, child_flags); // Отображение текстуры в дочернем окне ImTextureID tex_id = (ImTextureID)(uintptr_t)context->texture.idx; ImGui::Image(tex_id, render_window_size); // Обработка взаимодействия с изображением для вращения куба if (ImGui::IsItemHovered() && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) { ImVec2 delta = ImGui::GetIO().MouseDelta; context->cam_yaw += float(-delta.x) * context->rot_scale; context->cam_pitch += float(-delta.y) * context->rot_scale; } // Закрытие дочернего окна ImGui::EndChild(); // Закрытие основного окна ImGui ImGui::End(); // Завершение ImGui кадра ImGui::Render(); ImGui_Implbgfx_RenderDrawLists(ImGui::GetDrawData()); // Завершение BGFX кадра bgfx::frame(); #if BX_PLATFORM_EMSCRIPTEN if (context->quit) { emscripten_cancel_main_loop(); } #endif } int main(int argc, char** argv) { // Инициализация SDL if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf( stderr, "SDL could not initialize. SDL_Error: %s\n", SDL_GetError()); return 1; } printf("SDL Initialized successfully.\n"); const int width = 800; const int height = 600; SDL_Window* window = SDL_CreateWindow( "BGFX ImGui Example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL); SDL_SetWindowMinimumSize(window, width, height); if (window == nullptr) { fprintf( stderr, "Window could not be created. SDL_Error: %s\n", SDL_GetError()); return 1; } printf("SDL Window created successfully.\n"); context_t context; SDL_GetWindowSize(window, &context.width, &context.height); fprintf( stderr, "Initial window size: width=%d, height=%d\n", context.width, context.height); #if !BX_PLATFORM_EMSCRIPTEN SDL_SysWMinfo wmi; SDL_VERSION(&wmi.version); if (!SDL_GetWindowWMInfo(window, &wmi)) { fprintf( stderr, "SDL_SysWMinfo could not be retrieved. SDL_Error: %s\n", SDL_GetError()); return 1; } bgfx::renderFrame(); // single threaded mode #endif // !BX_PLATFORM_EMSCRIPTEN bgfx::PlatformData pd{}; #if BX_PLATFORM_WINDOWS pd.nwh = wmi.info.win.window; #elif BX_PLATFORM_OSX pd.nwh = wmi.info.cocoa.window; #elif BX_PLATFORM_LINUX pd.ndt = wmi.info.x11.display; pd.nwh = (void*)(uintptr_t)wmi.info.x11.window; #elif BX_PLATFORM_EMSCRIPTEN pd.nwh = (void*)"#canvas"; #endif // BX_PLATFORM_WINDOWS ? BX_PLATFORM_OSX ? BX_PLATFORM_LINUX ? // BX_PLATFORM_EMSCRIPTEN bgfx::Init bgfx_init; bgfx_init.type = bgfx::RendererType::Count; // auto choose renderer bgfx_init.resolution.width = context.width; bgfx_init.resolution.height = context.height; bgfx_init.resolution.reset = BGFX_RESET_VSYNC; bgfx_init.platformData = pd; if (!bgfx::init(bgfx_init)) { fprintf(stderr, "Failed to initialize BGFX.\n"); return 1; } printf("BGFX Initialized successfully.\n"); // Установите отладочные флаги после успешной инициализации // bgfx::setDebug(BGFX_DEBUG_TEXT | BGFX_DEBUG_STATS | BGFX_DEBUG_WIREFRAME // | BGFX_DEBUG_PROFILER); bgfx::setViewClear( 0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x6495EDFF, 1.0f, 0); bgfx::setViewRect(0, 0, 0, context.width, context.height); // Начальная инициализация основных вьюпортов bgfx::reset(context.width, context.height, BGFX_RESET_VSYNC); bgfx::setViewRect(0, 0, 0, context.width, context.height); ImGui::CreateContext(); ImGui_Implbgfx_Init(255); #if BX_PLATFORM_WINDOWS ImGui_ImplSDL2_InitForD3D(window); #elif BX_PLATFORM_OSX ImGui_ImplSDL2_InitForMetal(window); #elif BX_PLATFORM_LINUX || BX_PLATFORM_EMSCRIPTEN ImGui_ImplSDL2_InitForOpenGL(window, nullptr); #endif // BX_PLATFORM_WINDOWS ? BX_PLATFORM_OSX ? BX_PLATFORM_LINUX ? // BX_PLATFORM_EMSCRIPTEN bgfx::VertexLayout pos_col_vert_layout; pos_col_vert_layout.begin() .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) .end(); bgfx::VertexBufferHandle vbh = bgfx::createVertexBuffer( bgfx::makeRef(cube_vertices, sizeof(cube_vertices)), pos_col_vert_layout); bgfx::IndexBufferHandle ibh = bgfx::createIndexBuffer( bgfx::makeRef(cube_tri_list, sizeof(cube_tri_list))); if (!bgfx::isValid(vbh) || !bgfx::isValid(ibh)) { fprintf(stderr, "Failed to create buffers.\n"); return 1; } printf("Buffers created successfully.\n"); const std::string shader_root = #if BX_PLATFORM_EMSCRIPTEN "shader/embuild/"; #else "shader/build/"; #endif // BX_PLATFORM_EMSCRIPTEN std::string vshader; if (!fileops::read_file(shader_root + "v_simple.bin", vshader)) { fprintf(stderr, "Could not find vertex shader (ensure shaders have been " "compiled).\n" "Run compile-shaders-<platform>.sh/bat\n"); return 1; } printf("Vertex shader loaded successfully.\n"); std::string fshader; if (!fileops::read_file(shader_root + "f_simple.bin", fshader)) { fprintf(stderr, "Could not find fragment shader (ensure shaders have " "been compiled).\n" "Run compile-shaders-<platform>.sh/bat\n"); return 1; } printf("Fragment shader loaded successfully.\n"); bgfx::ShaderHandle vsh = create_shader(vshader, "vshader"); bgfx::ShaderHandle fsh = create_shader(fshader, "fshader"); if (!bgfx::isValid(vsh) || !bgfx::isValid(fsh)) { fprintf(stderr, "Failed to create shaders.\n"); return 1; } printf("Shaders created successfully.\n"); bgfx::ProgramHandle program = bgfx::createProgram(vsh, fsh, true); if (!bgfx::isValid(program)) { fprintf(stderr, "Failed to create program.\n"); return 1; } printf("Program created successfully.\n"); context.program = program; context.window = window; context.vbh = vbh; context.ibh = ibh; #if BX_PLATFORM_EMSCRIPTEN emscripten_set_main_loop_arg(main_loop, &context, -1, 1); #else while (!context.quit) { main_loop(&context); } #endif // BX_PLATFORM_EMSCRIPTEN bgfx::destroy(vbh); bgfx::destroy(ibh); bgfx::destroy(program); ImGui_ImplSDL2_Shutdown(); ImGui_Implbgfx_Shutdown(); ImGui::DestroyContext(); bgfx::shutdown(); SDL_DestroyWindow(window); SDL_Quit(); return 0; }