You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法通过多线程启动两个RayLib窗口的原因及解决方法

问题描述

我用RayLib开发时写了创建窗口的代码,单独运行或单线程启动(比如std::thread game1 (&start_window, "test");)能正常创建窗口,但多线程启动两个窗口(std::thread game1 (&start_window, "test"); std::thread game2 (&start_window, "test 2");)时,完全没有窗口弹出。想知道原因是什么?能不能用多线程启动两个RayLib窗口?如果可以,该怎么实现?

相关代码

void start_window(std::string windowName){

    InitWindow(800, 450, windowName.c_str());
    SetTargetFPS(60);
    rlFPCamera cam;
    cam.Setup(45,Vector3{ 1, 0, 0 });
    cam.SetCameraPosition((Vector3){1.0f, 500.0f, 1.0f});
    cam.MoveSpeed.z = 100;
    cam.MoveSpeed.x = 100;
    cam.FarPlane = 5000;


    Material matDefault = LoadMaterialDefault();
    Material matRed = LoadMaterialDefault();
    Material matGreen = LoadMaterialDefault();
    matDefault.maps[MATERIAL_MAP_DIFFUSE].color = BLUE;
    matRed.maps[MATERIAL_MAP_DIFFUSE].color = RED;
    matGreen.maps[MATERIAL_MAP_DIFFUSE].color = GREEN;

    Model cube = LoadModelFromMesh(GenMeshCube(5,5,5));
    int width = 3072;
    int height = 3072;

    // Dynamic memory allocation to store pixels data (Color type)
    Color *pixels = (Color *)malloc(width*height*sizeof(Color));

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            if (((x/16+y/16)/1)%2 == 0) pixels[y*width + x] = WHITE;
            else pixels[y*width + x] = BLUE;
        }
    }
    Image checkedIm = {
            .data = pixels,             // We can assign pixels directly to data
            .width = width,
            .height = height,
            .mipmaps = 1,
            .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
    };

    Texture2D checked = LoadTextureFromImage(checkedIm);

    Model terrain = LoadModel("Resources/Terrains/TestingGround.obj");
    terrain.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = checked;
    Vector3 cubePosition = {2.50f, 3.0f, 2.50f};

    UnloadImage(checkedIm);
    while (!WindowShouldClose())    // Detect window close button or ESC key
    {
        cam.Update();

        float offsetThisFrame = 100.0f*GetFrameTime();


        BeginDrawing();
        ClearBackground(SKYBLUE);
        cam.BeginMode3D();
        DrawGrid(1000, 1.0f);
        if (IsKeyDown(KEY_SPACE))
        {
            cam.SetCameraPosition((Vector3){cam.GetCameraPosition().x, cam.GetCameraPosition().y+offsetThisFrame, cam.GetCameraPosition().z});
        }
        else if (IsKeyDown(KEY_Z))
        {
            cam.SetCameraPosition((Vector3){cam.GetCameraPosition().x, cam.GetCameraPosition().y-offsetThisFrame, cam.GetCameraPosition().z});
        }
        if (IsKeyPressed(KEY_SPACE))
        {
            cubePosition = {cubePosition.x, cubePosition.y + 5, cubePosition.z};
        }
        VibraniumEngine::DrawModel(cube, (Vector3){50.30f, 12.32f, 40.7f}, 1, RED);
        VibraniumEngine::DrawModel(cube, (Vector3){68.8f, 8.8f, 74.7f}, 1, RED);
        VibraniumEngine::DrawModel(cube, (Vector3){15.52f, 11.65f, 84.51f}, 1, RED);
        VibraniumEngine::DrawModel(cube, cubePosition, 1, BLUE);

        DrawModelEx(terrain, (Vector3){0.0f, 0.0f, 0.0f},(Vector3){0.0f, 0.0f, 0.0f}, 0.0f,(Vector3){1.0f, 1.0f, 1.0f}, WHITE);

        EndMode3D();

        DrawFPS( 10, 10);
        DrawText("Press H to hide the Map Window.", 10, 32, 12, GREEN);
        DrawText(TextFormat("Camera Pos: X: %3.2fY:  %3.2f Z: %3.2f",
                            cam.GetCameraPosition().x * -1,
                            cam.GetCameraPosition().y,
                            cam.GetCameraPosition().z), 10, 52, 12, BLACK);
        EndDrawing();
    }
    UnloadModel(cube);
    CloseWindow();
}
解决方案

问题原因

RayLib默认单窗口模式依赖全局状态(比如OpenGL上下文、输入处理逻辑等),多线程直接调用InitWindow会触发资源竞争和上下文冲突,系统无法正确初始化多个窗口的渲染环境,最终导致窗口无法显示。

实现多窗口的正确方式

RayLib支持多窗口,但需要启用多窗口模式,且每个窗口的生命周期必须完全隔离在各自线程中,具体步骤如下:

  1. 编译时启用多窗口支持
    编译RayLib时必须定义RAYLIB_MULTI_WINDOW宏:

    • 自行编译库:在CMake中添加-DRAYLIB_MULTI_WINDOW=ON,或在编译选项中加入-DRAYLIB_MULTI_WINDOW
    • 使用预编译库:选择带多窗口支持的版本
  2. 线程逻辑完全隔离
    每个线程必须独立完成窗口初始化、渲染循环、资源销毁流程,绝对不能跨线程调用RayLib的窗口/渲染相关函数。你的现有代码结构已经符合单线程隔离要求,只需确保宏定义正确。

  3. 主线程等待子线程完成
    启动线程后必须调用join(),避免主线程提前退出导致子线程资源未正确释放,示例代码:

    std::thread game1(&start_window, "test");
    std::thread game2(&start_window, "test 2");
    game1.join();
    game2.join();
    
  4. 适配平台限制
    部分平台(如Windows)对多线程创建窗口有额外限制,RayLib的WindowShouldClose()、BeginDrawing()/EndDrawing()已经内置处理了消息循环,只需保证线程不被阻塞即可。

验证流程

确认以下几点后即可正常启动两个独立窗口:

  • 编译时已开启RAYLIB_MULTI_WINDOW宏
  • 每个线程独立执行InitWindow、渲染循环、CloseWindow
  • 主线程等待所有子线程执行完毕

内容的提问来源于stack exchange,提问作者Venelin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:27:45