Sign in to follow this  
clearz

Java Renderer

Recommended Posts

Hi I am going to try and program a small renderer in java just to gain a better knowlege of what goes on under the hood in a 3D engine. I have spent the day looking at the different ways that java can display graphics to the screen. I then developed this small prog to test what kind of framerate I could expect to get. I am not very happy with the results at all. I know it is java and all that but I expected to get better results. Maybe I am doing something completly wrong here and was wondering could you have a look at it and tell me youtr opinions. What it basically does is draw 1000 triangles to a VolitileImage and then flip it to the screen. I have a P4 2Ghz, Geforce 3 Ti500 Java1.5 and I get arroun 9 FPS with this. Surely this can be made better. At this rate if I were to design a renderer with basic texture and lighting support I wold be lucky to get one frame a week :)
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.util.*;

public class FPSTest extends JWindow {

    VolatileImage backBuffer = null;
	long temp = 0;
	long fps;
	long lg = 0;
	Random rand = new Random();
	int x[] = new int[3];
	int y[] = new int[3];
	public FPSTest()
	{
	    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

		GraphicsDevice gd = ge.getDefaultScreenDevice();
		addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent evt) {
				// Exit full-screen mode
				GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment()
					.getDefaultScreenDevice();
				gd.setFullScreenWindow(null);
				System.exit(0);
			}
		});
		try
		{
			gd.setFullScreenWindow(this);
       		requestFocus();

			while(true)
			{
				repaint();
			}
		}
		catch(Exception e)
		{}
		finally
		{
	        gd.setFullScreenWindow(null);
	        System.exit(0);
		}
	}

    public void createBackBuffer()
    {
		if (backBuffer != null)
		{
			backBuffer.flush();
			backBuffer = null;
		}
		backBuffer = createVolatileImage(getWidth(), getHeight());
    }
	String s;
    public void paint(Graphics g)
    {
		if (backBuffer == null)
		{
	   		createBackBuffer();
		}
		do
		{
			fps = new Date().getTime();
			// First, we validate the back buffer
			int valCode = backBuffer.validate(getGraphicsConfiguration());
			if (valCode == VolatileImage.IMAGE_RESTORED) {}
			else if (valCode == VolatileImage.IMAGE_INCOMPATIBLE)
			{
				createBackBuffer();
			}
			// Now we've handled validation, get on with the rendering
			// rendering to the back buffer:
			Graphics gBB = backBuffer.getGraphics();
			gBB.setColor(Color.white);
			gBB.fillRect(0, 0, getWidth(), getHeight());
			gBB.setFont(new Font("Arial",1,16));
		    gBB.setColor(Color.red);

			if((fps - temp) !=0)
			{
				lg = (1000 / (fps - temp));
				s = "FPS " + lg;
			}
			else
			{
				s = "FPS " + lg;
			}
			System.out.println(lg);
	 		gBB.drawString(s,20,25);
	 		gBB.setColor(Color.black);
			for(int q=0;q<1000;q++)
			{
				gBB.setColor(new Color(rand.nextInt(254),rand.nextInt(254),rand.nextInt(254)));

				x[0] = rand.nextInt(1200) + 40;
				x[1] = rand.nextInt(1200) + 40;
				x[2] = rand.nextInt(1200) + 40;
				y[0] = rand.nextInt(1000) + 40;
				y[1] = rand.nextInt(1000) + 40;
				y[2] = rand.nextInt(1000) + 40;
				gBB.fillPolygon(x, y, 3);
			}
			// copy from the back buffer to the screen
			g.drawImage(backBuffer, 0, 0, this);

	    // Now we are done; or are we?  Check contentsLost() and loop as necessary
	    	temp = fps;
		} while (backBuffer.contentsLost());
    }

    public static void main(String args[])
    {
		new FPSTest();

    }
}

Share this post


