Skip to content

Instantly share code, notes, and snippets.

@acgourley
Created December 4, 2013 07:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save acgourley/7783624 to your computer and use it in GitHub Desktop.
Save acgourley/7783624 to your computer and use it in GitHub Desktop.
A gist to show off my problematic FBO copy code. The copy method creates a dynamic texture and then tries to copy it to the destination texture. The result is always that the destination becomes entirely filled with whatever pixel is at texture coordinate (0, 0) on the input texture. This code runs fine without GL errors of any kind on a Galaxy …
public void UpdateTexture(float value) {
checkGlError("pre-UpdateTexture");
// Save the current state
IntBuffer previousFBO = IntBuffer.allocate(1);
IntBuffer previousRenderBuffer = IntBuffer.allocate(1);
IntBuffer previous_program = IntBuffer.allocate(1);
GLES20.glGetIntegerv(GLES20.GL_FRAMEBUFFER_BINDING, previousFBO);
GLES20.glGetIntegerv(GLES20.GL_RENDERBUFFER_BINDING,
previousRenderBuffer);
GLES20.glGetIntegerv(GLES20.GL_CURRENT_PROGRAM, previous_program);
// Need to set up the FBO first
if (mFrameBuffer <= 0) {
Log.w(TAG, "ERROR FBO not created");
return;
}
// Generate a new image and update source texture
this.generateImage(value);
// Set up our FBO
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer);
checkGlError("glBindFramebuffer");
GLES20.glViewport(0, 0, TEXTURE_WIDTH*4, TEXTURE_HEIGHT*4);
checkGlError("glViewport");
GLES20.glDisable(GLES20.GL_BLEND);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthMask(false);
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GLES20.glPolygonOffset(0.0f, 0.0f);
GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
checkGlError("fbo setup");
// Load the shaders if we have not done so
if (mProgram <= 0) {
createProgram();
Log.i(TAG, "InitializeTexture created program with ID: " + mProgram);
if (mProgram <= 0)
Log.e(TAG, "Failed to initialize shaders!");
}
// Set up the program
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glUniform1i(mUniforms[UNIFORM_TEXTURE], 0);
checkGlError("glUniform1i");
// clear the scene
GLES20.glClearColor(0.0f,0.0f, 0.1f, 1.0f);
checkGlError("glClearColor");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Bind out source texture
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
checkGlError("glActiveTexture");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mSourceTexture);
checkGlError("glBindTexture");
GLES20.glFrontFace( GLES20.GL_CW );
// Our object to render
ByteBuffer imageVerticesBB = ByteBuffer.allocateDirect(8 * 4);
imageVerticesBB.order(ByteOrder.nativeOrder());
FloatBuffer imageVertices = imageVerticesBB.asFloatBuffer();
imageVertices.put(new float[]{
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f}
);
imageVertices.position(0);
// The object's texture coordinates
ByteBuffer textureCoordinatesBB = ByteBuffer.allocateDirect(8 * 4);
imageVerticesBB.order(ByteOrder.nativeOrder());
FloatBuffer textureCoordinates = textureCoordinatesBB.asFloatBuffer();
textureCoordinates.put(new float[]{
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f}
);
textureCoordinates.position(0);
// Update attribute values.
GLES20.glEnableVertexAttribArray(ATTRIB_VERTEX);
GLES20.glVertexAttribPointer(ATTRIB_VERTEX, 2, GLES20.GL_FLOAT, false, 0, imageVertices);
GLES20.glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
GLES20.glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GLES20.GL_FLOAT, false, 0, textureCoordinates);
// Draw the quad
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
// Reset everything
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
// GLES20.glBindVertexArrayOES(0); //not universally supported, may need
// to do some device-by-device logic here. see
// http://stackoverflow.com/questions/14406829/undefined-reference-glbindvertexarrayoes-glgenvertexarraysoes-gldeletevertexarra
GLES20.glDisableVertexAttribArray(ATTRIB_VERTEX);
GLES20.glDisableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
// Restore state
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, previousFBO.get(0));
GLES20.glClear(0);//I've heard qualcomm devices need this after a glBindFramebuffer
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, previousRenderBuffer.get(0));
GLES20.glUseProgram(previous_program.get(0));
checkGlError("end update");
}
private boolean createFBO() {
if (mUnityTexture <= 0) {
Log.w(TAG, "Unity Texture not set");
return false;
}
// Create a new framebuffer if needed
if (mFrameBuffer <= 0) {
IntBuffer frameBuffers = IntBuffer.allocate(1);
GLES20.glGenFramebuffers(1, frameBuffers);
mFrameBuffer = frameBuffers.get(0);
checkGlError("glBindFramebuffer");
}
// bind FBO
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer);
checkGlError("glBindFramebuffer");
GLES20.glClear(0);//I've heard qualcomm devices need this after a glBindFramebuffer
checkGlError("glClear");
// bind the output texture and attach it
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mUnityTexture);
checkGlError("glBindTexture");
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GLES20.GL_RGBA,
GLES20.GL_UNSIGNED_BYTE, null);
checkGlError("glTexImage2D");
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
checkGlError("glTexParameteri");
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, 0, 0);
checkGlError("glFramebufferTexture2D");
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D,
mUnityTexture, 0);
checkGlError("glFramebufferTexture2D");
// Did it work?
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
Log.w(TAG, "ERROR: UNITY PLUGIN CANNOT MAKE VALID FBO ATTACHMENT FROM UNITY TEXTURE ID");
return false;
}
checkGlError("glCheckFramebufferStatus");
return true;
}
String vShaderStr = "attribute vec4 position; \n"
+ "attribute mediump vec4 textureCoordinate; \n"
+ "varying mediump vec2 coordinate; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = position; \n"
+ " coordinate = textureCoordinate.xy; \n"
+ "}";
String fShaderStr = "varying highp vec2 coordinate; \n"
+ "uniform sampler2D texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D(texture, coordinate); \n"
+ "}";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment