> Does the size of the point have any effect on how transparent a point > appears? No, the transparency comes from the color associated with the point, or with the transparency coefficient in the transparency attributes if alpha is not specified with the color. > I'm using a pointarray to perform some splatting, with a Color4f (rgba), but > the alpha component doesn't seem to make any difference. I see a huge difference depending on the version of OpenGL being used. The attached example looks correct on some frame buffers, but does not look right on an Elite3D under Solaris (no per marker alpha) or on a TNT2 under windows (incorrect colors). Also, using J3D for splatting has a problem: splatting depends on rendering the splatted points from back to front, so that the splats in front cover those further back. By default, J3D does not guarantee the order of rendering for primitives. You can use an ordered group to force the rendering to have a particular order, but you'll have to reorder your splats when the orientation changes. If you are rendering an X,Y,Z grid, I suggest you use ordered groups to render the "slices" in order. For example, the +X ordered group would be used when the view is looking down the X axis, and the group would render the points in the YZ plane for each X value, from minimum to maximum. That way the number of elements in each ordered group will be the CUBESIZE instead of CUBESIZE ^ 3, and you can change the render order using a Switch to select the correct ordered group. See the volume rendering demo at: http://tintoy.ncsa.uiuc.edu/~srp/java3d/volume.html for an example of how to do this using 2D textured polygons (see the Axis2DRenderer.java). Support for rendering transparent objects from back to front automatically is being considered for J3D 1.2. Doug Gehringer Sun Microsystems
import java.applet.Applet; import java.awt.BorderLayout; import java.awt.event.*; import java.awt.GraphicsConfiguration; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.*; import javax.media.j3d.*; import javax.vecmath.*; public class PtSize extends Applet { final static int CUBESIZE = 5; // based in part on some test code from Aditya Datta private Shape3D createPoints() { // set up the appearance to make large, transparent, antialiased points Appearance app = new Appearance(); // increase the size of each point and turn on AA PointAttributes pa = new PointAttributes(10.0f, true); app.setPointAttributes(pa); // set up transparency TransparencyAttributes ta = new TransparencyAttributes(); ta.setTransparencyMode(ta.NICEST); ta.setTransparency(0.2f); // used if color is not COLOR_4 app.setTransparencyAttributes(ta); // create a cube of points to display int volumesq = CUBESIZE*CUBESIZE; Point3f coords[] = new Point3f[CUBESIZE*CUBESIZE*CUBESIZE]; Color4f colors[] = new Color4f[CUBESIZE*CUBESIZE*CUBESIZE]; for(int x=0; x<CUBESIZE; x++) { for(int y=0; y<CUBESIZE; y++) { for(int z=0; z<CUBESIZE; z++){ // coord is x,y,z normalized and centered coords[volumesq*x+CUBESIZE*y+z]= new Point3f((float)x/(CUBESIZE-1) - 0.5f, (float)y/(CUBESIZE-1) - 0.5f, (float)z/(CUBESIZE-1) - 0.5f); // color varies by coords, r = x, g = y, b=1, a = z colors[volumesq*x+CUBESIZE*y+z]= new Color4f((float)x/(CUBESIZE-1), (float)y/(CUBESIZE-1), 1.0f, (float)z/(CUBESIZE-1)); } } } PointArray pointArray = new PointArray( CUBESIZE*CUBESIZE*CUBESIZE, PointArray.COORDINATES | PointArray.COLOR_4); pointArray.setCoordinates(0, coords); pointArray.setColors(0, colors); Shape3D shape = new Shape3D(pointArray, app); return shape; } public BranchGroup createSceneGraph() { // Create the root of the branch graph BranchGroup objRoot = new BranchGroup(); // Create the transform group node and initialize it to the // identity. Enable the TRANSFORM_WRITE capability so that // our behavior code can modify it at runtime. Add it to the // root of the subgraph. TransformGroup objTrans = new TransformGroup(); objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); objRoot.addChild(objTrans); // Create a simple shape leaf node, add it to the scene graph. objTrans.addChild(createPoints()); // Create a new Behavior object that will perform the desired // operation on the specified transform object and add it into // the scene graph. AxisAngle4f axisAngle = new AxisAngle4f(0.0f, 0.0f, 1.0f, -(float)Math.PI / 2.0f); Transform3D yAxis = new Transform3D(); Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, 4000, 0, 0, 0, 0, 0); RotationInterpolator rotator = new RotationInterpolator(rotationAlpha, objTrans, yAxis, 0.0f, (float) Math.PI*2.0f); BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); rotator.setSchedulingBounds(bounds); objTrans.addChild(rotator); // Have Java 3D perform optimizations on this scene graph. objRoot.compile(); return objRoot; } public PtSize() { setLayout(new BorderLayout()); GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); Canvas3D c = new Canvas3D(config); add("Center", c); // Create a simple scene and attach it to the virtual universe BranchGroup scene = createSceneGraph(); SimpleUniverse u = new SimpleUniverse(c); // This will move the ViewPlatform back a bit so the // objects in the scene can be viewed. u.getViewingPlatform().setNominalViewingTransform(); u.addBranchGraph(scene); } // // The following allows PtSize to be run as an application // as well as an applet // public static void main(String[] args) { new MainFrame(new PtSize(), 256, 256); } }