在Android上渲染YUV视频时,纹理未上传到纹理单元

时间:2019-11-01 20:55:48

标签: java android opengl-es

我将工作代码从C ++移植到Java。在C ++中,我使用了与此处相同的着色器和相同的代码,并且能够使用GPU的3个纹理单元加载YUV组件,然后使用texture()将这些纹理连接到要渲染的RGBA缓冲区中。

问题是,在Android中,我看到一个绿屏,这是着色器在指定空YUV纹理单元时生成的RGBA颜色。因此纹理没有被上传。我关闭了所有像素缓冲区的内容,并尝试使用简单的缓冲区简单地glTexImage2D,但也看不到任何变化。

 public boolean renderYUV(DecodedFrame decodedFrame) throws Exception {
        GLES20.glEnableVertexAttribArray(vertexInLocation);
        GLES20.glEnableVertexAttribArray(textureInLocation);

        if (!initiatedTextures)
        {
            glGenTextures(TEXTURE_NUMBER, textureId);

            for (int i = 0; i < TEXTURE_NUMBER; i++)
            {
                glBindTexture(GL_TEXTURE_2D, textureId.get(i));
                glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelBufferObjects.get(i));
                glBufferData(GL_PIXEL_UNPACK_BUFFER, decodedFrame.textureSize[i], null, GL_STREAM_DRAW);
                glTexImage2D(GL_TEXTURE_2D,
                            0,
                            GL_RED,
                            decodedFrame.width[i],
                            decodedFrame.height[i],
                            0,
                            GL_RED,
                            GL_UNSIGNED_BYTE,
                            null); //decodedFrame->buffer[i]);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            }
            initiatedTextures = true;
        }
        for (int j = 0; j < TEXTURE_NUMBER; j++)
        {
            glActiveTexture(GL_TEXTURE0 + j);
            glBindTexture(GL_TEXTURE_2D, textureId.get(j));
            glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelBufferObjects.get(j));

            if (true)//todo: change to verify if buffer has contents
            {
                for (int i = 0; i <= decodedFrame.height[j] - 1; i++)
                {
                    int offset = i * decodedFrame.linesize[j];
                    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, offset, decodedFrame.width[j], decodedFrame.buffer[j]);
                }
                glTexSubImage2D(GL_TEXTURE_2D,
                        0,
                        0,
                        0,
                        decodedFrame.width[j],
                        decodedFrame.height[j],
                        GL_RED,
                        GL_UNSIGNED_BYTE,
                        null);
            }
            glUniform1i(textureLocation[j], j);
        }
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        return true;
    }

以下是着色器:

顶点:

#version 320 es
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

void main()
{
    gl_Position = vec4(aPos, 1.0);
    TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}

片段:

#version 320 es

#ifdef GL_ES
precision mediump int;
precision mediump float;
#endif

uniform sampler2D tex_y;
uniform sampler2D tex_u;
uniform sampler2D tex_v;

in vec2 TexCoord;
out vec4 FragColor;

void main()
{
    vec3 yuv;
    vec4 rgba;
    yuv.r = texture(tex_y, TexCoord).r - 0.0625;
    yuv.g = texture(tex_u, TexCoord).r - 0.5;
    yuv.b = texture(tex_v, TexCoord).r - 0.5;

    rgba.r = yuv.r + 1.402 * yuv.b;
    rgba.g = yuv.r - 0.34413 * yuv.g - 0.71414 * yuv.b;
    rgba.b = yuv.r + 1.772 * yuv.g;
    FragColor = rgba;
}

我已验证正在加载tex_ytex_utex_v(glGetUniformLocation可以工作)并且着色器可以编译而没有任何问题。我还用FragColor = rgba交换了FragColor = vec4(1.0f, 0, 0, 1.0f)并说了一个红色图像,确认着色器正在工作,唯一的问题是纹理为空。因此,我很确定问题与填充纹理有关。如您所见,glUniform1i(textureLocation[j], j);为每个统一变量激活Sampler2D,所以这也不是问题。

有人可以发现我在Java中缺少的一些不同于C ++的简单东西吗?

只需添加更多信息,以下是我的顶点和纹理坐标:

static float vertex[] = {
        -1.0f,  -1.0f, 0.0f, // top left
        1.0f, -1.0f, 0.0f,   // bottom left
        -1.0f, 1.0f, 0.0f,   // bottom right
        1.0f,  1.0f, 0.0f    // top right
}; 
static float fragment[] = {
        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f
};

//create vertexBuffer and fragmentBuffer from the arrays here

GLES20.glVertexAttribPointer(vertexInLocation, 3, GLES20.GL_FLOAT, false, 3*4, vertexBuffer);
GLES20.glEnableVertexAttribArray(vertexInLocation);
GLES20.glVertexAttribPointer(textureInLocation, 2, GLES20.GL_FLOAT, false, 2*4, fragmentBuffer);
GLES20.glEnableVertexAttribArray(textureInLocation);

0 个答案:

没有答案