Video output glitch

Hi, I’m developing a game, everything is working fine but there is a small glitch with the video output. As you can see in the youtube link, there are some laggy moments when the draw get stuck for few milliseconds. However, the FPS are allways at 60. You can see the problem specifically at 0:11 and 0:14 on youtube.
What could it be?

Here’s the code:

Thank you!

#pragma once

#include "ofMain.h"
#define REPE (float)10
#define ROT (float)2.5

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();

		void keyPressed(int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y );
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);

		//UI
		ofImage UImain;
		ofSoundPlayer mainSong;
		ofSoundPlayer music;
		ofSoundPlayer UIselect;
		ofTrueTypeFont text;
		float frontColor = 0;
		float volume = 0;
		int counter;

		//scene1
		ofFbo fbo1;
		float displace = 0;
		float scroll = 0;
		ofPixels pix;
		ofPixels pixAux;
		ofTexture tex;

		//pause
		ofFbo fboPause;
		bool flag = false;

		//player
		ofVec2f center;
		ofVec2f ori;
		ofVec2f des;
		ofVec2f pos[(int)REPE];
		ofColor color;
		ofColor paleta[2] = {0, 230};
		int resolution = 3;
		float rad;
		float rot = 0;

		float adyasente;
		float opuesto;
		float hipotenusa;
		float angulo;
		float pendiente;
		float dirX, dirY;
		
		float speed = 0;

		int scene;
};
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){

	//window
	ofSetFrameRate(60);
	ofSetWindowShape(854, 480);
	ofBackground(255);
	ofSetColor(0);
	ofSetBackgroundAuto(false);
	center = ofVec2f(ofGetWindowWidth() / 2, ofGetWindowHeight() / 2);

	//player
	des = ori = pos[0] = center;
	ofSetCircleResolution(resolution);
	rad = 50;

	//UI
	text.load("font.ttf",15);
	UImain.load("main720.png");
	scene = 0;
	UIselect.load("UIselect.wav");
	mainSong.load("main.wav");
	music.load("song1.mp3");
	mainSong.setLoop(true);
	mainSong.setVolume(0);
	mainSong.play();
	music.setLoop(true);

	fboPause.allocate(ofGetWidth(), ofGetHeight(), GL_RGB);
	fboPause.begin();
	ofClear(255,255);
	fboPause.end();
	fbo1.allocate(ofGetWidth()*2, ofGetHeight(),GL_RGB,8);
	fbo1.begin();
	ofClear(255,255);
	fbo1.end();
	
}

//--------------------------------------------------------------
void ofApp::update(){

	UImain.resize(ofGetWidth(), ofGetHeight());

	// Show fps on window bar
	std::stringstream strm;
	strm << "fps: " << ofGetFrameRate();
	ofSetWindowTitle(strm.str());

	if (scene == 1) {
		//MAP
		if (scroll == -ofGetWidth()) {
			fbo1.begin();
			fbo1.readToPixels(pix);
			ofImage img;
			img.setFromPixels(pix);
			ofClear(255,255);
			img.draw(-ofGetWidth(), 0);
			fbo1.end();
			ori.x -= ofGetWidth();
			scroll = 0;
		}
		else {
			scroll -= 1;
		}
		// PLAYER
		for (int i = 0; i < REPE; i++) {
			pos[i].x = ori.x + speed * cos(angulo) * dirX; 
			pos[i].y = ori.y + speed * sin(angulo);
			speed += 3.5 / REPE;
		}
		rot += ROT;
		if (ofGetFrameNum() % 1 == 0) {
			color == paleta[0] ? color = paleta[1] : color = paleta[0];
		}
	}
}

//--------------------------------------------------------------
void ofApp::draw(){

	// main menu
	if (scene == 0) {
		
		mainSong.setVolume(ofMap(counter,0,99,0,1));
		ofSetColor(ofMap(ofClamp(counter,0,99),0,99,0,255));
		UImain.draw(0, 0);
		if (counter < 100) counter++;

		if (ofGetElapsedTimef() > 4.4) {
			ofColor c = 0;
			if (ofGetFrameNum() % 20 == 0) {
				color == 0 ? color = 255 : color = 0;
			}
			ofSetColor(color);
			text.drawString("PLAY",center.x-50, center.y*1.6);
		}
	}

	// scene -1 (transition to 1)
	if (scene == -1) {
		mainSong.setVolume(ofMap(counter, 0, 9999, 0,1));
		ofSetColor(ofMap(ofClamp(counter,0,9999), 0, 9999, 0, 255));
		UImain.draw(0, 0);

		if (counter > 0) counter-=2;
		else {

			if (!music.isPlaying()) music.play();
			if (music.getPosition() > 0.0245) {

				ofClear(255,255);
				scene = 1;
			}
		}
	}

	// scene 1
	if (scene == 1) {
		fbo1.begin();
		for (int i = 0; i < REPE; i++) {
			ofSetColor(color);
			ofPushMatrix();
			ofTranslate(pos[i]);
			ofRotateDeg(rot + (ROT/REPE) * i); 
			ofDrawCircle(0, 0, rad);
			ofPopMatrix();
		}
		fbo1.end();
		ofSetColor(255);
		fbo1.draw(scroll,0);
		ofSetColor(0);
		ofPushMatrix();
		ofTranslate(pos[0].x + scroll, pos[0].y);
		ofRotateDeg(rot);
		ofDrawCircle(0, 0, rad+5);
		ofPopMatrix();
		ofSetColor(255);
	}

	//Pause
	if (scene == 9) {
		
	}
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){
	if (scene == 0) {
		if (key == OF_KEY_RETURN && ofGetElapsedTimef() > 4.4) {
			UIselect.play();
			scene = -1;
		}
	}
	
	if (scene == 1)
		switch (key) {
		case OF_KEY_RETURN:
			scene = 9;
			key = NULL;
			break;
		case 'q':
			paleta[0] = 230;
			paleta[1] = 0;
			break;
		case 'w':
			paleta[0] = ofColor::indianRed;
			paleta[1] = 0;
			break;
		case 'e':
			paleta[0] = ofColor::lightBlue;
			paleta[1] = 0;
			break;
		case ' ':
			resolution++;
			if (resolution > 5) resolution = 3;
			ofSetCircleResolution(resolution);
			break;
		}
	if (scene == 9) {
		switch (key) {
		case OF_KEY_RETURN:
			scene = 1;
			break;
		}
	}
}

