提问人:Parsa Eslami 提问时间:10/26/2023 更新时间:10/26/2023 访问量:47
为什么使用 SDL2 时会出现双图像?
Why is there a double Image when using SDL2?
问:
我有一个 c++ 的 Mandelbrot 集渲染代码,我正在使用 SDL2 来显示图像。当我想让我的程序具有交互性时,我遇到了一个问题。通过按 W,我的代码应该清除上一个图像并显示一个带有新参数的新图像,但无论我做什么,之前的渲染都不会清除。顺便说一句,我注意到每次按 W 时,我的内存使用量都会更高。我应该如何解决这个问题?
#include <complex>
#include <iostream>
#include <SDL.h>
#include <chrono>
#include <omp.h>
using namespace std;
int main(int argc, char** argv) {
const int resolution= 2000;
const int rows = resolution;
const int cols = resolution;
complex<long double> position;
int dots[rows][cols];
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
dots[i][j] = 0;
}
}
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "SDL initialization failed: " << SDL_GetError() << std::endl;
return 1;
}
const int screenWidth = cols * 1; // Adjust the window size as needed
const int screenHeight = rows * 1;
SDL_Window* window = SDL_CreateWindow("Mandelbrot set Visualization", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screenWidth, screenHeight, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Rect rect;
long double startx = -2;
long double endx = 2;
long double starty = 2;
long double endy = -2;
long double stepx = (endx - startx) / (cols - 1);
long double stepy = (endy - starty) / (rows - 1);
rect.w = screenWidth / cols;
rect.h = screenHeight / rows;
int numThreads = 16;
omp_set_num_threads(numThreads);
#pragma omp parallel
{
int threadID = omp_get_thread_num(); // Get the thread ID
#pragma omp for
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
long double real = startx + j * stepx;
long double imag = starty + i * stepy;
position = complex<long double>(real, imag);
complex<long double> iterate(0, 0);
int color = 0;
for (int n = 0; n < 256; n++) {
iterate = iterate * iterate + position;
color++;
if (abs(iterate) > 2) {
dots[i][j] = color;
break;
}
}
}
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
SDL_SetRenderDrawColor(renderer, 0, dots[i][j], dots[i][j], 255);
rect.x = j * (screenWidth / cols);
rect.y = i * (screenHeight / rows);
SDL_RenderFillRect(renderer, &rect);
}
}
SDL_RenderPresent(renderer);
// Main game loop
bool quit = false;
SDL_Event event;
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
else if (event.type == SDL_KEYDOWN) {
if (event.key.keysym.sym == SDLK_w) {
// Zoom or change parameters, as needed
cout << "loop start";
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
long double decreaseAmountx = (abs(endx) + abs(startx)) / 20;
long double decreaseAmounty = (abs(endy) + abs(starty)) / 20;
endx -= decreaseAmountx;
startx += decreaseAmountx;
endy += decreaseAmounty;
starty -= decreaseAmounty;
stepx = (endx - startx) / (cols - 1);
stepy = (endy - starty) / (rows - 1);
// Render the Mandelbrot set with new parameters
#pragma omp parallel
{
int threadID = omp_get_thread_num(); // Get the thread ID
#pragma omp for
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
long double real = startx + j * stepx;
long double imag = starty + i * stepy;
position = complex<long double>(real, imag);
complex<long double> iterate(0, 0);
int color = 0;
for (int n = 0; n < 256; n++) {
iterate = iterate * iterate + position;
color++;
if (abs(iterate) > 2) {
dots[i][j] = color;
break;
}
}
}
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
SDL_SetRenderDrawColor(renderer, 0, dots[i][j], dots[i][j], 255);
rect.x = j * (screenWidth / cols);
rect.y = i * (screenHeight / rows);
SDL_RenderFillRect(renderer, &rect);
}
}
cout << "Present";
SDL_RenderPresent(renderer);
}
else if (event.key.keysym.sym == SDLK_r) {
// Trigger an SDL_QUIT event to exit the application
SDL_Event quitEvent;
quitEvent.type = SDL_QUIT;
SDL_PushEvent(&quitEvent);
}
}
}
}
// Cleanup and quit
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
答:
0赞
Ted Lyngmo
10/26/2023
#1
问题出在现有数组中分配新值的循环中。dots
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
long double real = startx + j * stepx;
long double imag = starty + i * stepy;
position = complex<long double>(real, imag);
complex<long double> iterate(0, 0);
int color = 0;
for (int n = 0; n < 256; n++) {
iterate = iterate * iterate + position;
color++;
if (abs(iterate) > 2) {
dots[i][j] = color; // <- here
break;
}
}
}
}
旧值仍在数组中,因此您将获得叠加效果。
首先,我建议不要在堆栈上分配巨大的数组,而是在堆上分配。并非所有环境都允许您在堆栈上分配这么多。只
#include <algorithm>
#include <vector>
并替换为int dots[rows][cols];
std::vector<int[cols]> dots(rows);
然后,为了验证我的理论,我在上面的重新缩放循环之前清除了:dots
std::for_each(dots.begin(), dots.end(),
[](auto& inner) {
std::fill(std::begin(inner), std::end(inner), 0);
});
或者使用执行策略来更快地清除它:
#include <execution>
//...
std::for_each(std::execution::par, dots.begin(), dots.end(),
[](auto& inner) {
std::fill(std::begin(inner), std::end(inner), 0);
});
通过这些更改,它可以正确地重新绘制。您还可以使用并行执行策略(或 omp)将清除与绘图结合起来。使用标准执行策略时,它可能如下所示:
std::for_each(std::execution::par_unseq, dots.begin(), dots.end(),
[&](auto& inner) {
// clear this row first:
std::fill(std::begin(inner), std::end(inner), 0);
auto i = std::distance(dots.data(), &inner);
long double imag = starty + i * stepy;
for(int j = 0; j < cols; j++) {
long double real = startx + j * stepx;
position = complex<long double>(real, imag);
complex<long double> iterate(0, 0);
int color = 0;
for(int n = 0; n < 256; n++) {
iterate = iterate * iterate + position;
color++;
if(abs(iterate) > 2) {
inner[j] = color;
break;
}
}
}
});
评论
int dots[rows][cols];
auto dots = std::make_unique<int[][cols]>(rows);