0

Ultimate goal is GPU image processing (color quantumization, pixel sorting, connected component analysis) using ping pong method with two textures attached to the same framebuffer.

I've looked at other threads, completed my textures, checked for errors, followed this tutorial and that tutorial, looked at the documentation, but nothing seems to work. I can render to the screen just fine, but I can render to the texture attached to the framebuffer.

I know the code for drawing to the quad works because I use the same for both types of rendering. I'm not getting errors with glCheckFramebufferStatus or glGetErrors, and eveything seems just as in the tutorials, expect I having created or attached a renderbuffer because I dont need depth or stencil data. So I'm at a loss. Any help would be great appreciated, so I can move on to figuring out the hard stuff.

Code for creating framebuffer and textures and checking for errors, in ImageRenderer class:

public static int createFBO()
{
    int[] fbo = new int[1];
    GLES30.glGenFramebuffers(1,fbo,0);
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fbo[0]);
        
    int error = GLES30.glGetError();
    if(error != GLES30.GL_NO_ERROR)
    {
        while (error !=GLES30.GL_NO_ERROR )
        {
            System.out.println(error);
            error = GLES30.glGetError();
        }
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
        return 0;
    }
    else
    {
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
        return fbo[0];
    }
}
    
public static int[] createFBOTextures(int framebuffer, int width, int height)
{
    //bind the framebuffer
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, framebuffer);
        
    int[] rt = new int[2];
    GLES30.glGenTextures(2, rt, 0);
    int[] DrawBuffers = {GLES30.GL_COLOR_ATTACHMENT0,GLES30.GL_COLOR_ATTACHMENT1};

    for (int i=0; i<2; i++)
    {
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, rt[i]);
        GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D,0,GLES30.GL_RGBA32F, width, height,0,GLES30.GL_RGBA, GLES30.GL_FLOAT, null);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR_MIPMAP_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
            // Attach each texture to colour attachement #i
        GLES30.glFramebufferTexture2D (GLES30.GL_FRAMEBUFFER, DrawBuffers[i], GLES30.GL_TEXTURE_2D, rt[i], 0);
    }
        
    if(check_framebuffer_errors())
        return null;
    else
        return rt;
    }
    
public static boolean check_framebuffer_errors()
{
    if(GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER) != GLES30.GL_FRAMEBUFFER_COMPLETE)
    {
            System.out.println(GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER));
        return true;
    }
    else
    {
        int error = GLES30.glGetError();
        if(error !=GLES30.GL_NO_ERROR )
        {
            while (error != GLES30.GL_NO_ERROR)
            {
                System.out.println(error);
                error = GLES30.glGetError();
            }
            return true;
        }
        else
            return false;
    }
}

All draw commands made from PixelCounter object, initialized like so:

public PixelCounter(Bitmap b)
{
    mWidth = b.getWidth();
    mHeight = b.getHeight();
            
    defineShape();
    ConversionData = ImageRenderer.createUBO(16+3);
    ImageRenderer.updateBuffer(toXYZ,0,ConversionData);
    ImageRenderer.updateBuffer(new float[]{0.95047f, 1.0f, 1.08883f},15,ConversionData);
    FBOHandle = ImageRenderer.createFBO();
    //create temporary texture to pass bitmap to float texture
    temptex = ImageRenderer.loadTexturefromBitmap(b);
    //create ping-pong textures
    FBOTextureHandles = ImageRenderer.createFBOTextures(FBOHandle, mWidth,mHeight);
            
    to_LAB = compile_shader(new String[]{default_vertex,to_lab});
    to_screen = compile_shader(new String[]{default_vertex, render_to_screen});
    to_texture = compile_shader(new String[]{default_vertex, render_to_texture});
}

Code for drawing to quad

//draw temptex to initial src texture
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER,FBOHandle);
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);
//GLES30.glViewport(0,0,mWidth,mHeight);
bindTexture(temptex, to_texture, "src");
GLES30.glDrawBuffers(1, new int[]{GLES30.GL_COLOR_ATTACHMENT0}, 0);    
simple_draw(to_texture);
        
//draw to screen
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER,0);
bindTexture(FBOTextureHandles[dest],to_screen, "src");
simple_draw(to_screen);

simple_draw function

private void simple_draw(int program)
{
    GLES30.glUseProgram(program);

    //get handle to vertex shader's position member
    mPositionHandle = GLES30.glGetAttribLocation(program, "position");

    //Add attribute array of vertices
        GLES30.glEnableVertexAttribArray(mPositionHandle);
        GLES30.glVertexAttribPointer(
            mPositionHandle, mPositionDataSize,
        GLES30.GL_FLOAT, false,
            mStrideBytes, vertexBuffer);

        GLES30.glDrawElements(
                GLES30.GL_TRIANGLES, drawOrder.length,
                GLES30.GL_UNSIGNED_SHORT, drawListBuffer);
    }

And my fragment shader for good measure:

private String render_to_texture =
"#version 300 es \n" +
"uniform sampler2D src;\n"+
"in vec4 coord;\n"+
"layout(location = 0) out vec4 dest;\n" +

"void main()\n"+
"{\n"+
    "vec2 size = vec2(textureSize(src,0));\n"+
    "ivec2 uv_coord = ivec2((coord.xy+vec2(1.0,1.0))/2.0*size);\n"+ 
    "dest = texelFetch(src,uv_coord,0);\n"+
"}";
deasmhumnha
  • 456
  • 4
  • 12

1 Answers1

0

Solved. Added glViewport(0,0,width,height) before rendering. Though I'm curious what the default is since width/height are retrieved from a photo taken with the camera of the phone running AIDE (so the dimensions should be the same as the GLSurfaceView).

EDIT: Also needed to change glDrawBuffers arguments to (2, new int[]{GL_NONE,COLOR_ATTACHMENT1},0) when drawing to second texture as destination.

deasmhumnha
  • 456
  • 4
  • 12