I develop video app on Android and use OpenGL for render and filtering video from camera via shaders. One of my shaders use two textures - one is live frame from camera and another is the previous render pass result. So I need to render picture twice - to screen for preview and to separate Texture for next render pass. To achieve it I use Frame Buffer object. Here is my code:
For init frame buffer:
private void initPredrawBuffer() {
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
prevBuffer = new int[1];
GLES20.glGenFramebuffers(1, prevBuffer, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, prevBuffer[0]);
prevTexture = new int[1];
GLES20.glGenTextures(1, prevTexture, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, prevTexture[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mFrameWidth, mFrameHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, prevTexture[0], 0);
int[] depthRenderbuffers = new int[1];
GLES20.glGenRenderbuffers(1, depthRenderbuffers, 0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRenderbuffers[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, mFrameWidth, mFrameHeight);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRenderbuffers[0]);
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
throw new RuntimeException("Incomplete buffer");
}
}
and for render:
private void draw(boolean offScreen, float[] mvpMatrix, FloatBuffer vertexBuffer, int firstVertex,
int vertexCount, int coordsPerVertex, int vertexStride,
float[] texMatrix, FloatBuffer texBuffer, int textureId, int texStride) {
GlUtil.checkGlError("draw start");
if (offScreen)
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, prevBuffer[0]);
else
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
// Select the program.
GLES20.glUseProgram(firstFrame && firstFrameProgram > 0 ? firstFrameProgram : mProgramHandle);
GlUtil.checkGlError("glUseProgram");
// Set the texture.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
// Copy the model / view / projection matrix over.
GLES20.glUniformMatrix4fv(muMVPMatrixLoc, 1, false, mvpMatrix, 0);
GlUtil.checkGlError("glUniformMatrix4fv");
// Copy the texture transformation matrix over.
GLES20.glUniformMatrix4fv(muTexMatrixLoc, 1, false, texMatrix, 0);
GlUtil.checkGlError("glUniformMatrix4fv");
// Enable the "aPosition" vertex attribute.
GLES20.glEnableVertexAttribArray(maPositionLoc);
GlUtil.checkGlError("glEnableVertexAttribArray");
// Connect vertexBuffer to "aPosition".
GLES20.glVertexAttribPointer(maPositionLoc, coordsPerVertex,
GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
GlUtil.checkGlError("glVertexAttribPointer");
// Enable the "aTextureCoord" vertex attribute.
GLES20.glEnableVertexAttribArray(maTextureCoordLoc);
GlUtil.checkGlError("glEnableVertexAttribArray");
// Connect texBuffer to "aTextureCoord".
GLES20.glVertexAttribPointer(maTextureCoordLoc, 2,
GLES20.GL_FLOAT, false, texStride, texBuffer);
GlUtil.checkGlError("glVertexAttribPointer");
// Setting Light Trails filter params
if (mProgramType == ProgramType.TEXTURE_LIGHT_TRAILS && !firstFrame) {
GLES20.glUniform1i(muTextureNew, 0);
GlUtil.checkGlError("glUniform1i muTextureNew");
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GlUtil.checkGlError("temp glActiveTexture");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, prevTexture[0]);
GlUtil.checkGlError("temp glBindTexture");
GLES20.glUniform1i(muTexturePrev, 1);
GlUtil.checkGlError("glUniform1i muTexturePrev");
GLES20.glUniform1f(muLightTrailsExposure, lightTrailsKernel[0]);
GlUtil.checkGlError("glUniform1f muLightTrailsExposure");
GLES20.glUniform1f(muLightTrailsEcho, lightTrailsKernel[1]);
GlUtil.checkGlError("glUniform1f muLightTrailsEcho");
GLES20.glUniform1f(muLightTrailsLimit, lightTrailsKernel[2]);
GlUtil.checkGlError("glUniform1f muLightTrailsLimit");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GlUtil.checkGlError("temp glActiveTexture");
}
// Draw the rect.
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, firstVertex, vertexCount);
GlUtil.checkGlError("glDrawArrays");
GLES20.glFinish();
}
The problem is that render to frame buffer not working, and glReadPixels always return an empty array. Render to screen works fine.
Related
I am new to OpenGL, work on Android. Found good code example in Web with possibility to record everything. But I found one big problem: depth test doesn't work, so in my models all faces that opposite to camera are lighted even if they are behind another faces:
I think some mistakes could be in this part of code:
/**
* Prepares the off-screen framebuffer.
*/
private void prepareFramebuffer(int width, int height) {
GlUtil.checkGlError("prepareFramebuffer start");
int[] values = new int[1];
// Create a texture object and bind it. This will be the color buffer.
GLES20.glGenTextures(1, values, 0);
GlUtil.checkGlError("glGenTextures");
mOffscreenTexture = values[0]; // expected > 0
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mOffscreenTexture);
GlUtil.checkGlError("glBindTexture " + mOffscreenTexture);
// Create texture storage.
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0,
GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
// Set parameters. We're probably using non-power-of-two dimensions, so
// some values may not be available for use.
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE);
GlUtil.checkGlError("glTexParameter");
// Create framebuffer object and bind it.
GLES20.glGenFramebuffers(1, values, 0);
GlUtil.checkGlError("glGenFramebuffers");
mFramebuffer = values[0]; // expected > 0
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFramebuffer);
GlUtil.checkGlError("glBindFramebuffer " + mFramebuffer);
// Create a depth buffer and bind it.
GLES20.glGenRenderbuffers(1, values, 0);
GlUtil.checkGlError("glGenRenderbuffers");
mDepthBuffer = values[0]; // expected > 0
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, mDepthBuffer);
GlUtil.checkGlError("glBindRenderbuffer " + mDepthBuffer);
// Allocate storage for the depth buffer.
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16,
width, height);
GlUtil.checkGlError("glRenderbufferStorage");
// Attach the depth buffer and the texture (color buffer) to the framebuffer object.
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
GLES20.GL_RENDERBUFFER, mDepthBuffer);
GlUtil.checkGlError("glFramebufferRenderbuffer");
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, mOffscreenTexture, 0);
GlUtil.checkGlError("glFramebufferTexture2D");
// See if GLES is happy with all this.
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
// throw new RuntimeException("Framebuffer not complete, status=" + status);
}
// Switch back to the default framebuffer.
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GlUtil.checkGlError("prepareFramebuffer done");
}
Another important things that I have already done:
/**
* Prepares window surface and GL state.
*/
private void prepareGl(Surface surface) {
Log.d(TAG, "prepareGl");
EglCore.logCurrent("before creating");
GlUtil.checkGlError("debug");
if (mWindowSurface == null)
mWindowSurface = new WindowSurface(mEglCore, surface, false);
mWindowSurface.makeCurrent();
EglCore.logCurrent("after creation");
glClearColor(0f, 0f, 0f, 1f); //glClearColor(0.15f, 0.15f, 0.15f, 1f);
GlUtil.checkGlError("debug");
glEnable(GL_DEPTH_TEST);
GlUtil.checkGlError("debug");
glEnable(GL_CULL_FACE);
GlUtil.checkGlError("debug");
glCullFace(GL_BACK);
GlUtil.checkGlError("debug");
glShadeModel(GL_SMOOTH);
GlUtil.checkGlError("debug");
glEnable(GL_BLEND);
GlUtil.checkGlError("debug");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
What am I doing wrong? Where can be the mistake?
Add onDraw code:
private void draw() {
GlUtil.checkGlError("draw start");
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthFunc(GL_LESS);
if (leftEye != null) {
resetMatrices();
setModelViewMatrix();
translateMEyes();
eyeTextureProgram.useProgram();
eyeTextureProgram.setViewAndTexture(modelViewProjectionMatrix, textureEye);
setProgramParams(eyeTextureProgram, textureEye);
leftEye.bindData(eyeTextureProgram);
leftEye.draw();
}
if (rightEye != null) {
rightEye.bindData(eyeTextureProgram);
rightEye.draw();
}
glDepthFunc(GL_LEQUAL);
resetMatrices();
setModelViewMatrix();
setProgramParams(faceTextureProgram, textureFace);
headBase.bindData(faceTextureProgram);
headBase.draw();
GlUtil.checkGlError("draw done");
}
Set the clearing value of the depth buffer to 1.0. Clearing value of the depth buffer should be the max value of the depth range which by default is 0.0 - 1.0.
glClearDepth(1.0)
Also, ensure that you clear both the depth and color buffer before your drawing.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
I want use OpenGL ES to draw a frame animation, so I use glTexSubImage2D to update the texture.
This function initializes the texture:
private void initTexture()
{
textures=new int[1];
GLES20.glGenTextures(1,textures,0);
//Bitmap bitmap= BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/xiaobizi/xiaobizi_0001.png");
Bitmap bitmap= BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/aa.png");
ratio=(float)bitmap.getHeight()/(float)bitmap.getWidth();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textures[0]);
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);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
this function to save&remove Bitmap:
mTextureMap.remove(mPathList.get(messageTag));
mTextureMap.put(mPathList.get(saveCount),BitmapFactory.decodeFile(mPathList.get(saveCount)));
private void drawMagic()
{
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE,GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glUseProgram(programMagic);
int mPositionHandleFace = GLES20.glGetAttribLocation(programMagic, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandleFace);
GLES20.glVertexAttribPointer(mPositionHandleFace, 2, GLES20.GL_FLOAT, false, 0, 0);
int mTexCoordLocFace = GLES20.glGetAttribLocation(programMagic, "a_texCoord" );
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray ( mTexCoordLocFace );
// Prepare the texturecoordinates
GLES20.glVertexAttribPointer(mTexCoordLocFace, 2, GLES20.GL_FLOAT, false, 0, 0);
// Get handle to shape's transformation matrix
int mTransHandle = GLES20.glGetUniformLocation(programMagic, "transMatrix");
int mScaleHandle=GLES20.glGetUniformLocation(programMagic,"scaleMatrix");
int mRotateXHandle=GLES20.glGetUniformLocation(programMagic,"rotateXMatrix");
int mRotateZHandle=GLES20.glGetUniformLocation(programMagic,"rotateZMatrix");
int mRotateYHandle=GLES20.glGetUniformLocation(programMagic,"rotateYMatrix");
//control matrix
GLES20.glUniformMatrix4fv(mTransHandle,1,false,transMatrix,0);
GLES20.glUniformMatrix4fv(mScaleHandle,1,false,scaleMatrix,0);
GLES20.glUniformMatrix4fv(mRotateXHandle,1,false,rotateXMatrix,0);
GLES20.glUniformMatrix4fv(mRotateZHandle,1,false,rotateZMatrix,0);
GLES20.glUniformMatrix4fv(mRotateYHandle,1,false,rotateYMatrix,0);
int mtrxhandleFace = GLES20.glGetUniformLocation(programMagic, "uMVPMatrix");
// Apply the projection and view transformation
//GLES20.glUniformMatrix4fv(mtrxhandleFace, 1, false, mGLTextureTransformMatrix, 0);
GLES20.glUniformMatrix4fv(mtrxhandleFace, 1, false, mSecondTransFormMatrix, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textures[0]);
if(i>=mTotalCount)
{
i=i-mTotalCount;
}
// update texture
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D,0,0,0,mTextureMap.get(mPathList.get(i)));
int mSamplerLocFace = GLES20.glGetUniformLocation (programMagic, "s_texture" );
// Set the sampler texture unit to 0, where we have saved the texture.
GLES20.glUniform1i ( mSamplerLocFace, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandleFace);
GLES20.glDisableVertexAttribArray(mTexCoordLocFace);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0);
mDecodeHandler.sendEmptyMessage(i);
i++;
}
this is my drawFrame function.
In initTexture function if the bitmap belongs to the Frame Animation, texSubImage2D works,the texture always updating, but if i pass a bitmap that does't belongs to the Frame Animation , the function texSubImage2D does't work. In that case, the texture always was the bitmap that i passed in function initTexture didn't update.
If i called the function when opengl was dawing, the texture was black,but its shapes can be displayed properly, just the background was black.
I am searching for a long time on net. But no use. Please help or try to give some ideas how to fix this.thank u.
I have been request texture id and It has been display ,but now i want to update what have been display ,for example
private void initTexture(){
int textureIds[] = new int[1];
// 启用纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glGenTextures(1, textureIds, 0);
// 将绑定纹理(texuture[0]表示指针指向纹理数据的初始位置)
mTextureID = textureIds[0];
}
public void freshTexture(){
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_NEAREST);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,0,mLayerDrawable.getBitmap(),0);
onFreshView();
}
protected void doDraw() {
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT|GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClearColor(163,156,158,255);
mGL20Factory.useProgram();
MatrixState.setInitStack();
MatrixState.transtate(mScreenPosition.getMoveX(mMoveX),mScreenPosition.getMoveY(mMoveY),0);
MatrixState.scale(mScale,mScale,0);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrixMM(), 0);
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
GLES20.glVertexAttribPointer(mAttribPosition, 3, GLES20.GL_FLOAT, false, 0, mVerticeBuf);
GLES20.glVertexAttribPointer(mAttribTexCoord, 2, GLES20.GL_FLOAT, false, 0, mTextureCoodBuf);
GLES20.glEnableVertexAttribArray(mAttribPosition);
GLES20.glEnableVertexAttribArray(mAttribTexCoord);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glDisableVertexAttribArray(mAttribPosition);
GLES20.glDisableVertexAttribArray(mAttribTexCoord);
}
other way,I use GLUtils.texSubImage2D() method ,but its not used,
Hy,
I'm developing an app on android and I'm in the testing phase and I'm trying it out on different devices. I developed the app on a nexus 7.
When I run it on a arm mali gpu device the rendered textrue starts to blink / lagg like crazy.
I use GLES20.GL_POINTS in the generated texture if I set the point size to 1 it blinks and it looks like there are artifacts in it, and if I set the point size to a bigger number like 10 it "laggs" meaning sometimes it shows a texture from a earlyer rendering.
Any idea what could cause this ?
private void setupRenderToTexture() {
fb = new int[1];
depthRb = new int[1];
renderTex = new int[2];
// generate
GLES20.glGenFramebuffers(1, fb, 0);
GLES20.glGenRenderbuffers(1, depthRb, 0);
GLES20.glGenTextures(1, renderTex, 0);
// create render buffer and bind 16-bit depth buffer
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, texW, texH);
}
This is my render to textue method:
private void createSmokeTexture() {
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);
GLES20.glClearColor(0.48f, 0.48f, 0.48f, 0.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTex[0], 0);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRb[0]);
//background counts
renderscriptSmokeStep_involke();
GLES20.glUseProgram(mProgramSmoke);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramSmoke, "u_MVPMatrix");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgramSmoke, "u_Move");
mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramSmoke, "u_Texture");
smokeParticleSizeUniformHandle = GLES20.glGetUniformLocation(mProgramSmoke, "u_PointSize");
maximumDensityHandler = GLES20.glGetUniformLocation(mProgramSmoke, "u_MaximumDensity");
cellDensityHandle = GLES20.glGetAttribLocation(mProgramSmoke, "a_Age");
smokeStartPositionHandle = GLES20.glGetAttribLocation(mProgramSmoke, "a_Position");
Matrix.setIdentityM(mMoveMatrix, 0);
Matrix.translateM(mMoveMatrix, 0, positionX, positionY, 0);
Matrix.multiplyMM(mMoveMatrix, 0, Render.mModelMatrix, 0, mMoveMatrix, 0);
GLES20.glUniform1f(smokeParticleSizeUniformHandle, PARTICLE_SIZE);
GLES20.glUniform1f(maximumDensityHandler, MAXIMUM_DENSITY);
GLES20.glUniform1i(mTextureUniformHandle, 0);
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMoveMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, Render.m2dProjectionMatrix, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, particlePosBuffer);
GLES20.glEnableVertexAttribArray(smokeStartPositionHandle);
GLES20.glVertexAttribPointer(smokeStartPositionHandle, 2, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glEnableVertexAttribArray(cellDensityHandle);
GLES20.glVertexAttribPointer(cellDensityHandle, 1, GLES20.GL_FLOAT, false, 0, cellDensity);
// Draw the point.
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, NUM_PARTICLES);
}
This gets called on draw:
public void draw(){
createSmokeTexture();
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
setTexture(renderTex[0]);
drawSmokeToScreen();
}
asdas
private void setTexture(int texture) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE);
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);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, texW, texH, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
}
And after this I draw it to the screen
private void drawSmokeToScreen() {
GLES20.glUseProgram(mProgramHandle);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Move");
positionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
textureHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate");
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, Render.mModelMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, Render.m2dProjectionMatrix, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, fullDrawSurfice.getPositionDataIndex());
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, fullDrawSurfice.getTextureDataIndex());
GLES20.glEnableVertexAttribArray(textureHandle);
GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}
It looks like there are a couple of problems with the ordering of your calls.
At the start of createSmokeTexture(), there is this code sequence:
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);
GLES20.glClearColor(0.48f, 0.48f, 0.48f, 0.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, renderTex[0], 0);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
GLES20.GL_RENDERBUFFER, depthRb[0]);
Here, the framebuffer is cleared before it is completely set up by attaching the render targets with the glFramebufferTexture2D() and glFramebufferRenderbuffer() calls. This is most likely only a problem for the first frame, because at least in the code shown here, the render targets are never un-attached again. After that, the calls are just redundant. It would be much better to attach the render targets during setup.
At the end of setTexture():
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, texW, texH, 0,
GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
Based on the sequence in draw(), this is called after the FBO rendering completed, and before using the resulting texture to draw to the main framebuffer. However, this glTexImage2D() call basically wipes out the content of the texture that was produced by the FBO rendering.
To fix both of these problems, remove the glFramebufferTexture2D() and glFramebufferRenderbuffer() from the first code sequence, and all but the glActiveTexture() and glBindTexture() calls from setTexture(). All of these should go to setupRenderToTexture() function, which then becomes:
GLES20.glGenTextures(1, renderTex, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
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);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, texW, texH, 0,
GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
// create render buffer and bind 16-bit depth buffer
GLES20.glGenRenderbuffers(1, depthRb, 0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,
GLES20.GL_DEPTH_COMPONENT16, texW, texH);
GLES20.glGenFramebuffers(1, fb, 0);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, renderTex[0], 0);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
GLES20.GL_RENDERBUFFER, depthRb[0]);
I am rendering to a frame buffer, and then I want to use that as a texture.
I can save the frame buffer to a file using glReadPixels so I am sure that I am rendering OK.
I can bind to fixed texture and render that OK.
But I cannot bind to the frame buffer to render that in place of the fixed texture.
//setup:
private void setupRenderToTexture() {
fb = new int[numberOfBuffers];
depthRb = new int[numberOfBuffers];
renderTex = new int[numberOfBuffers];
texBuffer = new IntBuffer[numberOfBuffers];
// generate
GLES20.glGenFramebuffers(fb.length, fb, 0);
GLES20.glGenRenderbuffers(depthRb.length, depthRb, 0);
GLES20.glGenTextures(renderTex.length, renderTex, 0);
GLErrorHandler.checkGlError("glGenFramebuffers");
for (int i = 0; i < fb.length; i++) {
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[i]);
// generate color texture
GLState.Instance.bindTexture(0, renderTex[i]);
// parameters
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
// GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
// GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
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);
// create it
// create an empty intbuffer first?
int[] fileData = new int[width * height];
texBuffer[i] = IntBuffer.wrap(fileData);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width,
height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
texBuffer[i]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D,
renderTex[i], 0);
// create render buffer and bind 16-bit depth buffer
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[i]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,
GLES20.GL_DEPTH_COMPONENT16, width, height);
GLErrorHandler.checkGlError("glRenderbufferStorage or above");
}
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
}
Use the frame buffer:
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);
Save the frame buffer (for testing):
GLES20.glReadPixels(sourceX, sourceY, width, height, GL10.GL_RGBA,
GL10.GL_UNSIGNED_BYTE, ib);
Then to render to screen:
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture); //some simple texture works but:
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[0]); //frame buffer texture does not work
All I get is a black screen if I bind to renderTex[0]
You are mis-using the FBO. You have to attach an empty texture so that it can render into it.
See this page