我繪製它從服務器接收圖形信息的呈現客戶端上工作。服務器以服務器上可變定義的幀速率發送包含不同純色的非重疊矩形的數據包。我現在配置了它,以便服務器傳輸的屏幕大小與客戶端繪製的窗口大小不同,因此可以進行縮放。我需要客戶端儘快繪製這些矩形,以避免落後於服務器的流。
目前,我正在使用SDL 2.0。我使用SDL 2 Migration Guide中描述的流紋理技術將矩形繪製到SDL_Surface
上。當顯示幀的時間到了時,我調用SDL_UpdateTexture()
覆蓋SDL_Texture
的像素數據,然後使用SDL_RenderCopyEx()
將紋理複製到渲染器。我需要這個函數而不是SDL_RenderCopy()
,所以我可以指定SDL_FLIP_VERTICAL
來說明傳遞的座標是位圖樣式的事實。
問題
我目前的做法並未使矩形的速度不夠快。爲了讓客戶端能夠跟上服務器,我目前必須將服務器的上傳速率從30+ FPS降低到15-FPS。即使這樣,我也必須使套接字的緩衝區大到危險的程度,最後我纔看到客戶端的渲染緩慢落後,最終導致數據包丟失。
什麼是使SDL渲染這些矩形的最快方法?如果我目前正在使用最快的方法,那麼其他人會推薦哪些其他API來創建可跟上的客戶端?
我已經包含了我的源代碼的簡化版本,所以其他人可以查找改進/錯誤。
技術細節
我使用C++ 11,MINGW32和SDL2用Eclipse開普勒CDT和GCC 4.8.2上窗口7 64位。
剝離代碼
int main(int argc, char** args) {
// omitted initialization code
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow(
"RTSC",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
windowWidth,
windowHeight,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface* surface = SDL_CreateRGBSurface(
0,
sourceWidth,
sourceHeight,
24,
0xFF << 16,
0xFF << 8,
0xFF,
0
);
SDL_FillRect(surface, nullptr, 0);
SDL_Texture* texture = SDL_CreateTexture(
renderer,
surface->format->format,
SDL_TEXTUREACCESS_STREAMING,
sourceWidth,
sourceHeight
);
bool running {true};
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
case SDL_WINDOWEVENT:
switch (event.windowevent.event) {
case SDL_WINDOWEVENT_CLOSE:
running = false;
break;
default:
break;
}
break;
default:
break;
}
}
// omitted packet reception and interpretation code
for (uint32_t i {0}; i < receivedRegions; ++i) {
Region& region = regions[i];
SDL_Rect rect {
(int) region.x,
(int) region.y,
(int) region.width,
(int) region.height
};
uint32_t color =
(region.red << 16) +
(region.green << 8) +
region.blue;
SDL_FillRect(surface, &rect, color);
}
// omitted logic for determining whether to present the frame
SDL_RenderClear(renderer);
SDL_UpdateTexture(texture, nullptr, surface->pixels, surface->pitch);
SDL_RenderCopyEx(
renderer,
texture,
nullptr,
nullptr,
0,
nullptr,
SDL_FLIP_VERTICAL
);
SDL_RenderPresent(renderer);
SDL_FillRect(surface, nullptr, 0);
}
// omitted clean-up and return code
}
您可以使用SDL2_Gfx進行矩形渲染,使用該庫可以直接在SDL_Texture上繪製它們,不需要首先創建SDL_Surface。但是您需要自己編譯它,否則我的github配置文件中已經編譯了一個版本。 SDL2-Gfx網站:http://cms.ferzkopp.net/index.php/software/13-sdl-gfx – jordsti
你爲什麼使用紋理來存儲這些矩形,而不是直接在屏幕上繪製它們?您可以使用SDL_RenderFillRect()直接渲染它們。 – TalesM
@TalesM我曾經嘗試了一段時間,並假設,也許不正確,使用紋理將使處理我接收到的倒y座標更快。我現在再次嘗試了它,並使用'SDL_RenderFillRect()'進行了比較,以便複製到紋理,然後使用'SDL_RenderCopyEx()'將其翻轉。這兩種方法具有相同的幀率和失速問題。不過謝謝你的建議。 – sadakatsu