[SOLVED] LWJGL 3 : How to change frame rate?

Started by hyyou, December 14, 2015, 06:11:57

Previous topic - Next topic

hyyou

In LWJGL 2, the frame rate can be set by
Display.update(120)
in the game loop.

In LWJGL 3, the game loop call
org.lwjgl.glfw.GLFW.glfwPollEvents();
org.lwjgl.glfw.GLFW.glfwSwapBuffers(window);


But... how to change frame rate in LWJGL 3 while the game is running?

The popular article LWJGL3-migration deliberately omit this topic. ( https://github.com/LWJGL/lwjgl3-wiki/wiki/2.6.6-LWJGL3-migration )

abcdef

Have a look at this page, you can implement a model that suits your needs

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

LWJGL3 is much lighter than LWJGL2 and some of the functionality was not ported across.

But there are some things to note here, your monitor refresh rate is the fastest you can possible update the monitor. If vsync is enabled then you max out at the monitor refresh rate. You might need to tell your graphics drivers to remove vsync if you want to "loop" faster.

bobjob

I have a class that will replace the sync method in LWJGL 2 (but also adds some features, if needed).

how to use:
SyncTimer timer  = new SyncTimer(SyncTimer.LWJGL_GLFW);

//MAIN RENDER LOOP

while ( GLFW.glfwWindowShouldClose(window) == GL11.GL_FALSE ) {
	render();
	GLFW.glfwSwapBuffers(window);
	GLFW.glfwPollEvents();
	timer.sync(60);	        
}



The class is as follows:
import org.lwjgl.glfw.GLFW;

public class SyncTimer {

	final static double
			NANO_RESOLUTION = 1000000000.0D,
			GLFW_RESOLUTION = 1.0D;
	
	public final static int
			JAVA_NANO = 1,
			LWJGL_GLFW = 2;
	
	private int mode;
	private double timeThen;
	private boolean enabled = true;
	
	public SyncTimer(int mode) {
		setNewMode(mode);
	}
		
	private double getResolution() {
		switch (mode) {
			case JAVA_NANO: return NANO_RESOLUTION;
			case LWJGL_GLFW: return GLFW_RESOLUTION; 
		}
		return 0;
	}
	
	private double getTime() {
		switch (mode) {
			case JAVA_NANO: return System.nanoTime();
			case LWJGL_GLFW: return GLFW.glfwGetTime(); 
		}
		return 0;
	}
	
	
	public void setEnabled(boolean enable) { enabled = enable;}
	
	public boolean isEnabled() { return enabled; }

	public void setNewMode(int timerMode) {
		mode = timerMode;
		timeThen = getTime();
		System.out.println("Timer mode set to " + getModeString() + " timer");
	}

	public String getModeString() {
		switch (mode) {
			case JAVA_NANO: return "NANO";
			case LWJGL_GLFW: return "LWJGL";
		}
		return null;
	}
	
	public int getMode() {
		return mode;
	}
	
	public int sync(double fps) throws Exception {
		double resolution = getResolution();
		double timeNow =  getTime();
		int updates = 0;
		
		if (enabled) {
			double gapTo = resolution / fps + timeThen;
			
			while (gapTo < timeNow) {
				gapTo = resolution / fps + gapTo;
				updates++;
			}
			while (gapTo > timeNow) {
				Thread.sleep(1);
				timeNow = getTime();
			}
			updates++;

			timeThen = gapTo; 
		} else {
			while (timeThen < timeNow) {
				timeThen = resolution / fps + timeThen;
				updates++;
			}
		}
		
		return updates;
	}
}


Note: the sync method will return the number of cycles that have passed since the last call. This can be used in case your rendering code is laggy and your logic is falling behind and needs to know how many extra logic cycles to run. You can also use these cycle counts along with disabling the SyncTimer and vsync, use it to only get the number of cycles passed. This is good along with an FPS Counter to benchmark your rendering cycles in order to see how efficient you rendering code is, without changing your game speed.

hyyou

Quote from: abcdef on December 14, 2015, 09:24:34
But there are some things to note here, your monitor refresh rate is the fastest you can possible update the monitor. If vsync is enabled then you max out at the monitor refresh rate. You might need to tell your graphics drivers to remove vsync if you want to "loop" faster.

Thank!, abcdef.
glfwSwapInterval(0) is the solution.

Thank bobjob, I will take a look into it.