Link to post
Share on other sites
Sorry I don't have Java installed at the mo so I cant help too much, but in your innermost loop you are creating a new Color object every iteration, that might be slowing it down. (Bare in mind my experiments with 3D graphics and Java were done in Java 1.1 and a lot has probably changed since then)

Share this post


Link to post
Share on other sites
A few things:

1. Buy these two books: Learning Java and Developing Games In Java.

2. I don't like the idea of having an endless loop in the constructor to call repaint. Might I suggest using threads (implement Runnable interface) and call your repaint in the run() method.

I haven't looked too closely at the code, but that is what I see after a quick glance.

Java has come a long long long long (did i say long?) long way since Java 1.0. It is practically as fast (of course, not faster) than C++. Those low frame rates definitly imply you are doing something wrong. The language is not /that/ slow :)

Share this post


Link to post
Share on other sites
I decided to play around with the code a little... Try this:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.util.*;

public class FPSTest extends JComponent implements Runnable {

VolatileImage backBuffer = null;
long temp = 0;
long fps;
long lg = 0;
Random rand = new Random();
int x[] = new int[3];
int y[] = new int[3];

public FPSTest()
{
Thread t = new Thread( this );
t.start();
}

public void run() {
// try {
while ( true ) {
repaint();
// Thread.sleep( 1000 );
}
// }
// catch ( InterruptedException ie ) {}
}

public void createBackBuffer()
{
if (backBuffer != null)
{
backBuffer.flush();
backBuffer = null;
}
backBuffer = createVolatileImage(getWidth(), getHeight());
}
String s;
public void paint(Graphics g)
{
if (backBuffer == null)
{
createBackBuffer();
}
do
{
fps = new Date().getTime();
// First, we validate the back buffer
int valCode = backBuffer.validate(getGraphicsConfiguration());
if (valCode == VolatileImage.IMAGE_RESTORED) {}
else if (valCode == VolatileImage.IMAGE_INCOMPATIBLE)
{
createBackBuffer();
}
// Now we've handled validation, get on with the rendering
// rendering to the back buffer:
Graphics gBB = backBuffer.getGraphics();
gBB.setColor(Color.white);
gBB.fillRect(0, 0, getWidth(), getHeight());
gBB.setFont(new Font("Arial",1,16));
gBB.setColor(Color.red);

if((fps - temp) !=0)
{
lg = (1000 / (fps - temp));
s = "FPS " + lg;
}
else
{
s = "FPS " + lg;
}
System.out.println(lg);
gBB.drawString(s,20,25);
gBB.setColor(Color.black);
for(int q=0;q<1000;q++)
{
gBB.setColor(new Color(rand.nextInt(254),rand.nextInt(254),rand.nextInt(254)));

x[0] = rand.nextInt(1200) + 40;
x[1] = rand.nextInt(1200) + 40;
x[2] = rand.nextInt(1200) + 40;
y[0] = rand.nextInt(1000) + 40;
y[1] = rand.nextInt(1000) + 40;
y[2] = rand.nextInt(1000) + 40;
gBB.fillPolygon(x, y, 3);
}
// copy from the back buffer to the screen
g.drawImage(backBuffer, 0, 0, this);

// Now we are done; or are we? Check contentsLost() and loop as necessary
temp = fps;
} while (backBuffer.contentsLost());
}

public static void main(String args[])
{
JFrame frame = new JFrame( "FPSTest" );
frame.getContentPane().add( new FPSTest() );
frame.setSize(500,500);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setVisible( true );
}
}


I just put it in a JFrame instead of a JWindow.. but it's the same concept.

I implemented a new thread, as I mentioned in my previous post. It raised the FPS from ~10 to ~21 fps. The lines commented out in my run() method allow for you to tweak your animation by putting the thread to sleep for however many milliseconds you want. During that time the paint() method won't be invoked.

Other than that, the reason for the semi-low FPS is that you're drawing a lot of stuff. If you lower your 1000 triangles, I was getting around 65 FPS.

Hope that helps.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this