Android ARM-gpu上的OpenGL ES 2.0渲染到纹理错误

Android ARM-gpu上的OpenGL ES 2.0渲染到纹理错误,android,opengl-es-2.0,render-to-texture,mali,Android,Opengl Es 2.0,Render To Texture,Mali,Hy, 我正在android上开发一个应用程序,我正在测试阶段,我正在不同的设备上试用。我在Nexus7上开发了这个应用程序 当我在arm-gpu设备上运行它时,渲染的textrue开始疯狂地闪烁/滞后。 我在生成的纹理中使用GLES20.GL_点,如果我将点大小设置为1,它会闪烁,看起来里面有瑕疵,如果我将点大小设置为更大的数字,如10,它会“滞后”,这意味着有时它会显示早期渲染的纹理 你知道这是什么原因吗 private void setupRenderToTexture() { f

Hy, 我正在android上开发一个应用程序,我正在测试阶段,我正在不同的设备上试用。我在Nexus7上开发了这个应用程序

当我在arm-gpu设备上运行它时,渲染的textrue开始疯狂地闪烁/滞后。 我在生成的纹理中使用GLES20.GL_点,如果我将点大小设置为1,它会闪烁,看起来里面有瑕疵,如果我将点大小设置为更大的数字,如10,它会“滞后”,这意味着有时它会显示早期渲染的纹理

你知道这是什么原因吗

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);
}
这是我的render to textue方法:

   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);
}
这将在绘图时调用:

   public void draw(){
    createSmokeTexture();
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    setTexture(renderTex[0]);
    drawSmokeToScreen();
}
阿斯达斯

然后我把它画到屏幕上

   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);
}

您的通话顺序似乎有几个问题

  • 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]);
    
    在这里,通过使用
    glFramebufferTexture2D()
    glFramebufferRenderbuffer()
    调用附加渲染目标,可以在完全设置帧缓冲区之前清除帧缓冲区。这很可能只是第一帧的问题,因为至少在这里显示的代码中,渲染目标永远不会再次解除连接。在那之后,这些电话只是多余的。最好在设置过程中附加渲染目标

  • setTexture()
    的末尾:

    根据
    draw()
    中的序列,在FBO渲染完成后,在使用生成的纹理绘制到主帧缓冲区之前,将调用该函数。但是,此调用基本上会清除FBO渲染生成的纹理内容

  • 要解决这两个问题,请从第一个代码序列中删除
    glFramebufferTexture2D()
    glFramebufferRenderbuffer()
    ,并从
    setTexture()
    中删除除
    glActiveTexture()和
    glBindTexture()
    之外的所有调用。所有这些都应转到
    setupRenderToTexture()
    函数,然后该函数将变为:

    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]);
    

    需要检查的一件事是支持的点大小。使用
    glGetFloatv(GL\u别名\u点\u大小\u范围,…)
    。实现不需要支持大于1的点大小。除此之外,仅仅描述一下问题,人们可能帮不了多少忙。这可能是一个驱动程序错误,或者是代码中的一个问题,恰好在其他体系结构上没有显示任何症状。@RetoKoradi很高兴知道这不是必需的,我检查过了,并且此设备支持它。你说得对,几分钟后我会输入一些代码。这是我的工作,我没有在不同架构上开发的经验,所以我不知道该检查什么
    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, texW, texH, 0,
            GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
    
    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]);