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"+
"}";