【问题标题】:Drawing polygons using multithreading in C++在 C++ 中使用多线程绘制多边形
【发布时间】:2015-02-05 07:07:07
【问题描述】:

我正在使用 C++ 在 WM_PAINT 事件中绘制多边形 (Polygon(dc, points, 3))。我有大量的多边形,所以我正在尝试实现多线程。我正在运行 VS2013,所以我包含了线程。我创建了一个要在线程上运行的函数:

void anyFunс2(HDC dc, int index)
{
    POINT points[3];

    for (unsigned i = index; i < model->vertexFaces.size(); i += fs)
    {
        // Here we convert our points to Clip and Windowed Coordinates
        // and only then fetch the results
        if (Algorithms::FetchPolygons(&model->finalizedVertices[0], model->vertexFaces[i], points))
        {
            Polygon(dc, points, 3);
        }
    }
}

例如,我有三个线程。我将代码设计为每个线程呈现每个第三个元素的方式。例如第一个线程渲染 0,3,6,9 个多边形,第二个线程渲染 1,4,7,10,最后一个线程渲染 2,5,8,11 个多边形。

这是我的 WM_PAINT 事件:

case WM_PAINT:
{
    // Get dc here
    hdc = GetDC(hWnd);

    // Create a backbuffer here 
    bdc = CreateCompatibleDC(hdc);

    // Get the screen dimensions
    RECT client;
    GetClientRect(hWnd, &client);

    // Create bitmap
    HBITMAP backBuffer = CreateCompatibleBitmap(hdc, client.right - client.left, client.bottom - client.top);

    // Release it, because we no longer need it
    hdc = NULL;
    ReleaseDC(hWnd, hdc);           

    // Select the back dc as a current one and specify the screen dimensions
    HPEN hPen = CreatePen(PS_SOLID, 1, RGB(0, 25, 205));
    HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 55));

    SelectObject(bdc, hPen);
    SelectObject(bdc, hBrush);
    SelectObject(bdc, backBuffer);

    Rectangle(bdc, client.left, client.top, client.right, client.bottom);

    // Call some threads to draw polygons on our BDC
    for (unsigned i = 0; i < func_threads.size(); i++)
    {
        func_threads.at(i) = thread(anyFunс2, bdc, i);
    }

    // Wait until all threads finish their job
    for (unsigned i = 0; i < func_threads.size(); i++)
    {
        if (func_threads[i].joinable()) func_threads[i].join();
    }

    // Swap buffers     
    hdc = BeginPaint(hWnd, &ps);
    BitBlt(hdc, client.left, client.top, client.right, client.bottom, bdc, 0, 0, SRCCOPY);
    EndPaint(hWnd, &ps);

    // Delete all created objects from memory
    DeleteObject(backBuffer);
    DeleteObject(hBrush);
    DeleteObject(hPen);
    DeleteDC(bdc);
    break;
}

如您所见,我在循环中运行这些线程。然后我有另一个循环,每个线程的 Join() 方法都位于其中。这些线程将多边形绘制到同一个 HDC(我假设)。在主线程完成等待所有这些线程后,它会将后台缓冲区中的所有内容复制到主线程。但是问题是对象没有完全绘制。我的意思是不是所有的多边形都被绘制出来。附上图片链接here。请帮帮我,为什么会这样?!

【问题讨论】:

    标签: c++ multithreading visual-studio-2013 polygon wm-paint


    【解决方案1】:

    简短的回答是,GDI 根本不支持同时从多个线程绘制到同一个 DC。

    这让您有几个选择。最直接的方法是使用PolyPolygon 在一次调用中绘制所有多边形(或至少大量多边形)。这似乎与您的情况特别相关-从外观上看,您正在绘制很多三角形,因此花费的很多时间可能只是调用 Polygon 函数的开销,而不是真正的时间 @987654323 @ 执行。

    另一种可能性是为每个要绘制的线程创建一个单独的后台缓冲区,然后使用 BitBlit 将它们与(例如)一个 OR 函数组合在一起,这样您就可以获得与原始绘图相同的整体效果。

    支持绘制大量多边形的第三种(可能也是最好的)方法是从使用 GDI 切换到使用 DirectX 或 OpenGL 之类的东西,这些东西从一开始就完全支持这一点。

    【讨论】:

    • 非常感谢您的完整回答!我在 GDI 中绘图是因为我有兴趣从头开始创建所有内容,以非常详细地了解它们是如何工作的。我对第二种方法非常满意。我有点困惑多边形是如何工作的。但我会发现的。我假设它需要一个多边形数组。所以我可以在单独的线程中计算它们并绘制一次。可能需要时间将它们存储在数组中并一一绘制。我认为结合 hdcs 会更快一些。不过我会尝试两种方式。再次感谢您!
    【解决方案2】:

    您可以使用 CreateDIBsection() 绘制具有多个线程的形状。 只需让每个线程直接将像素绘制到 DIB。然后当所有线程都完成后,您可以将DIB bitBlt到屏幕上。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-13
      • 2011-04-28
      • 1970-01-01
      • 2012-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多