Vision_Thing
Senior Newbie 
Java games rock!
|
 |
«
Posted
2003-04-27 23:18:11 » |
|
Hello, I am new here so bear with me  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... ************* 2) 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? 3) 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  ************* Sincerely, Tommi Kiviniemi from Luleå, Sweden 
|
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #1 - Posted
2003-04-28 07:50:18 » |
|
2) 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 
|
|
|
|
Vision_Thing
Senior Newbie 
Java games rock!
|
 |
«
Reply #2 - Posted
2003-04-28 19:56:59 » |
|
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  One question though, why did you use setPixel()? What did you use it for? Later!
|
|
|
|
|
Games published by our own members! Check 'em out!
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #3 - Posted
2003-04-28 20:09:44 » |
|
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 
|
|
|
|
Vision_Thing
Senior Newbie 
Java games rock!
|
 |
«
Reply #4 - Posted
2003-04-28 20:37:01 » |
|
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 
|
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #5 - Posted
2003-04-28 20:44:53 » |
|
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 
|
|
|
|
swpalmer
|
 |
«
Reply #6 - Posted
2003-04-29 02:56:22 » |
|
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.
|
|
|
|
EgonOlsen
|
 |
«
Reply #7 - Posted
2003-04-29 17:44:43 » |
|
It now supports solid shapes and lightning  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... 
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #8 - Posted
2003-04-29 17:49:57 » |
|
( light ning is far easier to pronounce than lighting in swedish, so it's a common mistake  )
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #9 - Posted
2003-04-29 17:50:46 » |
|
ehm i meant for a swede of course. in swedish it's easy to tell them apart
|
|
|
|
Games published by our own members! Check 'em out!
|
|
johtib
Senior Newbie 
|
 |
«
Reply #10 - Posted
2003-04-29 18:55:56 » |
|
Hello, I am new here so bear with me :) 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. I'll try to part with the little i learned while exploring the Java class library while writing a 2D game engine. 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... *************
I think that clipping is done automatically. You could always check in the source files for yourself (they're included with the SDK). 3) 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?
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
|
|
|
|
|
Vision_Thing
Senior Newbie 
Java games rock!
|
 |
«
Reply #11 - Posted
2003-04-29 20:28:53 » |
|
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 :) I am very glad that I am not american though, hehe.
Later dudes.
|
|
|
|
|
EgonOlsen
|
 |
«
Reply #12 - Posted
2003-04-29 21:01:56 » |
|
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).
|
|
|
|
johtib
Senior Newbie 
|
 |
«
Reply #13 - Posted
2003-04-29 22:25:16 » |
|
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: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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....
|
|
|
|
|
Vision_Thing
Senior Newbie 
Java games rock!
|
 |
«
Reply #14 - Posted
2003-04-29 22:35:39 » |
|
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  I'll try to answer here whenever I have time to pay back for your efforts. Tommi
|
|
|
|
|
johtib
Senior Newbie 
|
 |
«
Reply #15 - Posted
2003-04-30 06:00:29 » |
|
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?
You talking to me?  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?
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. Thanks a bunch of times for all your answers, this means a lot to me  I'll try to answer here whenever I have time to pay back for your efforts. Tommi No problem. Johan
|
|
|
|
|
EgonOlsen
|
 |
«
Reply #16 - Posted
2003-04-30 06:19:32 » |
|
You talking to me?  I think he was 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.
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: 1 2 3
| 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...  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).
|
|
|
|
johtib
Senior Newbie 
|
 |
«
Reply #17 - Posted
2003-04-30 13:55:13 » |
|
I think he was talking to me...  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: I understand. I was a little bit confused about who he was addressing in his post as you might have noticed.  Best Regards, Johan
|
|
|
|
|
snak
Senior Newbie 
Eu não falo o português
|
 |
«
Reply #18 - Posted
2003-05-01 19:26:54 » |
|
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)
|
|
|
|
|
Vision_Thing
Senior Newbie 
Java games rock!
|
 |
«
Reply #19 - Posted
2003-05-02 00:06:36 » |
|
Hi. I got around 60-70 fps so you are probably running on a very low end machine or have turned off JIT compiling.
|
|
|
|
|
EgonOlsen
|
 |
«
Reply #20 - Posted
2003-05-02 09:05:10 » |
|
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) It depends (like in any other 3D application). As long as you are fillrate limited (and you are most likely fillrate limited when using jPCT in software mode), the drop in framerate will be quite noticable when enlarging the window. Maybe not the 4x you mentioned, but close to that (3x maybe...). But there nothing you can do about it...the more pixels to fill, the slower it goes...  18fps is quite low...what kind machine is that? A P3-600 or similar?
|
|
|
|
snak
Senior Newbie 
Eu não falo o português
|
 |
«
Reply #21 - Posted
2003-05-02 14:39:07 » |
|
its just my cheap work laptop. its something like 800mhz. i tried it at home and got much better results.
|
|
|
|
|
Vision_Thing
Senior Newbie 
Java games rock!
|
 |
«
Reply #22 - Posted
2003-05-04 10:05:27 » |
|
Ok, major help needed here!
I created an application that tests the speed of the drawImage() instruction, ie:
Graphics g = surface.getGraphics(); g.drawImage(doubleBuffer);
The speed with an empty scene without framerate limiter was 300fps at 640x48, but at 1600x1200 just 35-40!
I will go with the MemoryImageSource as you guys suggested in this thread, but will it solve this problem; ie is it possible to copy the contents of the Image created from the 2d array into a surface without using g.drawImage()?
I have never used MemoryImageSource before but must master it in order to implement Z Buffer. Oh well :I
|
|
|
|
|
|