我使用 emscripten 和 SDL 创建了一个 Wasm 动画。我现在正在尝试创建一个按钮,用户可以在其中开始和停止/暂停动画。我遇到的问题是每次迭代都会清除整个画布。在我看来,这里有 3 个选项:
- 在每一帧上重绘按钮。
- 仅清除动画在每次迭代中使用的画布部分。
- 对输入按钮使用 HTML 表单。
(1(似乎效率低下。(3(需要我开始在JS和Wasm之间进行互操作。到目前为止,我已经能够在不编写一行 JS 的情况下构建整个东西,并且更愿意保持这种方式。所以可能(2(是最好的。
我知道使用 JS 可以指定 clearRect 调用的维度。但是,我在 SDL API 中找不到此功能。
下面是mainLoop函数(每秒调用约60次((如果不清楚,这是用C写的。不是C++(。我的问题是,如何调整"SDL_RenderClear",使其仅清除画布的一半?(带有动画的一半。 即不要清除我想制作按钮的一半。
主.c
#include <stdio.h>
#include <SDL2/SDL.h>
#include <emscripten.h>
#include <stdlib.h>
#include <stdbool.h>
<....>
/**
* The loop handler, will be called repeatedly
*/
void mainLoop(void *arg) {
struct Context *ctx = arg;
printf("iteration: %dn", ctx->iteration);
SDL_SetRenderDrawColor(ctx->renderer, 255, 0, 100, 255);
SDL_RenderClear(ctx->renderer);
bool running = true;
if (running) {
for (int j=1; j<8; j++) {
for (int i=1; i<130; i++) {
// drawRect is another app function that calls the SDL to draw a rectangles.
drawRectangle(ctx, i, j);
}
}
}
SDL_RenderPresent(ctx->renderer);
ctx->iteration++;
}
<....>
你可以用SDL_RenderFillRect画你不想要的部分。但是,除非你做很多诡计,否则它不是很有帮助。
正式原因 - https://wiki.libsdl.org/SDL_RenderPresent 说"每次出现后,后台缓冲应被视为无效;不要假设帧之间将存在以前的内容。
在许多情况下,缓冲区将(部分(失效,例如将窗口移出屏幕边界。我不知道webasm,您可能需要检查webgl文档,如果承诺了有关缓冲区内容的任何内容。
即使您可以依靠要保留的内容,但例如,您具有双缓冲设置。你已呈现到第一个缓冲区,执行缓冲区交换 - 现在你有第二个缓冲区,其内容尚未初始化。第二次交换后,它可能或多或少相似,但任何变化都将滞后于 1 帧。
一些 3d 软件(例如搅拌机(按照您的描述做了,但即使在那里它也不是 100% 稳定的,通常有一个选项可以禁用该行为。执行完全重绘比您想象的要便宜得多,如果它变得太昂贵 - 您始终可以将屏幕的一部分渲染为渲染纹理并将其用作单个静态图像,并在必要时进行更新。