Opengl-FrameBuffer Object Not Working on real device

Started by
2 comments, last by _WeirdCat_ 8 years, 5 months ago

I want to capture the rendered scene in my Android openGl App in A Texture Using FrameBuffer Object.

EveryThing is Fine in the emulator, But on Real Device the frameBuffer Object wouldn't work,

meaning Nothing Goes to my Texture, Here is the FBO Class (For Creating FrameBuffer and creating texture of it):


public class FBO {
    int [] fb, renderTex;
    int [] TextureBank;
    int top;
    int texW; 
    int texH;    
    int maxTextures;
    public FBO(int width,int height,int maxTextures){
        texW = width; 
        texH = height;
        fb = new int[1];
        renderTex= new int[1];
        top=-1;
        this.maxTextures = maxTextures;
        TextureBank = new int[maxTextures];
    }
    public void setup(GL10 gl){
        // generate
        ((GL11ExtensionPack)gl).glGenFramebuffersOES(1, fb, 0); 
        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glGenTextures(1, renderTex, 0);// generate texture
        gl.glBindTexture(GL10.GL_TEXTURE_2D, renderTex[0]);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D,
                GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D,
                GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
                GL10.GL_CLAMP_TO_EDGE); 
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
                GL10.GL_CLAMP_TO_EDGE);  
        //texBuffer = ByteBuffer.allocateDirect(buf.length*4).order(ByteOrder.nativeOrder()).asIntBuffer();
        //gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,GL10.GL_MODULATE);
        gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, texW, texH, 0, GL10.GL_RGBA, GL10.GL_FLOAT, null);
        gl.glDisable(GL10.GL_TEXTURE_2D); 
        if(top>=maxTextures-1){ 
            Log.e("OUT OF TEXTURE COUNTS", "OUT OF TEXTURE COUNTS Texture WIll Not Be added to Stack");
        }
        else{
        TextureBank [++top]= renderTex[0];
        Log.d("TOP= ", "" + top);
        }
    }  


    public boolean RenderStart(GL10 gl){
        // Bind the framebuffer
        ((GL11ExtensionPack)gl).glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, fb[0]);

        // specify texture as color attachment
        ((GL11ExtensionPack)gl).glFramebufferTexture2DOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, GL10.GL_TEXTURE_2D, renderTex[0], 0);

        int error = gl.glGetError();
        if (error != GL10.GL_NO_ERROR) {
            Log.d("err", "FIRST Background Load GLError: " + error+"      ");
        }
        int status = ((GL11ExtensionPack)gl).glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES);
        if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES)
        {
            Log.d("err", "SECOND Background Load GLError: " + status+"      ");;
            return true;
        }
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        return true;
    } 

    public void RenderEnd(GL10 gl){
        ((GL11ExtensionPack)gl).glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
        gl.glColor4f(1,1,1,1);
        gl.glDisable(GL10.GL_TEXTURE_2D);
    }

    public int getTexture(){
        return renderTex[0];
    }


} 

And here is my OnDrawFrame Method Which uses this FBO:


public synchronized void onDrawFrame(GL10 gl) {
mObserver.onDrawFrame();
gl.glClearColor(Color.red(mBackgroundColor) / 255f,
Color.green(mBackgroundColor) / 255f,
Color.blue(mBackgroundColor) / 255f,
Color.alpha(mBackgroundColor) / 255f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

gl.glLoadIdentity();




if(capture){

if(AttachTexture){
int h = gl.glGetError();
/**
Setup FBO
*/
frameBuffer.setup(gl);
if(h!=0){
Log.d("ERROR", "ERROR Happend"+h+"");
}
AttachTexture = false;
}

/**
Start Rendering In FBO
*/
frameBuffer.RenderStart(gl); 


if (USE_PERSPECTIVE_PROJECTION) { 
double x = mCurlMesh.GetMinX()* mCurlMesh.GetMinY();
gl.glTranslatef((float)(-1.000-mCurlMesh.GetMinX()),(float)(-1.000-mCurlMesh.GetMinY()), -6f);
}

gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();


GLU.gluOrtho2D(gl, (float)mCurlMesh.GetMinX(), (float)mCurlMesh.GetMaxX(),
(float)mCurlMesh.GetMinY(), (float)mCurlMesh.GetMaxY());
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glViewport(0, 0,texW,texH);
mCurlMesh.onDrawFrame(gl); 

/**
End Rendering In FBO
*/
frameBuffer.RenderEnd(gl); 

} 

//Reset Every Thing to Its Normal State
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, -1.1f,1.1f,-1.1f, 1.1f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glViewport(0, 0, mViewportWidth, mViewportHeight);



mCurlMesh.onDrawFrame(gl);
}

I Should mention that my Texture size IS 2^n:

frameBuffer = new FBO(1024, 1024, 8);

Advertisement

It's not necessarily the root of your problems, but why are you using GL10 with extensions?

GLES20 has been supported on pretty much all hardware in the last 5 years - I don't think I've run into a 1.1 or lower device in at least that long. And GLES20[/t]] natively supports framebuffer objects, no need to muck about with extensions.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

