I’m trying to add a number of partially transparent markers on the horizon between the main world and the sky, like this:
I can’t just make them part of the sky image because they move independently from each other every frame. They work fine as long as they aren’t near each other but when they are they z fight:
Now I thought I could fix this by explicitly setting the z order:
viewPort.getQueue().setGeometryComparator(RenderQueue.Bucket.Transparent, new TransparentComparator(){
@Override
public int compare(Geometry o1, Geometry o2) {
if(o1 instanceof ForcedOrderGeometry && o2 instanceof ForcedOrderGeometry){
ForcedOrderGeometry fog1 = (ForcedOrderGeometry)o1;
ForcedOrderGeometry fog2 = (ForcedOrderGeometry)o2;
return fog1.getOrder() - fog2.getOrder();
}else{
return super.compare(o1, o2);
}
}
});
But that doesn’t seem to be making a difference.
I’ve tried to create a self contained example, it doesn’t quite look the same but it looks equally wrong, without a custom geometry comparator:
With a custom geometry comparator (arguably worse):
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.renderer.queue.TransparentComparator;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.shape.Quad;
import java.util.Random;
public class Main extends SimpleApplication {
public static void main(String[] args) {
Main app = new Main();
app.start();
}
@Override
public void simpleInitApp() {
viewPort.getQueue().setGeometryComparator(RenderQueue.Bucket.Transparent, new TransparentComparator(){
@Override
public int compare(Geometry o1, Geometry o2) {
if(o1 instanceof ForcedOrderGeometry && o2 instanceof ForcedOrderGeometry){
ForcedOrderGeometry fog1 = (ForcedOrderGeometry)o1;
ForcedOrderGeometry fog2 = (ForcedOrderGeometry)o2;
return fog1.getOrder() - fog2.getOrder();
}else{
return super.compare(o1, o2);
}
}
});
for(int i=0;i<10; i++){
float angle = 0.05f * i;
Geometry geo = createGeometry(i);
float x = (500+i)*FastMath.sin(angle);
float z = (500+i)*FastMath.cos(angle);
this.rootNode.attachChild(geo);
geo.setLocalTranslation(x, 0, z);
geo.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
}
cam.setLocation(new Vector3f(0,200,0));
cam.lookAt(new Vector3f(0,0,500), Vector3f.UNIT_Y);
}
private Geometry createGeometry(int order){
Random rnd = new Random(order);
Mesh b = new Quad(100, 1000);
Geometry geom = new ForcedOrderGeometry("forced", b, order);
Material mat = new Material(assetManager,"Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", new ColorRGBA(rnd.nextFloat(), rnd.nextFloat(), rnd.nextFloat(), 1));
mat.setTexture("ColorMap", assetManager.loadTexture("Textures/horizonImage.png"));
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
geom.setQueueBucket(RenderQueue.Bucket.Transparent);
geom.setMaterial(mat);
return geom;
}
public static class ForcedOrderGeometry extends Geometry {
int order;
public ForcedOrderGeometry(String name, Mesh mesh, int order){
super(name,mesh);
this.order = order;
}
public int getOrder() {
return order;
}
}
}
I don’t really care about what the order is for these objects just as long as the order is consistent between frames and doesn’t z fight. What do I need to do to make some of the transparent items are always completely in front of others independent of the true z distance (I seem to need to make them quite far apart in real space to make them not z fight and that causes other issues.