Wasm с emscripten и SDL - Как очистить только часть рендерера - PullRequest
0 голосов
/ 17 февраля 2020

Я создал анимацию Wasm с использованием emscripten и SDL. Я сейчас пытаюсь создать кнопку, где пользователь может запустить и остановить / приостановить анимацию. У меня проблема в том, что весь холст очищается на каждой итерации. На мой взгляд, здесь есть 3 варианта:

  1. Перерисовать кнопку на каждом кадре.
  2. Очистить только ту часть холста, которую анимация использует на каждой итерации.
  3. Используйте форму HTML для кнопок ввода.

(1) кажется неэффективным. (3) потребовал бы, чтобы я начал взаимодействовать между JS и Wasm. До сих пор я был в состоянии построить все это без написания ни одной строки JS, и предпочел бы сохранить это так. Поэтому, вероятно, (2) лучше.

Я знаю, что с JS можно указать размеры вызова clearRect. Однако я не могу найти эту функцию в SDL API.

Ниже приведена функция mainL oop (которая вызывается примерно 60 раз в секунду) (записывается в C, если неясно. Не C ++). У меня вопрос, как я могу адаптировать SDL_RenderClear, чтобы он очищал только половину холста? (Половина с анимацией. Т.е. не очищайте половину, где я хочу сделать кнопки.

main. 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: %d\n", 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++;
}

<....>

1 Ответ

2 голосов
/ 18 февраля 2020

Вы можете просто закрасить ненужные детали с помощью SDL_RenderFillRect . Однако, если вы не проделали много хитростей, это не очень полезно.

Формальная причина - https://wiki.libsdl.org/SDL_RenderPresent говорит: «После каждого подарка буфер должен считаться недействительным; не предполагайте что предыдущее содержимое будет существовать между кадрами. "

Есть много случаев, когда ваш буфер будет (частично) признан недействительным, например, перемещение окна за пределы экрана. Я не знаю насчет webasm, вам, вероятно, нужно проверить документацию webgl, если обещано что-либо о содержимом буфера.

Даже если вы можете полагаться на сохраняемое содержимое, но, например, у вас есть установка с двойной буферизацией. Вы выполнили рендеринг в первый буфер, произвели замену буфера - теперь у вас есть второй буфер, содержимое которого еще не инициализировано. После второго обмена это может быть более или менее похоже, но любое изменение будет отставать от 1 кадра.

Некоторые 3D-программы (например, Blender) сделали то, что вы описали, но даже там они не были стабильны на 100% и обычно была возможность отключить это поведение. Выполнение полной перерисовки намного дешевле, чем вы думаете, и если это становится слишком дорогостоящим, вы всегда можете визуализировать часть экрана в текстуру рендеринга и использовать ее в качестве отдельного изображения c, обновляя его при необходимости.

...