It's not necessarily the root of your problems, but why are you using GL10 with extensions?

GLES20 has been supported on pretty much all hardware in the last 5 years - I don't think I've run into a 1.1 or lower device in at least that long. And GLES20[/t]] natively supports framebuffer objects, no need to muck about with extensions.

well there is no problem with the OpenGL Version, i even changed the OpenGL Version Used in my App But still same Problem. what should I do?

that fbo initialization doesnt seem to be complete, you dont bind fbo after doing glgenframebuff.

heres my code for fbo initialization (explanation below code) for ogl es 2.0


void TwoDimTerraED::InitEditorFBO()
{
	glGenTextures(1, &EDITOR_TEX);
	glBindTexture(GL_TEXTURE_2D, EDITOR_TEX);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RENDER_BUFF_W, RENDER_BUFF_H, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);


	glGenFramebuffers(1, &EDITOR_FBO1);
	glGenRenderbuffers(1, &EDITOR_RBO1);
	glBindRenderbuffer(GL_RENDERBUFFER, EDITOR_RBO1);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, RENDER_BUFF_W, RENDER_BUFF_H);
	glBindFramebuffer(GL_FRAMEBUFFER, EDITOR_FBO1);
	glBindTexture(GL_TEXTURE_2D, EDITOR_TEX);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER,
	                          GL_DEPTH_ATTACHMENT,
	                          GL_RENDERBUFFER,
							  EDITOR_RBO1);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EDITOR_TEX, 0);


	glBindFramebuffer(GL_FRAMEBUFFER, 0);

}

ok so first of all i create the texture that fbo will be writing to (texture size of the fbo size, its really important to use power of two texture and width must be the same as height - i believe es 1.0 is strict with that as much as es 2.0)

then i create fbo (additionally i attach renderbuffer (because i want depth testing inside fbo)

then something liek that for use:


 glViewport(0,0, RENDER_BUFF_W, RENDER_BUFF_H);
	glBindFramebuffer(GL_FRAMEBUFFER, EDITOR_FBO1);


//set camera
//set all matrices
//clear depth and color buffer
//draw anything

glBindFramebuffer(GL_FRAMEBUFFER, 0);


if you want to use glReadPixels (to read from fbo) use it when FBO is bound

btw i did not find any thing that says what pixels you get from that fbo maybe you thing you should see it on screen and you see blank color (then

its caused by RenderEnd function)

also calling glFramebufferTexture2D each render loops is not quite what you should do define that in initialization

code looks like a mess.

You should consider switching to es 2.0 and stop using ffp.

but the main problem i see is that you are trying to create floating point texture, i am really confused that your program doesn't crash here.

gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, texW, texH, 0, GL10.GL_RGBA, GL10.GL_FLOAT, null);

for such old devices like es 1.0 and actually for all es 2.0 you should use GL_UNSIGNED_BYTE, i quite dont get what are you trying to fetch to float. (depth?) then forget it you dont have render buffer attached), also if you are not targeting es 3.0 forget about using floating point textures.

My solution for that is to store 32 bit float in each pixel (as a set of 4 unsigned chars) you try to store 4 32bit floats in one pixel. thats impossible for such devices.

side note: dont blame me for


        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

in fbo initialization

This topic is closed to new replies.

Advertisement