2017-07-16 107 views
0

在我的OpenGL ES Android遊戲中,我試圖根據它們的Z值(即在Z平面中的位置)按照順序繪製形狀。這意味着先繪製最小的最遠的形狀(紋理),然後繪製更大的圖形。我已經將形狀屬性存儲在一個數組列表中,並且在繪製和更新時我使用了一個迭代器。讓我們說,這是它的Z值的ArrayList的(只是一個例子)抽獎OpenGL - 較大的對象超過較小

的ArrayList arraylistBricks

obj (0) ... z = -20 
obj (1) ... z = -37 
obj (2) ... z = -31 
obj (3) -...z = -20 

我排序使用Collections.sort(..)對每一幀和後此ArrayList的排序列表看起來是這樣的

obj (0) ... z = -37 
obj (1) ... z = -31 
obj (2) ... z = -20 
obj (3) -...z = -20 

即 - 最小的形狀首先在列表中,並首先被繪製。我可以看到arraylist是真的排序,但不知何故發生。我想要的是較小的形狀應該落後於較大的形狀。 GPU是否具有某種繪圖程序的algortitm?我剛剛從skia遷移到了opengl,並對此感到驚訝。

我在這裏錯過了什麼?我怎麼能解決這個問題?

private void drawShape() { 

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboDataListLevelSprites.get(iName).getBuff_id_vertices()); 
    GLES20.glEnableVertexAttribArray(mPositionHandle); 
    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, 0); 
    for (int i = 0; i < BrickProperties.get_buff_id_uvs().length; i++) { 
     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, BrickProperties.get_buff_id_uvs()[i]); 
     GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); 
     GLES20.glVertexAttribPointer(mTextureCoordinateHandle, 2, GLES20.GL_FLOAT, false, 0, 0); 

     for (Iterator<BrickProperties> shapeIterator = arrayListBricks.iterator(); shapeIterator.hasNext();) { 

      BrickProperties bp = shapeIterator.next(); 
      int buffIndexVal = bp.get_status_diff(); 

      if (buffIndexVal == i) { 
       Matrix.setIdentityM(mModelMatrix, 0); 
       Matrix.translateM(mModelMatrix, 0, bp.getTranslateData()[0], bp.getTranslateData()[1], bp.getTranslateData()[2]); 

       if (bp.get_status() == 0) { 
        Matrix.rotateM(mModelMatrix, 0, bp.getAngleInDegrees(), 0, 1, 0); 
       } 

       render(); 
      } 
     } 
    } 

} 

的渲染方法

private void render() { 

    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0); 
    GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0); 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); 
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6); 
} 

更新(片斷)

public void update() { 

    Collections.sort(arrayListBricks, new Comparator<BrickProperties>() { 
     @Override 
     public int compare(BrickProperties bp2, BrickProperties bp1) 
     { 
      int result = Float.compare(bp1.getTranslateData()[2], bp2.getTranslateData()[2]); 
      return result; 

     } 
    }); 
    Collections.reverse(arrayListBricks); 

.... 

回答

0

的OpenGL ES 2具有一個內置深度測試。您可以使用glEnable(GL_DEPTH_TEST)啓用它。

不要忘記清除每幀的緩衝區(或者如果您使用OpenGL ES 3,請使用framebuffer的ivalidate)。

+0

我試過,但它不工作。用** GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT)清除緩衝區; ** – java

+0

@java它是否給出任何錯誤? – Reaper

+0

完全沒有錯誤 – java

0

這意味着先畫出最小的最遠的形狀(紋理),然後畫出更大的圖形。

不要這樣做 - 你會失去早期zs測試在遮蔽片段之前殺死遮擋片段的所有好處。

以前後渲染順序(深度測試啓用,深度寫入啓用)渲染您的不透明片段,然後在後端渲染順序(深度測試啓用,深度寫禁用)渲染透明頂部。

+0

找不到GLES20字段DEPTH_WRITE,只有WRITEMASK – java

+0

是 - 屏蔽是您如何禁用寫入。 https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glDepthMask.xml – solidpixel