Actually, changing the framebuffer while the application is running isn't fully supported. When using compiled objects, there might be problems to recover from this. However, if you don't use compiled objects (or no VBOs/display lists), it should actually work fine and in my test case, it does. And in no case, it should give you this strange flickering...
I'll post my simple test case here. It uses a way to resize the FrameBuffer instead of destroying and recreating it. That's the better way because it preserves the context and avoids crashes when disposing a framebuffer that can occur on some NVidia cards under Windows.
Please tell me how it works:
import java.awt.Color;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import com.threed.jpct.*;
import com.threed.jpct.util.Light;
public class SwitchTest
{
private static final long serialVersionUID = 1L;
private FrameBuffer fb = null;
private World world = null;
private Object3D plane = null;
private Object3D ramp = null;
private Object3D cube2 = null;
private Object3D sphere = null;
public SwitchTest()
{
//
}
private void initStuff()
{
fb = new FrameBuffer(640, 480, FrameBuffer.SAMPLINGMODE_NORMAL);
world = new World();
fb.disableRenderer(IRenderer.RENDERER_SOFTWARE);
fb.enableRenderer(IRenderer.RENDERER_OPENGL);
ramp = Primitives.getCube(20);
ramp.setAdditionalColor(Color.RED);
plane = Primitives.getPlane(20, 10);
plane.setAdditionalColor(Color.GREEN);
sphere = Primitives.getSphere(30);
sphere.setAdditionalColor(Color.CYAN);
sphere.translate(-50, 10, 50);
cube2 = Primitives.getCube(20);
cube2.setAdditionalColor(Color.ORANGE);
cube2.translate(60, -20, 60);
plane.rotateX((float) Math.PI / 2f);
ramp.rotateX((float) Math.PI / 2f);
plane.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
ramp.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
sphere.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
cube2.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
world.addObject(plane);
world.addObject(ramp);
world.addObject(sphere);
world.addObject(cube2);
Light light = new Light(world);
light.setPosition(new SimpleVector(0, -80, 0));
light.setIntensity(255, 130, 140);
light.setAttenuation(-1);
plane.compile();
ramp.compile();
sphere.compile();
cube2.compile();
world.setAmbientLight(10, 10, 10);
world.buildAllObjects();
}
private void doIt()
throws Exception
{
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 100);
cam.moveCamera(Camera.CAMERA_MOVEUP, 160);
cam.lookAt(plane.getTransformedCenter());
long s = System.currentTimeMillis();
boolean changed = false;
while (!Display.isCloseRequested())
{
if (System.currentTimeMillis() - s >= 2000 && !changed)
{
fb.resize(800, 600);
Display.setDisplayMode(findMode(800, 600, Config.glColorDepth, Config.glZBufferDepth));
changed = true;
}
fb.clear(Color.BLUE);
world.renderScene(fb);
world.draw(fb);
fb.update();
fb.display(null);
world.getCamera().rotateZ(0.01f);
Thread.sleep(10);
}
}
public static void main(String[] args)
throws Exception
{
SwitchTest cd = new SwitchTest();
cd.initStuff();
cd.doIt();
}
private DisplayMode findMode(int x, int y, int cbpp, int zbppm)
throws Exception
{
int mode = -1;
DisplayMode[] modes = Display.getAvailableDisplayModes();
String os = System.getProperty("os.name");
if (os != null && os.toLowerCase().indexOf("linux") != -1)
{
if (cbpp == 32)
{
cbpp = 24;
Logger.log("Running on Linux with a 32bit color setting...adjusting to 24bit instead!");
}
}
for (int i = 0; i < modes.length; i++)
{
if (modes[i].getWidth() == x && modes[i].getHeight() == y && modes[i].getBitsPerPixel() == cbpp
&& (Config.glRefresh == 0 || modes[i].getFrequency() == Config.glRefresh || !Config.glFullscreen))
{
mode = i;
break;
}
}
if (mode == -1)
{
for (int i = 0; i < modes.length; i++)
{
if (modes[i].getWidth() == x && modes[i].getHeight() == y && modes[i].getBitsPerPixel() >= cbpp
&& (modes[i].getFrequency() >= Config.glRefresh || !Config.glFullscreen))
{
mode = i;
break;
}
}
if (mode == -1)
{
for (int i = 0; i < modes.length; i++)
{
if (modes[i].getWidth() == x && modes[i].getHeight() == y)
{
mode = i;
break;
}
}
}
if (mode == -1)
{
return null;
}
}
return modes[mode];
}
}