C++ precisão timer para aplicação gráfica

Prezados,

Estou com uma dúvida. Estou criando uma aplicação que, com precisão, precisa fazer um retângulo (ou outra imagem qualquer) cintilar em uma dada frequência (por exemplo, 12 Hz, 20 Hz, etc). Eu consegui fazer isso usando o Unity3d, mas agora estou querendo implementar em OpenGL.

Pretendo usar C++, OpenGL e SDL. Mas me veio uma dúvida. Se eu usar o Visual C++, a aplicação vai rodar em uma virtual machine, correto? Se sim, isso vai me fazer perder precisão (lembrando que preciso cravar a frequência). Neste caso, deveria usar outro compilador, como o g++?

Desde já agradeço qualquer tipo de ajuda.

Prezados,

Para deixar o tópico mais completo, deixo o código que fiz abaixo:

void setup() { SDL_Init(SDL_INIT_VIDEO); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	window = SDL_CreateWindow(
		"Estimulos Visuais",
		SDL_WINDOWPOS_CENTERED,
		SDL_WINDOWPOS_CENTERED,
		1920,
		1080,
		SDL_WINDOW_FULLSCREEN
		);

	surface = SDL_GetWindowSurface(window);

	if (window == NULL) {
		printf("Could not create window: %s\n", SDL_GetError());
	}
}

void draw()
{
	if (troca == 0)
	{
		SDL_FillRect(surface, &rect, SDL_MapRGB(surface->format, 255, 255, 255));
		SDL_UpdateWindowSurface(window);
		troca = 1;
	}
	else
	{
		SDL_FillRect(surface, &rect, SDL_MapRGB(surface->format, 0, 0, 0));
		SDL_UpdateWindowSurface(window);
		troca = 0;
	}
}

void processEvents()
{
	SDL_Event event;

	while (SDL_PollEvent(&event) != 0)
	{
		switch (event.type)
		{
		case SDL_QUIT:
			exit(0);
			break;
		}
	}
}

int main(int argc, char* argv[])
{
	try
	{
		setup();

		while (true)
		{
			processEvents();
			draw();
			SDL_Delay(1000 / 30);
		}

		SDL_DestroyWindow(window);
		SDL_Quit();
	}
	catch (std::exception &e)
	{
		exit(1);
	}
}

Fiz baseado nos artigos do pontov e também da documentação do OpenGL-SDL.

A frequência que o quadrado cintila na tela é dada por:

SDL_Delay(1000/30);

Alguma sugestão para aumentar ainda mais a precisão da frequência?

Eu li em algum lugar que usar SDL_Delay para controlar a frequencia da atualização da tela não é uma boa pratica, então acredito que o mesmo se aplica à frequencia com o que seu quadrado pisca.

Veja se encontra outras tecnicas para alcançar seu resultado. Para ajudar em sua busca, segue os links que me ajudaram bastante e que podem lhe dar uma luz:

http://gafferongames.com/game-physics/fix-your-timestep/
http://gameprogrammingpatterns.com/game-loop.html


http://www.koonsolo.com/news/dewitters-gameloop/

Outra coisa é não usar a surface para desenhar e sim o renderer, parece que a performance é melhor pois ele é acelerado por hardware, mas pesquise melhor sobre isso.

Espero ter ajudado de alguma forma.

Oi wldomiciano,

Obrigado por responder.

Na verdade, eu não queria travar o FPS, eu queria travar a quantidade de vezes que o quadrado pisca na tela.

Eu estou desenvolvendo um aplicativo para controlar cadeira de rodas por pensamento. Se eu conseguir fazer um quadrado piscar na tela, por exemplo, 12 Hz por segundo, precisamente, então eu consigo selecionar o sinal cerebral e acionar um comando. No entanto, eu estou com dificuldade de conseguir esta precisão usando OpenGL. Eu consegui este resultado com outras ferramentas, mas como quero simplificar ao máximo a aplicação, até para poder embarcar a aplicação na cadeira de rodas, estou tentando solucionar usando opengl.

Eu até tentei pegar o tempo que o programa leva para o processamento e desenho a cada iteração e subtrair no delay, mas não consegui um resultado satisfatório. De qualquer forma, vou trocar a forma de renderizar, de acordo com a sua sugestão, com aceleração de hardware, e ver o que consigo.

Caso tenha mais alguma sugestão, peço que compartilhe.

Abraços.

1 curtida

Prezados,

Usei o Renderer, mas tive um comportamento estranho.

Segue o código:

void setup() { SDL_Init(SDL_INIT_VIDEO); //SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); //SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 0); //SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 0); //SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 0); //SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 0);
	window = SDL_CreateWindow(
		"Estimulos Visuais",
		SDL_WINDOWPOS_CENTERED,
		SDL_WINDOWPOS_CENTERED,
		1920,
		1080,
		SDL_WINDOW_FULLSCREEN
		);
	//
	renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
	//

	//surface = SDL_GetWindowSurface(window);

	if (window == NULL) {
		printf("Could not create window: %s\n", SDL_GetError());
	}
}

void draw()
{
	if (troca == 0)
	{
		SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
		//SDL_FillRect(surface, &rect, SDL_MapRGB(surface->format, 255, 255, 255));
		troca = 1;
	}
	else
	{
		SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
		//SDL_FillRect(surface, &rect, SDL_MapRGB(surface->format, 0, 0, 0));
		troca = 0;
	}

	SDL_RenderFillRect(renderer, &rect);
	SDL_RenderPresent(renderer);

}

void processEvents()
{
	SDL_Event event;

	while (SDL_PollEvent(&event) != 0)
	{
		switch (event.type)
		{
		case SDL_QUIT:
			exit(0);
			break;
		}
	}
}

int main(int argc, char* argv[])
{
	try
	{
		setup();

		while (true)
		{
			processEvents();
			draw();
			//SDL_UpdateWindowSurface(window);
			//Sleep(1000/30);
			SDL_Delay(1000 / 10);
		}

		SDL_DestroyWindow(window);
		SDL_Quit();
	}
	catch (std::exception &e)
	{
		exit(1);
	}
}

Acontece que quando eu rodo, as vezes aparecem umas faixas brancas horizontais na tela, como uma televisão antiga, mas somente na região do quadrado, alguém sabe o que pode estar acontecendo?

Testei o novo código e não vi as faixas brancas. To usando o CLion e compilando com o g++, só pra constar ^^

Se eu tiver mais alguma idéia compartilharei sim.

Que engraçado.

Eu testei no meu notebook que tem uma nvidia e funcionou sem a faixa também. Estranho.

No meu desktop eu tenho uma placa de vídeo AMD. Será que pode ser isso?

Vou fazer uma aquisição com eletroencefalografia usando esta versão e testar.

Tendo respostas eu poto aqui. Pode ser útil para outros.

Abraços.

1 curtida