1

嗨,我正在开发一个安卓应用程序,我正处于测试阶段,我正在不同的设备上试用它。我在nexus 7上开发了该应用程序。

当我在 arm mali gpu 设备上运行它时,渲染的 textrue 开始疯狂地闪烁/滞后。如果我将点大小设置为 1,我在生成的纹理中使用 GLES20.GL_POINTS早期渲染的纹理。

知道是什么原因造成的吗?

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

这是我渲染到文本的方法:

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

然后我把它画到屏幕上

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

1 回答 1

1

您的通话顺序似乎存在一些问题。

  1. 在 的开头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()在这里,通过使用andglFramebufferRenderbuffer()调用附加渲染目标,帧缓冲区在完全设置之前被清除。这很可能只是第一帧的问题,因为至少在此处显示的代码中,渲染目标永远不会再次取消附加。在那之后,电话只是多余的。在设置期间附加渲染目标会更好。

  2. 在结束时setTexture()

    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, texW, texH, 0,
            GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
    

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

要解决这两个问题,请从第一个代码序列中删除glFramebufferTexture2D()and ,并从. 所有这些都应该发挥作用,然后变成:glFramebufferRenderbuffer()glActiveTexture()glBindTexture()setTexture()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]);
于 2014-12-13T06:45:09.933 回答