Created
December 4, 2013 07:27
-
-
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 …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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