I am overlaying text on an image and then loading the image into a OpenGL texture. From there encoding the opengl surface to mp4 using MediaCodec.
Here is an example of an image I am loading into a texture then encoding to mp4.
But after encoding the OpenGl surface to mp4 using MediaCodec I have black artifacts around the text. Like so:
This is basically how I am loading bmp into a texture and displaying it.
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
//Also have tried this
//GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mWidth, mHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, ByteBuffer.wrap(frameData));
onDrawFrame(mInputSurface.textureHandle);
public void onDrawFrame(int textureHandle)
{
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
// Tell OpenGL to use this program when rendering.
GLES20.glUseProgram(mProgramHandle);
// Set program handles
mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "position");
mTextureCoordHandle = GLES20.glGetAttribLocation(mProgramHandle, "inputTextureCoordinate");
mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "videoFrame");
// Set the active texture unit to texture unit 0.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
// Bind the texture to this unit.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle);
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
GLES20.glUniform1i(mTextureUniformHandle, 0);
drawTriangle(mRectVertices, mRectTextureCoordinates);
}
/**
* Draws a triangle from the given vertex data.
*
* #param aTriangleBuffer The buffer containing the vertex data.
* #param aRectTextureCoordinates
*/
private void drawTriangle(final FloatBuffer aTriangleBuffer, FloatBuffer aRectTextureCoordinates)
{
// Pass in the position information
aTriangleBuffer.position(mPositionOffset);
GLES20.glVertexAttribPointer(mPositionHandle, 2, GLES20.GL_FLOAT, false,
0, aTriangleBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Pass in the color information
aRectTextureCoordinates.position(mPositionOffset);
GLES20.glVertexAttribPointer(mTextureCoordHandle, 2, GLES20.GL_FLOAT, false,
0,aRectTextureCoordinates);
GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
Any idea what could be causing this?
Edit:
#BDL
"Does your textures contain an alpha channel?"
The bitmap has an alpha channel. It is encoded as ARGB_8888.
But I have made sure that it is fully opaque with an alpha value of 255 for all pixels.
"Do you have blending enabled?"
I have tried enabling
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
Nothing changed
Edit 2:
I am setting the viewport to be the same size as the surface used to encode the video.
// Set the OpenGL viewport to the same size as the surface.
GLES20.glViewport(0, 0, width, height);
But then I tried doubling the width and height
// Set the OpenGL viewport to the same size as the surface.
GLES20.glViewport(0, 0, width*2, height*2);
And while only a quarter of the image is showing... there are no more artifacts.
Related
This is the code I'm using to render a Bitmap in Wikitude SDK class ArchitectView
// clear Screen and Depth Buffer, we have set the clear color as black.
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// get handle to vertex shader's vPosition member
int mPositionHandle = GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "vPosition");
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
// Get handle to texture coordinates location
int mTexCoordLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "a_texCoord" );
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray ( mTexCoordLoc );
// Prepare the texturecoordinates
GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
false,
0, uvBuffer);
// Get handle to shape's transformation matrix
int mtrxhandle = GLES20.glGetUniformLocation(riGraphicTools.sp_Image, "uMVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, m, 0);
// Get handle to textures locations
int mSamplerLoc = GLES20.glGetUniformLocation (riGraphicTools.sp_Image, "s_texture" );
// Set the sampler texture unit to 0, where we have saved the texture.
GLES20.glUniform1i ( mSamplerLoc, 0);
// Draw the triangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
And this is how image being setup:
public void SetupImage(Bitmap bmp)
{
// Create our UV coordinates.
uvs = new float[] {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
// The texture buffer
ByteBuffer bb = ByteBuffer.allocateDirect(uvs.length * 4);
bb.order(ByteOrder.nativeOrder());
uvBuffer = bb.asFloatBuffer();
uvBuffer.put(uvs);
uvBuffer.position(0);
// Generate Textures, if more needed, alter these numbers.
int[] texturenames = new int[1];
GLES20.glGenTextures(1, texturenames, 0);
// Bind texture to texturename
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
// We are done using the bitmap so we should recycle it.
bmp.recycle();
}
The problem is I can't render texture inside ArchitectView, but rendering it without any issues on default android's GLSurfaceView.
You're not supposed to write any OpenGL code inside the ArchitectView. If you need some custom drawing, please write a plugin for the Wikitude SDK and use the startRender/endRender method to draw your OpenGL content (Only these two methods guarantee a valid OpenGL context bound).
in my android App, i have a Frame Buffer Object that takes me the rendered Scene As a texture.
the app is an Origami game and user can fold a paper freely:
in every Fold, the current rendered scene saves to a texture using fbo and then i redraw the paper with new coordinates with new texture attached to it, to seem like folded paper. and this way the user can fold the paper as many time as he wants.
I want in every frame Check the rendered scene, to determinate does the user riches to the final shape (assume that i have the final shape in a 2d-array with 0 and 1 filled, 0 for transparency and 1 for colored pixels)
what i want, is to some How, Convert this Texture to A 2d-Array filled with 0 and 1,
0 for transparency pixel, and 1 for Colored pixel of texture.
i need this to then compare this result with a previously Known 2d-Array to determinate if the texture is the shape i want or not.
is it possible to save the texture data to an array?
i cant use glreadPixels because it is so heavy and its not possible to call it every frame.
here is the FBO class (i want to have renderTex[0] as array):
public class FBO {
int [] fb, renderTex;
int texW;
int texH;
public FBO(int width,int height){
texW = width;
texH = height;
fb = new int[1];
renderTex= new int[1];
}
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_UNSIGNED_BYTE, null);
gl.glDisable(GL10.GL_TEXTURE_2D);
}
public boolean RenderStart(GL10 gl){
Log.d("TextureAndFBO", ""+renderTex[0] + " And " +fb[0]);
// 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.0f,1.0f,1.0f,1.0f);
gl.glDisable(GL10.GL_TEXTURE_2D);
}
public int getTexture(){
return renderTex[0];
}
public int getFBO(){
return fb[0];
}
}
If you are using openGL ES 3.0 and later then pbo would be a good solution. But I think you can use EGLImage. Because this only needs OpenGL ES 1.1 or 2.0.
The function to create an EGLImageKHR is:
EGLImageKHR eglCreateImageKHR(EGLDisplay dpy,
EGLContext ctx,
EGLenum target,
EGLClientBuffer buffer,
const EGLint *attrib_list)
To allocate an ANativeWindowBuffer, Android has a simple wrapper called GraphicBuffer:
GraphicBuffer *window = new GraphicBuffer(width, height, PIXEL_FORMAT_RGBA_8888, GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE);
struct ANativeWindowBuffer *buffer = window->getNativeBuffer();
EGLImageKHR *image = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, *attribs);
to read pixels from an FBO use one of these two methods below:
void EGLImageTargetTexture2DOES(enum target, eglImageOES image)
void EGLImageTargetRenderbufferStorageOES(enum target, eglImageOES image)
These two methods will esablish all the properties of the target GL_TEXTURE_2D or GL_RENDERBUFFER
uint8_t *ptr;
glBindTexture(GL_TEXTURE_2D, texture_id);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
window->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &ptr);
memcpy(pixels, ptr, width * height * 4);
window->unlock();
To accomplish what you want, you need to use a PBO (Pixel Buffer Object): You can map it to an array to read it if it were a regular array.
OpenGL ARB_pixel_buffer_object extension is very close to
ARB_vertex_buffer_object. It simply expands ARB_vertex_buffer_object
extension in order to store not only vertex data but also pixel data
into the buffer objects. This buffer object storing pixel data is
called Pixel Buffer Object (PBO). ARB_pixel_buffer_object extension
borrows all VBO framework and APIs, plus, adds 2 additional "target"
tokens. These tokens assist the PBO memory manger (OpenGL driver) to
determine the best location of the buffer object; system memory,
shared memory or video memory. Also, the target tokens clearly specify
that the bound PBO will be used in one of 2 different operations;
GL_PIXEL_PACK_BUFFER_ARB to transfer pixel data to a PBO, or
GL_PIXEL_UNPACK_BUFFER_ARB to transfer pixel data from PBO.
It can be created similiar to other buffer objects:
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, size, 0, GL_DYNAMIC_READ);
Then you can read from an FBO (or a texture) easily:
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
GLubyte *array = (GLubyte*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, size, GL_MAP_READ_BIT);
// TODO: Do your checking of the shape inside of this 'array' pointer or copy it somewhere using memcpy()
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
Here GL_COLOR_ATTACHMENT0 is used as input - see the specification of glReadBuffer for further details how to specify front or backbuffer to be used.
So I'm able to display 1 texture at a time but I have a problem with displaying more textures. The render function is called for every texture separately (tex_nr), not sure if that's a good approach. Here's the rendering code:
private void Render(float[] m, int tex_nr) {
// Set our shaderprogram to image shader
GLES20.glUseProgram(riGraphicTools.sp_Image);
// clear Screen and Depth Buffer, we have set the clear color as black.
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// get handle to vertex shader's vPosition member
int mPositionHandle = GLES20.glGetAttribLocation(riGraphicTools.sp_SolidColor, "vPosition");
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
// Get handle to texture coordinates location
int mTexCoordLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image,
"a_texCoord" );
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray ( mTexCoordLoc );
// Prepare the texturecoordinates
GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
false,
0, uvBuffer);
// Get handle to shape's transformation matrix
int mtrxhandle = GLES20.glGetUniformLocation(riGraphicTools.sp_Image,
"uMVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, m, 0);
// Get handle to textures locations
int mSamplerLoc = GLES20.glGetUniformLocation (riGraphicTools.sp_Image,
"s_texture" );
// Set the sampler texture unit to where we have saved the texture.
GLES20.glUniform1i ( mSamplerLoc, tex_nr);
// Draw the triangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
}
And here the loading textures code:
texturenames = new int[GameObject.spritePaths.size()];
GLES20.glGenTextures(GameObject.spritePaths.size(), texturenames, 0);
for(int i = 0; i < GameObject.spritePaths.size(); i++)
{
// Retrieve our image from resources.
int id = mContext.getResources().getIdentifier(GameObject.spritePaths.get(i), null, mContext.getPackageName());
// Temporary create a bitmap
Bitmap bmp = BitmapFactory.decodeResource(mContext.getResources(), id);
// Bind texture to texturename
GLES20.glActiveTexture(GLES20.GL_TEXTURE0+i);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[i]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
// We are done using the bitmap so we should recycle it.
bmp.recycle();
}
As a result of this code, only the last loaded texture is displayed and I have no idea why the former ones do not show up. I would be very grateful for any clues!
edit:
Actually, I have just found out that I can display all of the textures that I loaded but only 1 at a time. So I guess that the problem isn't connected with loading? It looks as if each consecutive Render call(my function) prevented the drawing in the previous call...
You have a call to glClear() in your Render() method:
// clear Screen and Depth Buffer, we have set the clear color as black.
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
This does pretty much what the name suggests, and what's also captured in your comment: It clears all rendering that has been done so far. So if you call the Render() method multiple times, only the rendering from the last call will be visible.
If you want to invoke Render() multiple times for the same frame, you will need to take it out of Render(), and call it only once at the start of rendering the frame.
There's another thing in your code that looks slightly suspicious:
int mPositionHandle = GLES20.glGetAttribLocation(riGraphicTools.sp_SolidColor, "vPosition");
....
int mTexCoordLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "a_texCoord");
Unless sp_SolidColor and sp_Image have the same value, you're querying attribute locations from two different shader programs. Since sp_Image is the program you are using, you should pass it in as the first parameter for both these calls.
I've posted my drawing method which is called each frame.
I change the vertices each frame to move the object (which is basically a sprite/textured quad).
As you can see I was initially creating an array each frame, but I have changed this now and I create the array initially and just update it every frame, however I'm wondering if I can do anything more to improve the efficiency? (Although I'm getting about 90fps the sprite does not move smoothly all the time, every now and then it just pauses for a split second). I can't see garbage collector running but I'm guessing it's due to allocation).
As I add more sprites/quads the jerkiness gets worse, but event at 100+ quads, although the smoothness has all but gone, my frame rate is still around 60fps so I can't understand what is slowing this down?
I've also added a screencap from Allocation Tracker
Any help would be appreciated.
public void drawTest(float x, float y, float[] mvpMatrix){
//Convert Co-ordinates
//Left
xPlotLeft = (-MyGLRenderer.ratio)+((x)*MyGLRenderer.coordStepAmountWidth);
//Top
yPlotTop = +1-((y)*MyGLRenderer.coordStepAmountHeight);
//Right
xPlotRight = xPlotLeft+((quadWidth)*MyGLRenderer.coordStepAmountWidth);
//Bottom
yPlotBottom = yPlotTop-((quadHeight)*MyGLRenderer.coordStepAmountHeight);
// Following has been changed as per below. I am now declaring the array initially and just updating it every frame.
// float[] vertices = {
//Top Left
// xPlotLeft,yPlotTop,0, 0,0,
//Top Right
// xPlotRight,yPlotTop,0, 1,0,
//Bottom Left
// xPlotLeft,yPlotBottom,0, 0,1,
//Bottom Right
// xPlotRight,yPlotBottom,0, 1,1
// };
vertices[0]=xPlotLeft;
vertices[1]=yPlotTop;
vertices[2]=0;
vertices[3]=0;
vertices[4]=0;
vertices[5]=xPlotRight;
vertices[6]=yPlotTop;
vertices[7]=0;
vertices[8]=1;
vertices[9]=0;
vertices[10]=xPlotLeft;
vertices[11]=yPlotBottom;
vertices[12]=0;
vertices[13]=0;
vertices[14]=1;
vertices[15]=xPlotRight;
vertices[16]=yPlotBottom;
vertices[17]=0;
vertices[18]=1;
vertices[19]=1;
vertexBuf = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuf.put(vertices).position(0);
//GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
//Bind texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texID);
//Use program
GLES20.glUseProgram(iProgId);
// Combine the rotation matrix with the projection and camera view
Matrix.multiplyMM(mvpMatrix2, 0, mvpMatrix, 0, mRotationMatrix, 0);
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(iProgId, "uMVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix2, 0);
//Set starting position for vertices (0 for position)
vertexBuf.position(0);
//Specify attributes for vertex
GLES20.glVertexAttribPointer(iPosition, 3, GLES20.GL_FLOAT, false, 5 * 4, vertexBuf);
//Enable attribute for position
GLES20.glEnableVertexAttribArray(iPosition);
//Set starting position for vertices (3 for texture)
vertexBuf.position(3);
//Specify attributes for vertex
GLES20.glVertexAttribPointer(iTexCoords, 2, GLES20.GL_FLOAT, false, 5 * 4, vertexBuf);
//Enable attribute for texture
GLES20.glEnableVertexAttribArray(iTexCoords);
//Enable Alpha blending and set blending function
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
//Draw
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
//Disable Alpha blending
GLES20.glDisable(GLES20.GL_BLEND);
}
ByteBuffer.allocateDirect() allocates a new buffer in memory every frame, you can create an initial buffer and overwrite the contents instead. Just use rewind() or position(0) before put().
To improve matters further, use a VBO (vertex buffer object, there are many tutorials online, and several questions on SO on this topic) and glBufferSubData to update the buffer.
I am very new to OpenGL, and I am trying to create a 2 pass shader. Basically, it has two frame buffers and two shader programs. It runs the first pass as usual, and then I need to take the resulting texture and pass it as an input to the second shader. How is this done? I cannot seem to see how you take a resulting texture and use it as an input to the next texture?
Here is some code: This code assumes I have setup the second filter program, and some attributes and uniforms in the program correctly
#Override
public void onDraw(final int textureId, final FloatBuffer cubeBuffer,final FloatBuffer textureBuffer){
//this draws the first pass (this is tested and working)
super.onDraw(textureId, cubeBuffer, textureBuffer);
//change the program
GLES20.glUseProgram(secondFilterProgram);
//clear the old colors
GLES20.glClearColor(0, 0, 0, 1);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glActiveTexture(GLES20.GL_TEXTURE3); //change the texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, secondFilterOutputTexture[0]);
GLES20.glUniform1i(secondFilterInputTextureUniform, 3);
cubeBuffer.position(0);
GLES20.glVertexAttribPointer(secondFilterPositionAttribute, 2, GLES20.GL_FLOAT, false, 0, cubeBuffer);
GLES20.glEnableVertexAttribArray(secondFilterPositionAttribute);
textureBuffer.position(0);
GLES20.glVertexAttribPointer(secondFilterTextureCoordinateAttribute, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
GLES20.glEnableVertexAttribArray(secondFilterTextureCoordinateAttribute); //same as line from init
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glDisableVertexAttribArray(secondFilterPositionAttribute);
GLES20.glDisableVertexAttribArray(secondFilterTextureCoordinateAttribute);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
}
I feel like I am missing a piece of the puzzle here. Again, I am very new to OpenGL, so any help, even conceptually is appreciated
What you want to achieve is called Render to Texture
A small tutorial how to do this with android can be found here:
http://blog.shayanjaved.com/2011/05/13/android-opengl-es-2-0-render-to-texture/