I am about to switch from an AssetLinkNode to InstancedNode and I have a few questions first:
Do I have to check for opengl3.0 compatability in order to use the InstancedNode?
Will my code blow up if the video card is only opengl2.0 compatible?
Do I just create and instance of InstanedNode and create new Geometries with the same mesh instance on each and I will be able to set any material to each Geometry and pick up the speed increase?
Can an instance of InstancedNode contain several copied of say, two or more difrent meshes and still give me the speed increase I am looking for?
if (renderer.getCaps().contains(Caps.MeshInstancing)) {
// Use instancing
} else {
// Fallback
}
We avoided adding instancing for a long time because its a feature that requires hardware support beyond OpenGL 2.
Note that you can still use InstancedNode, but you just have to avoid calling the .instance() method if its not supported.
Yes the mesh instances have to be the same for instancing to work. Material instances also have to be the same for objects to be instanced together. This doesn’t mean instancing will break or anything, just that you won’t see any performance improvement if all objects are completely different.
No, you cannot use mesh copies, the instances have to be the same.
I converted them from blender to .j3o . and when calling this method :
((InstancedNode) instancedNodeJungle).instance();
I got this error :
SEVERE: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.IllegalStateException: You must set the 'UseInstancing' parameter to true on the material prior to adding it to InstancedNode
at com.jme3.scene.instancing.InstancedNode.addToInstancedGeometry(InstancedNode.java:199)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:261)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:268)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:268)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:268)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:268)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:268)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:268)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:268)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:268)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:268)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:268)
at com.jme3.scene.instancing.InstancedNode.instance(InstancedNode.java:274)
at mygame.Main.simpleInitApp(Main.java:48)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:227)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:211)
at java.lang.Thread.run(Thread.java:745)
so I created this method to add “UseInstancing” parameter to all materials in scene :
private void enableMaterialInstancing(Spatial jungle) {
SceneGraphVisitor v = new SceneGraphVisitor() {
@Override
public void visit(Spatial spatial) {
if (spatial instanceof Geometry) {
Material mat = ((Geometry) spatial).getMaterial();
mat.getMaterialDef().addMaterialParam(VarType.Boolean, "UseInstancing", true);
mat.setBoolean("UseInstancing", true);
}
}
};
jungle.depthFirstTraversal(v);
}