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

Raylib中DrawPixel调用过多导致大量像素无法显示的问题求助

DrawPixel调用次数超限导致像素不显示的解决方案

问题原因

当DrawPixel调用次数达到60000-80000次时出现部分像素不显示,核心原因是Raylib默认的GPU批处理顶点缓冲区存在上限——单个批次最多能处理8192个顶点(对应4096个四边形,而DrawPixel本质是绘制1x1的四边形),超出这个数量的绘制请求会被丢弃,无法正常提交到GPU。

另外你提供的代码存在一个明显逻辑错误:ClearBackground放在了绘制像素之后,这会导致所有绘制的像素被直接清空,实际运行时应该看不到任何粒子(除非FPS显示在清屏前),建议先修正这个顺序。

解决方法

要解决这个问题,核心思路是减少GPU绘制调用次数,避免逐个提交DrawPixel请求,以下是两种可行方案:

方案1:使用Image作为像素缓冲区(推荐)

先在CPU端将所有像素绘制到Image对象中,最后仅通过一次纹理绘制操作提交到GPU,完全规避批处理限制,同时性能远高于逐个调用DrawPixel。

修改后的核心代码:

const int particleCount = 60000;
// 假设xPositions、yPositions为已初始化的坐标数组
Image canvas = GenImageColor(WIDTH, HEIGHT, Color{41, 41, 41, 255});
Texture2D canvasTexture = LoadTextureFromImage(canvas);

InitWindow(WIDTH, HEIGHT, "Particles");
SetTargetFPS(80);

while (!WindowShouldClose())
{
    BeginDrawing();
        // 重置画布背景
        ImageClearBackground(&canvas, Color{41, 41, 41, 255});
        
        // 批量绘制像素到CPU端Image
        for (int i = 0; i < particleCount; i++) {
            ImageDrawPixel(&canvas, (int)xPositions[i], (int)yPositions[i], {255, 255, 255, 180});
        }
        
        // 更新纹理并渲染到屏幕
        UpdateTexture(canvasTexture, canvas.data);
        DrawTexture(canvasTexture, 0, 0, WHITE);
        
        DrawFPS(5, 5);
    EndDrawing();
}

// 资源清理
UnloadTexture(canvasTexture);
UnloadImage(canvas);
CloseWindow();

方案2:使用自定义顶点数组

通过构建包含所有像素顶点数据的数组,一次性提交给GPU绘制,同样能合并成单个绘制调用:

// 省略初始化代码
Vertex* vertices = malloc(particleCount * 4 * sizeof(Vertex)); // 每个像素对应4个顶点
Color particleColor = {255, 255, 255, 180};

for (int i = 0; i < particleCount; i++) {
    int x = (int)xPositions[i];
    int y = (int)yPositions[i];
    // 构建像素的四个顶点
    vertices[i*4] = (Vertex){(float)x, (float)y, 0, 0, 0, particleColor};
    vertices[i*4+1] = (Vertex){(float)x+1, (float)y, 0, 0, 0, particleColor};
    vertices[i*4+2] = (Vertex){(float)x+1, (float)y+1, 0, 0, 0, particleColor};
    vertices[i*4+3] = (Vertex){(float)x, (float)y+1, 0, 0, 0, particleColor};
}

while (!WindowShouldClose())
{
    BeginDrawing();
        ClearBackground(Color{41, 41, 41, 255});
        // 一次性绘制所有顶点
        DrawVertices(vertices, particleCount*4, TRIANGLES, NULL, 0);
        DrawFPS(5, 5);
    EndDrawing();
}

free(vertices);

注意事项

  • 无论哪种方案,都要确保ClearBackground放在BeginDrawing后的第一行,避免绘制内容被清空。
  • 逐个调用DrawPixel不仅会触发批处理限制,还会导致严重的性能下降,建议尽量采用批量绘制的方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 08:47:47