簡體   English   中英

OpenGL ES 2.0渲染到ARM MALI GPU上的紋理錯誤

[英]OpenGL ES 2.0 render to texture bug on ARM MALI gpu

嗨,我正在Android上開發一個應用,目前處於測試階段,並且正在其他設備上進行嘗試。 我在Nexus 7上開發了該應用程序。

當我在手臂馬里GPU設備上運行它時,渲染的textrue開始閃爍/滯后,就像瘋了一樣。 我將GLES20.GL_POINTS用於生成的紋理中,如果將點大小設置為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);
}

這是我的渲染文本方法:

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

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

然后將其繪制到屏幕上

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

您的通話順序似乎有幾個問題。

  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()glFramebufferRenderbuffer()調用,在完全設置幀緩沖區之前將其清除。 這很可能只是第一幀的問題,因為至少在此處顯示的代碼中,渲染目標再也不會解除連接。 在那之后,通話只是多余的。 在安裝過程中附加渲染目標會更好。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM