Questions about the way Java handles graphics

Hello, I am new here so bear with me :slight_smile:
I have some questions which I’d like to get answered. They are all about JComponent.getGraphics() (Graphics.XXX()) function calls. I am making a 3d engine so I’d like the most efficient solutions.

  1. How does Java handle drawing outside of a component’s boundaries? I’d like to know this so I can decide if it’s more efficient to write a clipping function to remove the data outside the boundaries or just let Java draw outside the boundaries. There are three scenarios as far as I can see:

*) Java clips automatically and skips the drawing instruction - thus rendering the need of a separate clipping function in the XY-plane unnecessary. I find this most probable.

*) Java tries to draw outside the boundaries with the same speed as drawing inside the boundaries.

*) Java tries to draw outside the boundaries with an impact on speed, thus validating the use of a separate clipping function.

**** EDIT ****
After some testing, I found out JComponents are almost certainly clipped by Java. That’s good news…


  1. How does Java fill shapes; does it use some sort of scan conversion algorithm or a flood filling algorithm?
    If the later is correct; how fast is it? Would a custom made filling function for filling shapes speed up things?

  2. How does Java double buffer JComponents? Is it acceptable to use the built in double buffering or should you make an own function for it?

Any more things I should take into account? I have got a wireframe 3d engine to work, and am in the process of adding support for solid shapes.

**** EDIT ****
It now supports solid shapes and lightning :slight_smile:


Sincerely,
Tommi Kiviniemi from Luleå, Sweden :slight_smile:

  1. i dunno, but i once wrote a software 3D renderer with a miniGL and it’s horribly slow. i haven’t tried to optimize it, i however think that my setPixel() is slow, and it’s a known fact that direct image manipulation is slow. you can find the source over at my site. the renderer is called Crap3D. source is included.

i’d suggest that you use the built-in stuff for rendering flat shaded poys. about gourad or phong shaded polys there are no built-in support.

you might be better off using LWJGL or Java3D.

nice to see a fellow swede :slight_smile:

Hi and thanks for the answer.

I am making it purely in software so I don’t want to use ANY libraries from Java3D or anything that has to do with OpenGL :slight_smile:

One question though, why did you use setPixel()? What did you use it for?

Later!

to set a pixel on the screen i created a method called that and everything that is drawn uses that, from lines to triangles etc.

that way the renderar can be converted to all sorts of things and only one method has to be changed, that is, setPixel(…)

it seemed like a good idea at the time :slight_smile:

Hmm that is a really really slow way of doing it.

When drawing horizontal lines Java can copy an entire section of pixels with a fast memcopy instruction into the double buffer. Most probably the filling instructions are built utilizing this method. (Note that I am not sure this really is the case (hence my questions), but I am 99% sure the above method is used).
Thus using dedicated drawLines() and fillXXX() would be heaps faster!

Peace :slight_smile:

yup, most likely.

i wrote this to learn how low level graphics were implemented. i didn’t think it would end up this slow though :slight_smile:

Much of this is not specified. So any experiments you do will only be valid for the version of the Java runtime that you test on.
The Mac for instance could be quite different, since it uses OpenGL for rendering and implicitly double buffers a lot of graphic operations and hardware accelerates some operations.

[quote]It now supports solid shapes and lightning :slight_smile:
[/quote]
Do you want to add texture mapping/gouraud shading? If so, you’ll most likely have to use a MemoryImageSource (for 1.1) or a BufferedImage (for 1.2+) and rasterize the scanlines all be yourself (i.e. you end up writing ints into an array…). The same is true if you want to stay flatshaded but zbuffered.
Oh, and btw: It’s called lighting (without the n). Lightning is what comes before the thunder… :slight_smile:

( lightning is far easier to pronounce than lighting in swedish, so it’s a common mistake :slight_smile: )

ehm i meant for a swede of course. in swedish it’s easy to tell them apart

[quote]Hello, I am new here so bear with me :slight_smile:
I have some questions which I’d like to get answered. They are all about JComponent.getGraphics() (Graphics.XXX()) function calls. I am making a 3d engine so I’d like the most efficient solutions.
[/quote]
I’ll try to part with the little i learned while exploring the Java class library while writing a 2D game engine.

I think that clipping is done automatically. You could always check in the source files for yourself (they’re included with the SDK).

One could for example use the buffer strategies introduced in 1.4. They use hardware accelerated images as buffers (voilatile image… sp?) and use either blitting or flipping to render to the screen depending on if you are in fullscreen. Also note that Swing components should be double buffered by default (not with voilatile images though).

Very much can be gained by looking at the source files.

Best Regards,

Johan Tibell
Gothenburg, Sweden

Thanks everyone for the answers, I am slowly getting to my goals :o)

Oh does JDK1.4 have support for full screen? Didn’t even know about it, just played by the rules like I’ve always done with Java (no full screen, no hardware acceleration etc…:).

