Случайно исчезающая часть визуализированного изображения - PullRequest
1 голос
/ 06 июня 2019

Я создаю простую полосу следа, чтобы покрыть весь видовой экран одним прямоугольником. Затем я применяю текстуру 100x100 к этой поверхности, которая меняется с каждым кадром.

Я настроил viewPort и инициализировал свой vertexBuffer и т. Д. В методе onSurfaceChanged моего класса GLSurfaceView, а затем вызываю мою функцию рендеринга из onDrawFrame.

Эта установка работает как надо, но в случайных случаях рендерится только правая нижняя четверть моего прямоугольника, остальные 3/4 холста закрашиваются цветом фона! Это происходит не каждый раз, и аномалия исчезает после вращения устройства вперед-назад (я думаю, потому что все получает сброс в onSurfaceChanged)

Я пытался перезагружать все вершины при каждом обновлении фрейма с помощью GLES20.glBufferData, который, кажется, избавляется от этой ошибки, хотя, возможно, я просто не был достаточно терпелив, чтобы наблюдать, как это происходит (как это совершенно непредсказуемо). Это очень простая полоса треугольника, поэтому я не думаю, что она отнимает много времени, но просто плохая практика загружать данные со скоростью 60 / сек, которые не меняются вообще!

//called from onSurfaceChanged
private fun initGL (side:Int) {

        /*======== Defining and storing the geometry ===========*/
        //vertices for TRIANGLE STRIP
        val verticesData = floatArrayOf(
            -1.0f,1.0f,//LU
            -1.0f,-1.0f,//LL
            1.0f,1.0f,//RU
            1.0f,-1.0f//RL
        )

        //float : 32 bit -> 4 bytes
        val vertexBuffer : FloatBuffer = ByteBuffer.allocateDirect(verticesData.size * 4)
            .order(ByteOrder.nativeOrder()).asFloatBuffer()
        vertexBuffer.put(verticesData).position(0)

        val buffers = IntArray(1)
        GLES20.glGenBuffers(1, buffers, 0)
        vertexBufferId = buffers[0]

        //upload vertices to GPU
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId)
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
            vertexBuffer.capacity() * 4, // 4 = bytes per float
            vertexBuffer,
            GLES20.GL_STATIC_DRAW)
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0)

        /*================ Shaders ====================*/

        // Vertex shader source code
        val vertCode =
                """
                attribute vec4 aPosition;
                void main(void) {
                    gl_Position = aPosition;
                }
                """

        val fragCode =
            """
            precision mediump float;

            varying vec2 vCoord;
            uniform sampler2D u_tex;
            void main(void) {
                //1-Y, because we need to flip the Y-axis!!
                vec4 color = texture2D(u_tex, vec2(gl_FragCoord.x/$side.0, 1.0-(gl_FragCoord.y/$side.0)));
                gl_FragColor = color;
            }
            """

        // Create a shader program object to store
        // the combined shader program
        val shaderProgram = createProgram(vertCode, fragCode)

        // Use the combined shader program object
        GLES20.glUseProgram(shaderProgram)

        val vertexCoordLocation = GLES20.glGetAttribLocation(shaderProgram, "aPosition")
        GLES20.glVertexAttribPointer(vertexCoordLocation, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer)
        GLES20.glEnableVertexAttribArray(vertexCoordLocation)

        //set ClearColor
        GLES20.glClearColor(1f,0.5f,0.5f,0.9f)

        //setup a texture buffer array
        val texArray = IntArray(1)
        GLES20.glGenTextures(1,texArray,0)
        textureId = texArray[0]
        if (texArray[0]==0) Log.e(TAG, "Error with Texture!")
        else Log.e(TAG, "Texture id $textureId created!")

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)

        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_MIN_FILTER, GLES20.GL_NEAREST)
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST)
        GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT,1)
    }

//called from onDrawFrame
private fun updateGLCanvas (matrix : ByteArray, side : Int) {
        //create ByteBuffer from updated texture matrix
        val textureImageBuffer : ByteBuffer = ByteBuffer.allocateDirect(matrix.size * 1)//Byte = 1 Byte
            .order(ByteOrder.nativeOrder())//.asFloatBuffer()
        textureImageBuffer.put(matrix).position(0)

        //do I need to bind the texture in every frame?? I am desperate XD 
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0,GLES20.GL_RGB, side, side, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, textureImageBuffer)

        //bind vertex buffer
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId)
        // Clear the color buffer bit
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
        //draw from vertex buffer
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4)
        //unbind vertex buffer
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0)
    }

Нет сообщений об ошибках, и большую часть времени код работает так, как и должен ... что затрудняет его отслеживание ...

1 Ответ

1 голос
/ 06 июня 2019

Если вы хотите использовать буфер вершин, тогда объект буфера должен быть в настоящее время привязан к цели GLES20.GL_ARRAY_BUFFER, когда массив данных общего атрибута вершины указан как glVertexAttribPointer.Спецификация атрибута вершины ссылается на этот буфер.

В этом случае последний параметр glVertexAttribPointer обрабатывается как смещение байта в хранилище данных объекта буфера.
В вашем случае это означает, что последний параметр имеетбыть равным 0.

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId)
GLES20.glVertexAttribPointer(vertexCoordLocation, 2, GLES20.GL_FLOAT, false, 0, 0)

Обратите внимание: если ни один буферный объект не связан с буфером (ноль), то последний параметр является указателем на буферную память.Каждый раз, когда выполняется вызов отрисовки, этот буфер считывается.
В вашей реализации данные, загруженные в графический процессор, никогда не используются, поскольку на них не ссылается спецификация массива вершин.
См. Также Спецификация вершины .

...