I am working on a 3D renderer in Java using the Graphics class, It is now capable of drawing any shape with coloured faces, however I was wondering if it was possible to texture the faces? I have seen a lot of people creating software renderers in Javascript so surely there is an equivalent function/method of however they are doing it in Java...
I have looked around so far but all I can find is Graphics.setClip(Shape), I don't think it would be suitable because it merely sets the background texture and wouldn't stretch the texture if a vertex moved - and that's just in 2D, it need to also stretch/skew the texture when it's at an angle to the camera (Think of the sides of a rotating cube).
I really have no idea where to start, I can't use XOR modes because of no skewing and I really wouldn't know how to do the math if I had to do it manually.
How do these Javascript software renderers do it so well?
You may be able to leverage java.awt.TexturePaint
, illustrated here and here. In this context, you should know that TexturePaint
aligns with the rendering surface's raster, rather than the shape's bounds.
Addendum: While shading is a broad topic, also consider a pixel-based approach using gradient shading with alpha, illustrated in the KineticModel
cited here. Note that such a gradient can be applied to the WritableRaster
of a TexturePaint
.
For non-affine transformations, see javax.media.jai.Warp.Warp
, cited here.
I looked at doing this as a "fallback" for an OpenGL feature that would not run on some machines due to JOGL problems. I was unsuccessful. These were the unresolved questions that caused me to stop work:
Hidden surface removal. I could find no way to implement a z-buffer under Graphics2d primitives.
Perspective texture transforms. The AffineTransform available in Graphics2d has enough power to map textures if the image projection is parallel, but not perspective.
Mismatches in 2d clipping. The last operation in texturing will have to be clipping against a 2d mask. It turns out there is a bug in Graphics2d clipping. If you clip against perfectly adjoining 2d polygons, the clipped patches do not mate perfectly. Single pixels at the boundary are unshaded.
Performance. While recent versions of the Graphics2d pipeline try to use hardware acceleration if it's there, raw polygon rendering still tested an order of magnitude slower than JOGL, which was not good enough for my purposes.
The Javascript 3d libraries I've looked at are all built on WebGL, which in turn is implemented in HTML 5 Canvas objects. WebGL is an OpenGL API that must be implemented by the browser. Other 3d Javascript libraries use plug-ins to get at hardware-accelerated graphics. So they're not a useful source of information about how to do 3d in Swing.
Addition
Perhaps it is worth adding what I did do. To replace the 3d JOGL scene that the user can "fly through" by moving the camera, I chose a single, fixed viewpoint and "hard wired" the drawing order, effectively implementing the Painter's Algorithm with fixed logic to determine sort order, rendering more-or-less the same models as the JOGL view. I implemented Gouraud shading using gradient-filled polygons, which is where I found the clipping bug mentioned above. It all works and is running in hundreds of thousands of copies, but it's messy and fragile, and I wouldn't want to do it again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With