So I’m making a galaxy with point sprites representing stars (thousands, not billions, obviously- for both rendering and gameplay reasons). I’ll be rendering this galaxy both somewhat close up and very far out (it should be possible to see the entire galaxy on the screen). To make it look not-crappy, in addition to the stars, I want to render a quad with a texture on the galaxy’s plane of the ecliptic (is that a term for galaxies? I know it’s used for solar systems) so it looks more solid than it would with just stars. I also want a skybox - realistically, very few other galaxies would be visible and they would be so distant as to appear as points, but people associate space with seeing a dense starfield, so a skybox is necessary.
I have all these rendering, but I’m running into some very odd depth problems. This is the code for creating the point sprite for a star, after its characteristics have been determined:
[java] private Geometry createStar(Vector3f color, Vector3f position,
float size, String texture, AssetManager assetManager) {
Mesh m = new Mesh();
m.setMode(Mesh.Mode.Points);
m.setBuffer(VertexBuffer.Type.Normal, 3,
BufferUtils.createFloatBuffer(Vector3f.ZERO));
m.setBuffer(VertexBuffer.Type.Color, 3,
BufferUtils.createFloatBuffer(color));
m.setBuffer(VertexBuffer.Type.Position, 3,
BufferUtils.createFloatBuffer(new Vector3f(0f, 0f, 0f)));
m.setBuffer(VertexBuffer.Type.TexCoord, 4,
BufferUtils.createFloatBuffer(new Vector4f(0.0f, 0.0f, 1.0f, 1.0f)));
m.setBuffer(VertexBuffer.Type.Size, 1,
BufferUtils.createFloatBuffer(size));
Geometry g = new Geometry("Star", m);
g.setLocalTranslation(position);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
mat.setTexture("Texture", assetManager.loadTexture(texture));
mat.setFloat("Quadratic", 20f);
mat.setBoolean("PointSprite", true);
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
mat.getAdditionalRenderState().setDepthTest(true);
g.setMaterial(mat);
return g;
}[/java]
Once a list of stars has been created, I create these and batch them together:
[java] SimpleBatchNode galaxy = new SimpleBatchNode();
for (Star s : stars) {
Geometry g = createStar(
s.color, s.location, s.size, "Textures/Star2d.DDS", assetManager);
galaxy.attachChild(g);
s.sprite = g;
}
galaxy.batch();
rootNode.attachChild(galaxy);[/java]
It uses alpha blend mode and (supposedly) its material is doing depth testing, but some stars are occluded when they should not be:
Upon further testing, it seems like if star A is created (and added to the scenegraph) before star B, B will always appear in front of A, regardless of their 3D locations.
Additionally, I use a quad to render a galaxy image I cobbled together from my star density map and Hubble pics. This is rendered on the galaxy’s plane of the ecliptic, with some stars below it and some above. This is the code I use to create it:
[java] private void createGalaxyImage(Node rootNode, AssetManager assetManager, int diameter) {
Material galaxyMat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
galaxyMat.setTexture(“ColorMap”, assetManager.loadTexture(“Textures/GalaxyLarge2.png”));
galaxyMat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
galaxyMat.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
Quad galaxyImage = new Quad(diameter, diameter, true);
Geometry galaxyImageGeo = new Geometry("Galaxy", galaxyImage);
galaxyImageGeo.rotate((float)(-Math.PI/2), 0, 0);
galaxyImageGeo.move(-diameter/2, 0, diameter/2);
galaxyImageGeo.setMaterial(galaxyMat);
rootNode.attachChild(galaxyImageGeo);
}[/java]
This comes with its own rendering issues. The image has an alpha channel and its blendmode is set to Alpha, but it occludes the star PointSprites:
The weirdest problem arises when I render he skybox. This is the code to make it, which runs after both the galaxy and its quad are created/placed in the scenegraph (not sure if that’s relevant):
[java] Texture top = assetManager.loadTexture(“Textures/Galaxies_top.png”);
Texture bottom = assetManager.loadTexture(“Textures/Galaxies_bottom.png”);
Texture front = assetManager.loadTexture(“Textures/Galaxies_front.png”);
Texture back = assetManager.loadTexture(“Textures/Galaxies_back.png”);
Texture left = assetManager.loadTexture(“Textures/Galaxies_left.png”);
Texture right = assetManager.loadTexture(“Textures/Galaxies_right.png”);
rootNode.attachChild(SkyFactory.createSky(assetManager, left, right, front, back, top, bottom));[/java]
And now, the galaxy image quad occludes the skybox as well as the stars, and it seems like stars are occluded by having the quad, rather than the skybox, behind them:
So, depth on point sprites isn’t being calculated correctly, a BlendMode.Alpha quad is occluding stuff, and pointsprites won’t render if the only thing behind them is the skybox. I’m not entirely new to the theory behind rendering stuff but I’m less familiar with implementation, especially in JME.