Here's an example, because this might make it clearer. It also shows how to compensate for the fact that the GL screen's coordinate system starts at the bottom of the screen:
package com.threed.jpct.rendertargets;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.NPOTTexture;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;
public class RenderTargets extends Activity {
private GLSurfaceView mGLView;
private MyRenderer renderer = null;
private FrameBuffer fb = null;
private World world = null;
private World dummyWorld = null;
private NPOTTexture target1 = null;
private NPOTTexture target2 = null;
private Object3D cube = null;
private int fps = 0;
private Light sun = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(getApplication());
mGLView.setEGLContextClientVersion(2);
mGLView.setPreserveEGLContextOnPause(true);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
renderer = new MyRenderer();
mGLView.setRenderer(renderer);
setContentView(mGLView);
}
@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}
@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}
@Override
protected void onStop() {
super.onStop();
}
protected boolean isFullscreenOpaque() {
return true;
}
class MyRenderer implements GLSurfaceView.Renderer {
private long time = System.currentTimeMillis();
public MyRenderer() {
//
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
fb = new FrameBuffer(w, h); // OpenGL ES 2.0 constructor
world = new World();
world.setAmbientLight(20, 20, 20);
sun = new Light(world);
sun.setIntensity(250, 250, 250);
TextureManager.getInstance().addTexture("texture", new Texture(16, 16, RGBColor.GREEN));
cube = Primitives.getCube(10);
cube.calcTextureWrapSpherical();
cube.setTexture("texture");
cube.strip();
cube.build();
world.addObject(cube);
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(cube.getTransformedCenter());
SimpleVector sv = new SimpleVector();
sv.set(cube.getTransformedCenter());
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);
MemoryHelper.compact();
target1 = new NPOTTexture(w / 2, h, RGBColor.BLUE);
target2 = new NPOTTexture(w / 2, h, RGBColor.RED);
dummyWorld = new World();
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
public void onDrawFrame(GL10 gl) {
cube.rotateY(0.01f);
cube.rotateX(0.01f);
// Render into first target
fb.setRenderTarget(target1);
fb.clear(RGBColor.BLUE);
world.renderScene(fb);
world.draw(fb);
fb.display();
fb.removeRenderTarget();
// Render into second target
fb.setRenderTarget(target2);
fb.clear(RGBColor.RED);
world.renderScene(fb);
world.draw(fb);
fb.display();
fb.removeRenderTarget();
// jPCT-AE needs this to setup some stuff for correct blitting
dummyWorld.renderScene(fb);
dummyWorld.draw(fb);
// Blit both textures. Please note that the blitting is upside down
// (starting at the bottom with negative destination height, because
// OpenGL's coordinate system starts at the bottom. This compensates
// for that.
fb.blit(target1, 0, 0, 0, fb.getHeight(), target1.getWidth(), target1.getHeight(), fb.getWidth() / 2, -fb.getHeight(), -1, false);
fb.blit(target2, 0, 0, fb.getWidth() / 2, fb.getHeight(), target1.getWidth(), target1.getHeight(), fb.getWidth() / 2, -fb.getHeight(), -1, false);
fb.display();
if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}
}
}