SkyBox rendering

So i have been playing around a bit with cube cams. View ports and Render to texture stuff.

It mostly behaves the way i expect. Except if i access the cubemap on the first frame i get lots of artifacts. Like the skybox is lazy loaded or something. If i wait a frame everything is fine. However this feels very ugly.

Example code of the AppState:

 protected void initialize(Application arg0) {
		
	cubeMap = new TextureCubeMap(faceSize, faceSize, format);

	cubeCamera = new Camera(faceSize, faceSize);
	cubeCamera.setFrustumPerspective(90f, 1, 1, 100);

	cubePort = new ViewPort("cubeCam", cubeCamera);
	cubePort.setClearFlags(true, true, true);
	cubePort.attachScene(scene);

	cubeBuffer = new FrameBuffer(faceSize, faceSize, 1);
	cubeBuffer.setDepthBuffer(Format.Depth);
	cubePort.setOutputFrameBuffer(cubeBuffer);
}

public void render(RenderManager rm) {
    for (int side = 0; side < 6; side++) {
	cubeCamera.setAxes(axisX[side], axisY[side], axisZ[side]);
	cubeBuffer.resetObject();
	cubeBuffer.setDepthBuffer(Format.Depth);
	cubeBuffer.setColorTexture(cubeMap, TextureCubeMap.Face.values()[side]);
        cubePort.setOutputFrameBuffer(cubeBuffer);
	rm.renderViewPort(cubePort, 0.16f);
   }
}

In the simple App class

@Override
	public void simpleInitApp() {
		Box testBox = new Box(1, 1, 1);
		Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
		Geometry geo = new Geometry("box", testBox);
		geo.setMaterial(mat);
		mat.setColor("Color", ColorRGBA.Red);
		Node node = new Node();
		node.attachChild(geo);
		boxNode=node;
		rootNode.attachChild(node);

		Geometry pbrBox = geo.clone(false);
		Material pbrMat = assetManager.loadMaterial("Models/Tank/tank.j3m");
		pbrBox.setMaterial(pbrMat);
		Node pbrNode = new Node();
		pbrNode.setLocalTranslation(new Vector3f(1, 1, 1));
		pbrNode.attachChild(pbrBox);
		rootNode.attachChild(pbrNode);

		DirectionalLight dl = new DirectionalLight();
		dl.setDirection(new Vector3f(-1, -1, -1));
		rootNode.addLight(dl);

		sky = SkyFactory.createSky(assetManager, "milky.jpg", SkyFactory.EnvMapType.EquirectMap);
		 
		rootNode.attachChild(sky);

		ChaseCamera chaser = new ChaseCamera(cam, node, inputManager);
		chaser.setDragToRotate(true);
		chaser.setMinVerticalRotation(-FastMath.HALF_PI);
		chaser.setMaxDistance(100);
		chaser.setMinDistance(0.1f);
		chaser.setSmoothMotion(true);
		chaser.setRotationSensitivity(80);
		chaser.setZoomSensitivity(5);
		flyCam.setEnabled(false);
		
		camTester=new OctEnvCamera(rootNode,new Vector3f(5,0,0),256);
		stateManager.attach(camTester);
	}

	float rot=0;
	@Override
	public void simpleUpdate(float tpf) {
		frame++;
		rot+=tpf;
		//System.out.println("Update frame " + frame);
		
		if ( frame == 2) {
			sky.removeFromParent();
			TextureCubeMap cube=camTester.getCubeMap();
			sky=SkyFactory.createSky(assetManager, cube, SkyFactory.EnvMapType.CubeMap);
			rootNode.attachChild(sky);
			System.out.println("RemoveOldSky");
			
		}
		boxNode.setLocalRotation(new Quaternion(new float[] {0,rot,0}));

	}

if i use frame==1 i get the following:

I feel like i may be missing something. Since i am trying to do a few fancy things with viewports and stuff, i want to make sure i really understand what is going on.

Well if i understand what you do, you generate your skymap in the first frame, so it is not available there,

I want to do a lot more than a single thing in the first frame, use it , to do something else, then something else then finally we can start the main game loop. I don’t know if it should be an app state or some sort of scene processor.

Also shouldn’t app states go in order. The app state is finished. Also when i do RTT viewports this way its fine. Including on the first frame.

Also shouldn’t the texture then update after the first frame? while is does not.

Sorry this looks like the original scene is somehow not “validated”.

Don’t put stuff you want done once in the update, instead have it done in the init or use app.enqueue() which will be executed the following frame. Unless I’m mistaken states attached to the state manager will be initialized the following frame as well. A better way to force a specific order for your app to be initialized would be:

public static void main(String[] args) {
        MyApp app = new MyApp();
        app.start();
    }
    
    public MyApp(){
        super(new MyAppState(),
                new MyOtherAppState(),
                new MyGameState());
    }

This forces the appstates to be initialized in that order BEFORE SimpleInitApp() is called. Now you can put all your render code in an appstate, have it all initialized and ready to go before your game even gets to frame 1.

1 Like

But i need a full graphics context. I didn’t think i could do things like RenderManager.renderViewPortRaw(Spatial) for example in inits.

I could be wrong hence the posts.

enqueue() will execute the following frame, put it in your initialized and it should be executed frame 1 after the scene graph is built. I was able to call renderViewPortRaw() with no issue from simpleInitApp()

I had this issue too for PBR environment maps, and if you look at the TestPBRLighting the cube screen shot is taken in the update loop 2 frames after the start…
I never dug the issue… I guess everything is not yet properly initialized in the simpleinit.