void ofApp::mousePressed(int x, int y, int button) {
	if (scene == 1) {
		speed = 0;
		ori = pos[0];
		des = ofVec2f(x - scroll, y);
		adyasente = des.x - ori.x;
		opuesto = des.y - ori.y;
		hipotenusa = sqrt(adyasente * adyasente + opuesto * opuesto);
		angulo = asin(opuesto / hipotenusa);
		dirX = adyasente / abs(adyasente);
		dirY = opuesto / abs(opuesto);
	}
}

#video #lag #laggy #glitch #frames #FPS #frame #slow #performance

Hey @Ezequiel_Leon_Zybert ,

It looks like you’re reading and writing to the same ofFbo in ofApp::update(). This could be causing the glitch. A “pingpong” approach with 2 ofFbos might work better. Write to one while reading from the other. And std::swap() works with ofFbo if/when you need to swap them.

Also, in ofApp::draw() it looks like you’re writing to fbo1 and then drawing it as well. If you render to the ofFbos in ofApp::update(), and then draw them in ofApp::draw(), the graphics pipeline has a chance to work properly and draw the ofFbo. So I’d suggest you try and do all of your rendering to fbo1 in ofApp:update(), and then draw it if ofApp::draw().

1 Like

Hey thank you very much for your help.
With reading and writing the same fbo, do you mean this?:

if (scroll == -ofGetWidth()) {
  fbo1.begin();
  fbo1.readToPixels(pix);
  ofImage img;
  img.setFromPixels(pix);
  ofClear(255,255);
  img.draw(-ofGetWidth(), 0);
  fbo1.end();
  ori.x -= ofGetWidth();
  scroll = 0;
}

Because even if I comment that code lines the glitch stills there.

Hey yeah you can get the pixels with ofFbo::readToPixels() without calling ofFbo::begin() beforehand, like this:

if (scroll == -ofGetWidth()) {
  fbo1.readToPixels(pix);
  ofImage img;
  img.setFromPixels(pix);

  fbo1.begin();
  ofClear(255,255);
  img.draw(-ofGetWidth(), 0);
  fbo1.end();
  ori.x -= ofGetWidth();
  scroll = 0;
}

And you can also use 2 ofFbo, and draw 1 into the other, so that you don’t have to get the pixel data from the gpu (the ofTexture in the ofFbo) to the cpu (as ofPixels) and then into an ofImage (which has both an ofPixels and an ofTexture). So maybe something like this:

// in ofApp.h
ofFbo fbo1;
ofFbo fbo2; // could use this instead of an ofImage

// then in ofApp.cpp
if (scroll == -ofGetWidth()) {
  std::swap(fbo1, fbo2); // fbo2 now has the ofTexture of fbo1
  fbo1.begin(); // fbo1 is now available to draw something into it
  ofClear(255,255);
  fbo2.draw(-ofGetWidth(), 0);
  fbo1.end();
  ori.x -= ofGetWidth();
  scroll = 0;
}

thank you, but it stills doing that glitch even using 2 fbo instead of an ofImage.

I’ve sometimes had problems if I draw into an ofFbo in ofApp::draw(), and then try to render (to the screen) that same ofFbo in the same cycle. So I try to update the ofFbo (draw into it/them) in ofApp::update(), and then draw them to the screen in ofApp::draw(). You could try moving the following bit of code (and anything related to it) out of ofApp::draw() and into ofApp::update():

	// scene 1
	if (scene == 1) {
		fbo1.begin();
		for (int i = 0; i < REPE; i++) {
			ofSetColor(color);
			ofPushMatrix();
			ofTranslate(pos[i]);
			ofRotateDeg(rot + (ROT/REPE) * i); 
			ofDrawCircle(0, 0, rad);
			ofPopMatrix();
		}
		fbo1.end();

Then in ofApp::draw(), fbo1 can still be drawn along with the circle.

Sometimes allocating something (ofFbo), or loading something (ofImage), or calling functions with lots of computation (ofImage::resize() with a large image) can cause little glichy moments. So, you may also want to move the following into ofApp::setup(), so it just gets called once (and not once per cycle):

	UImain.resize(ofGetWidth(), ofGetHeight());

But I’m thinking this likely wouldn’t cause the intermittent glitch that you’ve shown in the video at 11 seconds or so. It seems to me that resizing a large image every cycle would slow down the fps.