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
相关产品推荐
相关产品推荐

