Unity OpenGL текстура отображается четыре раза - PullRequest
0 голосов
/ 26 февраля 2019

У меня сейчас проблема, которую я просто не понимаю.Я использую ARCore для задачи отслеживания наизнанку.Поскольку мне нужно выполнить дополнительную обработку изображений, я использую возможность Unitys для загрузки собственного плагина c ++.В самом конце каждого кадра я передаю изображение в формате YUV_420_888 в виде необработанного байтового массива моему плагину.

Дескриптор текстуры создается в самом начале инициализации компонентов:

private void CreateTextureAndPassToPlugin()
{

    Texture2D tex = new Texture2D(640, 480, TextureFormat.RGBA32, false);

    tex.filterMode = FilterMode.Point;
    tex.Apply();
    debug_screen_.GetComponent<Renderer>().material.mainTexture = tex;

    // Pass texture pointer to the plugin
    SetTextureFromUnity(tex.GetNativeTexturePtr(), tex.width, tex.height);
}

Поскольку мне нужно только изображение в градациях серого, я в основном игнорирую часть UV изображения и использую только Yкоординаты, как показано ниже:

uchar *p_out;
int channels = 4;
for (int r = 0; r < image_matrix->rows; r++) {
    p_out = image_matrix->ptr<uchar>(r);
    for (int c = 0; c < image_matrix->cols * channels; c++) {
        unsigned int idx = r * y_row_stride + c;
        p_out[c] = static_cast<uchar>(image_data[idx]);
        p_out[c + 1] = static_cast<uchar>(image_data[idx]);
        p_out[c + 2] = static_cast<uchar>(image_data[idx]);
        p_out[c + 3] = static_cast<uchar>(255);
    }
}

, затем каждый кадр данных изображения помещается в текстуру GL:

GLuint gltex = (GLuint)(size_t)(g_TextureHandle);
glBindTexture(GL_TEXTURE_2D, gltex);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 640, 480, GL_RGBA, GL_UNSIGNED_BYTE, current_image.data);

Я знаю, что я использую слишком много памяти, создавая иПередача текстуры как RGBA, но поскольку GL_R8 не поддерживается OpenGL ES3, а GL_ALPHA всегда приводит к внутренним ошибкам OpenGL, я просто передаю значение шкалы серого для каждого компонента цвета.

Однако в конце текстура отображается как может бытьвидно на следующем изображении:

image

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

Я что-то пропустил в создании OpenGL-текстуры?

1 Ответ

0 голосов
/ 27 февраля 2019

YUV_420_888 - многоплоскостная текстура, где плоскость яркости содержит только один канал на пиксель.

for (int c = 0; c < image_matrix->cols * channels; c++) {
    unsigned int idx = r * y_row_stride + c;

В ваших границах цикла предполагается, что c кратно 4 каналам, что подходит для выводаповерхность, но затем вы используете его также при вычислении индекса входной поверхности.Используемая вами плоскость входной поверхности содержит только один канал, поэтому idx неверен.

В общем случае вы также перезаписываете одну и ту же память несколько раз - цикл увеличивает c на одну каждую итерацию, но вызатем запишите в c, c+1, c+2 и c+3, чтобы перезаписать три значения, которые вы написали в прошлый раз.

Краткий ответ - ваш код OpenGL ES в порядке, но я думаю, что вы заполняете текстуру неверными данными.

Не проверено, но я думаю, что вам нужно:

for (int c = 0; c < image_matrix->cols * channels; c += channels) {
    unsigned int idx = (r * y_row_stride) + (c / channels);
...