【问题标题】:Draworder OpenGL - larger objects over smallerDraworder OpenGL - 较大的对象大于较小的对象
【发布时间】:2017-07-17 18:10:09
【问题描述】:

在我的 OpenGL ES Android 游戏中,我尝试根据其 z 值(即 z 平面中的位置)按顺序绘制形状。这意味着首先绘制最小最远的形状(纹理),然后再绘制更大的。我已将形状属性存储在数组列表中,并且在绘制和更新时我使用的是迭代器。假设这是带有 z 值的 arrayList(只是一个示例)

ArrayList 数组列表砖

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

我使用 Collections.sort(..) 为每一帧排序这个数组列表,排序后的列表看起来像这样

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

也就是说 - 最小的形状在列表中首先被绘制。我可以看到数组列表确实已排序,但不知何故什么也没发生。我想要的是较小的形状应该在较大的形状后面。 GPU是否有某种绘图顺序的算法?我刚从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);
}

更新(sn-p)

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

....

【问题讨论】:

    标签: android opengl-es opengl-es-2.0 gldrawarrays


    【解决方案1】:

    OpenGL ES 2 具有内置的深度测试。您可以使用glEnable(GL_DEPTH_TEST) 启用它。

    不要忘记每帧清除缓冲区(或者如果您使用 OpenGL ES 3,则验证帧缓冲区)。

    【讨论】:

    • 我试过了,但它不起作用。使用 GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); 清除缓冲区
    • 是的 - 每一帧。
    • 您的 EGL 配置是否请求深度缓冲区?
    【解决方案2】:

    这意味着先绘制最小最远的形状(纹理),然后再绘制较大的。

    不要这样做 - 你会失去 early-zs 测试的所有好处,因为它会在被遮蔽之前杀死被遮挡的片段。

    按从前到后的渲染顺序渲染不透明片段(启用深度测试,启用深度写入),然后按从后到前的渲染顺序在顶部渲染透明片段(启用深度测试,禁用深度写入)。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多