Я создаю буфер текстур NVidia на Jetson AGX Xaview со следующим:
NvBufferCreateParams params = {
.width = TEXTURE_WIDTH,
.height = TEXTURE_HEIGHT,
.payloadType = NvBufferPayload_SurfArray,
.memsize = TEXTURE_WIDTH * TEXTURE_HEIGHT * 4,
.layout = NvBufferLayout_Pitch,
.colorFormat = NvBufferColorFormat_ARGB32,
.nvbuf_tag = NvBufferTag_NONE
};
NvBufferCreateEx(&f_texture_fd, ¶ms));
Затем я хочу нарисовать изображение в этой области, поэтому я использую следующее, чтобы сопоставить текстуру с указателем памяти:
NvBufferMemMap(
f_texture_fd
, 0
, NvBufferMem_Read_Write
, reinterpret_cast<void **>(&f_texture));
NvBufferMemSyncForCpu(
f_texture_fd
, 0
, reinterpret_cast<void **>(&f_texture));
Вторая строка там, чтобы убедиться, что буферы памяти правильно синхронизированы.
Аналогичным образом я отключу текстуру следующим образом, как мы видим, у меня также есть вызов синхронизации, поэтому графический процессор видит мои изменения:
NvBufferMemSyncForDevice(f_texture_fd, 0, reinterpret_cast<void **>(&f_texture));
ckt(NvBufferMemUnMap(
f_texture_fd
, 0
, reinterpret_cast<void **>(&f_texture)));
f_texture = nullptr; // pointer was invalidated
Отмена отображения происходит только после того, как я закончу рендеринг своего изображения в буфере.
Вот пример, показывающий, как я визуализирую изображение в текстуру:
std::uint8_t * output(f_texture);
for(int idx(0); idx < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++idx, output += 4)
{
output[0] = blue;
output[1] = green;
output[2] = red;
output[3] = alpha; // <-- whatever I put here, in the fragment shader `tex.a == 1.0`
}
Теперь я могу работать над визуализацией. Поскольку я использую EGL, сначала мне нужен вершинный шейдер:
precision mediump float;
varying vec2 interp_tc;
// the input position includes (x,y) for the vertex and (x,y) for the texture
attribute vec4 in_position;
void main()
{
interp_tc = in_position.zw;
gl_Position = vec4(in_position.xy, 0, 1);
}
а затем фрагмент шейдеров:
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 interp_tc;
uniform samplerExternalOES tex;
void main()
{
gl_FragColor = texture2D(tex, interp_tc);
}
А рендеринг в моей программе выглядит так:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
f_egl_image = NvEGLImageFromFd(
f_egl_display
, f_texture_fd);
glUseProgram(f_program);
glActiveTexture(f_texture_id);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, f_texture);
panel_context::glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, f_egl_image);
glDrawArrays(GL_TRIANGLES, 0, 6);
glUseProgram(0);
glSwapBuffers();
NvDestroyEGLImage(f_egl_display, f_egl_image);
Рендеринг отлично работает для части RGB (я получаю правильные цвета), но я ничего не вижу даже там, где альфа не равна 255 (1.0) в моей текстуре. Для проверки я даже изменил этот цикл выше, чтобы использовать rand()
вот так:
output[3] = rand(); // <- random alpha channel
Это должно дать мне флуктуирующий альфа-канал, который будет отображаться на экране как смесь фона и этого изображения. Изображение по-прежнему кажется 100% сплошным.
Кроме того, смешивание работает просто отлично, так как я могу настроить альфа-канал во фрагментном шейдере, и он работает, как и ожидалось, поэтому, например, я мог бы настроить шейдер следующим образом:
if(texture2D(tex, interp_tc).a == 1.0)
{
gl_FragColor = vec4(1.0, 0.75, 0.0, 0.3);
}
else
{
gl_FragColor = texture2D(tex, interp_tc);
}
и изображение оранжевое, потому что входной альфа-канал всегда равен 1,0, а FragColor
установлен на довольно прозрачный оранжевый цвет. Я вижу сквозь этот оранжевый цвет, как и ожидалось (т. е. 0,3 соответствует действительности и работает так, как я ожидал).
Я также пробовал следующее:
gl_FragColor = vec4(texture2D(tex, interp_tc).r,
texture2D(tex, interp_tc).g,
texture2D(tex, interp_tc).b,
0.5);
и, конечно же, изображение появляется с прозрачностью 50%, поэтому я вижу фон через изображение текстуры.
Другими словами, я могу заставить RGB и альфу работать, только текстура tex
, кажется, не несет альфу, которую я в нее вложил.
Чтение Фрагментный шейдер всегда использует 1.0 для альфа-канала заставляет меня думать, что каким-то образом доступ к tex
эквивалентен:
vec4(r, g, b, 1.0);
Но я не использую буфер глубины или какую-то особую магию. Я явно выделяю буфер NvBufferColorFormat_ARGB32
для своей текстуры.