Я портировал рабочий код с C ++ на Java. В C ++ я использовал те же шейдеры, что и здесь, и тот же код, и я смог использовать 3 текстурных блока графического процессора для загрузки компонентов Y
, U
и V
, а затем использовать texture()
для соединения с ними. текстуры в буфер RGBA для визуализации.
Проблема в том, что в Android я вижу зеленый экран, который представляет собой цвет RGBA, который генерируется шейдером при пустых Y
, U
и V
даны текстурные единицы. Таким образом, текстуры не загружаются. Я отключил все объекты в пиксельном буфере и попытался просто 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;
}
Вот шейдеры:
Vertex:
#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);