About the double buffering thingy, when you draw hundreds of shapes (faces) to a JComponent that is (natively) double buffered it starts to flicker inherently. I thought this was supposed to be fixed so Java never ceases to amaze me! Is this a known bug or am I doing something terribly wrong?

Thanks about the tip about BufferedImage, I’ve looked a bit into it earlier and came to the same conclusion. An another idea that crossed my mind today, however, was to use Java2Ds GradientPaint. I’ve never used anything from the Java2D library so I don’t know if this would even work, so it’s just an idea that crossed my mind. Could anyone who has used it post how fast it is? I don’t want to spend some hours writing code for it at this point just to find out it’s crawlingly slow…

Oh, and sorry about the lightning stuff, I try to be as correct as possible when writing posts in english but sometimes these things just slip by :slight_smile: I am very glad that I am not american though, hehe.

Later dudes.

I don’t know about the speed of GradientPaint, but from my experience with 2D stuff done in Java (i.e. AWT/Swing) in general, i wouldn’t expect to much from it speedwise. And i don’t think that it’s usefull for doing lighting, because it seems to interpolate between 2 colors, but for filling a triangle you’ll need to interpolate between the colors of all three vertices. That, and a linear interpolation in screen-space like GradientPaint is doing it, is not perspective correct. That may not be that much of a problem on smaller polygons but it will be noticable on larger ones (the lighting will distort somehow when viewing the polygon from different angles).
If you really want to do something more advanced than flatshading, i suggest to go the BufferedImage/MemoryImageSource-way, but that means to do the rasterisation yourself…
In case you are interested in how fast/slow this can be, my own “pixel-stuff” can be found here: http://www.jpct.net/ (but not the sources, just the API).

I’m pretty sure that the javax.swing.JComponent doesn’t use buffer strategies. It’s double buffered in a simpler way not using volatile images. You could draw on a canvas for example:

public class GameCanvas extends java.awt.Canvas
{
    public GameCanvas()
    {
        createBufferStrategy(2);

        while (running)
        {
            Graphics g = getBufferStrategy;().getDrawGraphics();

            g.setColor(Color.WHITE);
            g.fillRect(0, 0, getWidth(), getHeight());

            getBufferStrategy().show();
        }
    }
}

The code above is very much simplified and perhaps not 100% correct since I just wrote it on the top of my head without looking at the API (time to go to bed).

NOTE: I couldn’t even align it properly by hand…

Whoa whoa whoa… I saw that globe on your site and it surely is impressive. Very nice job on the engine. Do you have many users for it?

Oh, and do you use BufferedImage for all the drawing instructions? I mean, for example, I draw the lines when in wireframe mode with a simple drawLine() command and fill the calculated 3d vertices in 2d space with fillPolygon(xvertices[], yvertices[]). Do you think I’d gain speed by doing all the rasterisation by myself and make my own library for all the drawing operations with BufferedImage, or would it be overkill for everything else than texture mapping?

Thanks a bunch of times for all your answers, this means a lot to me :slight_smile: I’ll try to answer here whenever I have time to pay back for your efforts.

Tommi

[quote]Whoa whoa whoa… I saw that globe on your site and it surely is impressive. Very nice job on the engine. Do you have many users for it?
[/quote]
You talking to me? ???

Yes. You accuire the Graphics object from the BufferedImage an do all your drawing such as drawLine() on it. Then you blit it to the screen.

No problem.

Johan

I think he was talking to me… :wink:

You may do that, but that’s not what i was talking about in the first place. But it’s correct…you can use all drawXXX-stuff on a BufferedImage even if you are setting pixels by yourself too. What i was actually talking about was this:

Image output = new BufferedImage(x, y, BufferedImage.TYPE_INT_RGB);
DataBufferInt data = (DataBufferInt) ((BufferedImage) output).getRaster().getDataBuffer();
int[] pixels = data.getData();

Then you may put your pixels into that array one by one like you did in the good old DOS-days directly into the VGA’s framebuffer… ;D

IF you want to support Java 1.1 (which makes sense for applets IMHO), you can’t use the drawXXX-methods, because you don’t get a usefull Graphics-object from the MemoryImageSource…so in that case, you would have write all drawLine(), drawString() etc stuff yourself (or copy the rendered Image into a regular Image and do it there…which decreases performance due to the copying).

I understand. I was a little bit confused about who he was addressing in his post as you might have noticed. :smiley:

Best Regards,

Johan

Egon - I checked out your globe (very pretty). I was getting ~18 fps on my machine. How does that scale with increasing window size? If you displayed the same globe in a window twice as wide & high, would the fps drop by 4x? A while ago I was doing some pixel plotting for a voxel engine. It was fine when I had a small window (300x200), but once I got to a size usable for a game, it ran terribly slow. (or slowly, one or the other)

Hi. I got around 60-70 fps so you are probably running on a very low end machine or have turned off JIT compiling.