我将工作代码从C ++移植到Java。在C ++中,我使用了与此处相同的着色器和相同的代码,并且能够使用GPU的3个纹理单元加载Y
,U
和V
组件,然后使用texture()
将这些纹理连接到要渲染的RGBA缓冲区中。
问题是,在Android中,我看到一个绿屏,这是着色器在指定空Y
,U
和V
纹理单元时生成的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_y
,tex_u
和tex_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);