I’m developing an application at my day job that offscreen renders maps using a JME offscreen viewport. I have the offscreen camera/viewport/framebuffer set up and working (that’s no problem), but when I tried to enable multiple samples on the framebuffer then I get the following:
It should look like this, but hopefully with the mostly horizontal-ish green line looking nicely antialiased:
Here’s the class that handles the offscreen rendering:
public class TileRenderer extends BaseAppState {
private Application app;
private Node mapRoot;
private ViewPort viewport;
private Camera cam;
private FrameBuffer buff;
private Texture2D tex;
public TileRenderer(){
mapRoot = new Node("Map Root");
tex = new Texture2D(512, 512, 1, Image.Format.RGBA8);
tex.setMinFilter(Texture.MinFilter.Trilinear);
tex.setMagFilter(Texture.MagFilter.Bilinear);
}
@Override
public void initialize(Application app) {
this.app = app;
cam = new Camera(512, 512);
// map textures should be parallel projected
cam.setParallelProjection(true);
// TODO - adjust frustum with zoom level
cam.setFrustum(-1000, 1000, -512, 512, 512, -512);
// on X,Y axes, small Z distance
cam.setLocation(new Vector3f(0, 0, 50f));
cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
viewport = app.getRenderManager().createPreView("mapViewport", cam);
viewport.setClearColor(true);
viewport.setBackgroundColor(ColorRGBA.White);
buff = new FrameBuffer(512, 512, 1);
// Enable color texture only. We don't need depth
// to render map tiles
buff.setColorTexture(tex);
viewport.setOutputFrameBuffer(buff);
}
public Texture2D getTile(){
return tex;
}
@Override
protected void cleanup(Application app) {
app.getRenderer().deleteFrameBuffer(buff);
}
@Override
protected void onEnable() {
Line line = new Line(Vector3f.ZERO, new Vector3f(0f, 256f, 0f));
Geometry lineGeom = new Geometry();
lineGeom.setMesh(line);
Material lineMat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
lineMat.setColor("Color", ColorRGBA.Green);
lineMat.getAdditionalRenderState().setLineWidth(1.0f);
lineGeom.setMaterial(lineMat);
mapRoot.attachChild(lineGeom);
line = new Line(Vector3f.ZERO, new Vector3f(474f, 6f, 0f));
lineGeom = new Geometry();
lineGeom.setMesh(line);
lineGeom.setMaterial(lineMat);
mapRoot.attachChild(lineGeom);
viewport.attachScene(mapRoot);
}
@Override
public void update(float tpf){
mapRoot.updateLogicalState(tpf);
mapRoot.updateGeometricState();
}
@Override
protected void onDisable() {
mapRoot.detachAllChildren();
viewport.detachScene(mapRoot);
}
}
This class, as posted, correctly renders the (non-antialiased) result in the second screenshot. If you change the texture and framebuffer creation to:
tex = new Texture2D(512, 512, 2, Image.Format.RGBA8);
and
buff = new FrameBuffer(512, 512, 2);
respectively, it produces the result in the first screenshot.
Here’s my main class:
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.jme3.system.AppSettings;
public class TestTileRenderer extends SimpleApplication {
private TileRenderer mapper;
public static void main(String[] args){
TestTileRenderer mapper = new TestTileRenderer();
// enable antialiasing by default, and default
// to a reasonably large resolution
AppSettings settings = new AppSettings(true);
settings.setSamples(4);
settings.setResolution(1280, 960);
mapper.setSettings(settings);
mapper.start();
}
@Override
public void simpleInitApp() {
// set up the mapper
mapper = new TileRenderer();
stateManager.attach(mapper);
Quad testQuad = new Quad(10, 10);
Geometry testGeo = new Geometry("Test Quad");
testGeo.setMesh(testQuad);
Material testMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
testMat.setTexture("ColorMap", mapper.getTile());
testGeo.setMaterial(testMat);
rootNode.attachChild(testGeo);
testGeo.setLocalTranslation(-5f, -5f, -5f);
}
}
Have I committed a no-no in my offscreen rendering setup, or is this a bug?