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:Here, the framebuffer is cleared before it is completely set up by attaching the render targets with the
glFramebufferTexture2D()
andglFramebufferRenderbuffer()
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()
: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, thisglTexImage2D()
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()
andglFramebufferRenderbuffer()
from the first code sequence, and all but theglActiveTexture()
andglBindTexture()
calls fromsetTexture()
. All of these should go tosetupRenderToTexture()
function, which then becomes: