I’ve created an example to illustrate the performance hit on the OS even though the application isn’t using any CPU resources.
Please try it yourself and tell me if you get the same results or if I’m doing something wrong.
import com.sun.opengl.util.GLUT;
import javax.media.opengl.*;
import static javax.media.opengl.GL.*;
import javax.media.opengl.glu.GLU;
import javax.swing.*;
import java.awt.*;
/**
* Example to illustrate the choppyness of the OS while the application is not using CPU resources.
*/
public class SlowDownTest implements GLEventListener {
private String[] vertexShader = new String[]{
"varying vec3 normal;\n" +
"void main() {\n" +
" normal = normalize(gl_Normal);\n" +
" gl_Position = ftransform();\n" +
"}"};
private String[] fragmentShader = new String[]{
"varying vec3 normal;\n" +
"void main (void) {\n" +
" vec3 N = normalize(normal);\n" +
" vec4 final_color = vec4(0, 0, 0, 0);\n" +
" float f = 0.0;\n" +
" for(int i = 0; i < 220; i++) {\n" +
" for(int j = 0; j < 150; j++) {\n" +
" f = f + float(i) / float(j + 1);\n" +
" }\n" +
" }\n" +
" for(int i = 0; i < 220; i++) {\n" +
" for(int j = 0; j < 150; j++) {\n" +
" final_color.rgb = N.xyz * 0.5 + 0.5;\n" +
" final_color.a = 1.0 * f;\n" +
" }\n" +
" }\n" +
" gl_FragColor = final_color;\n" +
"}"};
private int width = 500;
private int height = 400;
private GLCanvas glCanvas;
private float stepSize = (float) (Math.PI / 16);
private float rot = 0;
private int program;
public SlowDownTest() {
GLCapabilities glCapabilities = new GLCapabilities();
glCanvas = new GLCanvas(glCapabilities);
Dimension size = new Dimension(width, height);
glCanvas.setSize(size);
glCanvas.setPreferredSize(size);
glCanvas.setMinimumSize(size);
glCanvas.addGLEventListener(this);
JFrame frame = new JFrame("Slowdown Shader Test");
frame.getContentPane().add(glCanvas);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
CustomAnimator animator = new CustomAnimator();
animator.start();
}
public void init(GLAutoDrawable glAutoDrawable) {
GL gl = glAutoDrawable.getGL();
gl.glClearColor(0, 0, 0, 1);
gl.glEnable(GL_DEPTH_TEST);
gl.glShadeModel(GL_SMOOTH);
gl.glEnable(GL_NORMALIZE);
gl.glFrontFace(GL_CCW);
gl.glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
gl.glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
createShaders(gl);
}
private void createShaders(GL gl) {
System.out.println("Compiling Shaders.");
int vertexShaderObject = gl.glCreateShader(GL_VERTEX_SHADER);
int fragmentShaderObject = gl.glCreateShader(GL_FRAGMENT_SHADER);
program = gl.glCreateProgram();
gl.glShaderSource(vertexShaderObject, vertexShader.length, vertexShader, null);
gl.glShaderSource(fragmentShaderObject, fragmentShader.length, fragmentShader, null);
gl.glAttachShader(program, vertexShaderObject);
gl.glAttachShader(program, fragmentShaderObject);
gl.glCompileShader(vertexShaderObject);
gl.glCompileShader(fragmentShaderObject);
gl.glLinkProgram(program);
System.out.println("Compiled!");
}
public void display(GLAutoDrawable glAutoDrawable) {
GL gl = glAutoDrawable.getGL();
gl.glClearColor(0, 0, 0, 1);
gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl.glPushMatrix();
gl.glTranslatef(0, 0, -3);
gl.glRotatef(rot, 0, 1, 0);
gl.glUseProgram(program);
GLUT glut = new GLUT();
glut.glutSolidTeapot(1);
gl.glUseProgram(0);
gl.glPopMatrix();
rot += stepSize;
}
public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int height) {
GL gl = glAutoDrawable.getGL();
gl.glViewport(x, y, width, height);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
GLU glu = new GLU();
glu.gluPerspective(60, (float) width / height, 0.1f, 1000f);
gl.glMatrixMode(GL.GL_MODELVIEW);
}
public void displayChanged(GLAutoDrawable glAutoDrawable, boolean b, boolean b1) {
}
public static void main(String[] args) {
SlowDownTest test = new SlowDownTest();
}
public class CustomAnimator implements Runnable {
private boolean running = true;
private Thread thread = null;
public CustomAnimator() {
thread = new Thread(this);
}
public synchronized void start() {
thread.start();
}
public synchronized void stop() {
running = false;
while (thread != null) {
//Make sure run completes
try {
wait();
} catch (InterruptedException ie) {
//
}
}
}
public void run() {
while (running) {
if (glCanvas != null) {
glCanvas.display();
} else {
running = false;
}
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (CustomAnimator.this) {
thread = null;
CustomAnimator.this.notify();
}
}
}
}
PS: Increase or decrease the number of iterations in the fragment shader to get the right effect. ;D