android - Unity原生OpenGL贴图显示四次

标签 android c++ unity3d opengl-es

我目前正面临一个我根本不明白的问题。 我使用 ARCore 执行由内而外的跟踪任务。因为我需要做一些额外的图像处理,所以我使用 Unitys 功能来加载 native 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 传递使用了太多内存,但是由于 OpenGL ES3 和 GL_ALPHA 不支持 GL_R8 总是导致内部 OpenGL 错误,我只是将灰度值传递给每个颜色分量。

然而最终纹理渲染如下图所示:

image

起初我想,这可能是因为其他 channel 具有相同的值,但是将除第一个 channel 之外的所有其他 channel 设置为任何值都不会产生任何影响。

我是否遗漏了一些明智的 OpenGL 纹理创建方法?

最佳答案

YUV_420_888 是一种多平面纹理,其中亮度平面每个像素仅包含一个 channel 。

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

您的循环边界假定 c 是 4 个 channel 的倍数,这适用于输出表面,但您随后在计算输入表面索引时也会使用它。您使用的输入表面平面仅包含一个 channel ,因此 idx 是错误的。

通常,您还会多次覆盖同一内存 - 循环每次迭代都会将 c 递增 1,但您随后写入 cc+ 1c+2c+3 所以覆盖你上次写的三个值。

较短的答案 - 您的 OpenGL ES 代码很好,但我认为您正在用错误的数据填充纹理。

未经测试,但我认为您需要:

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

关于android - Unity原生OpenGL贴图显示四次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54884697/

相关文章:

unity3d - 如何使一个切换在另一个打开时关闭

c# - 为什么在编辑器中按Play时Unity崩溃?

Android:盒子阴影和边框半径布局

Android Activity 生命周期和 jni 内存管理

c++ - 如何阅读模板偏特化?

c++ - 在 C 或 C++ 中取消引用数组时使用小数参数

c# - 如何指定动态默认值

android - AppsFlyer 集成测试失败

java - addListener 按钮在 android studio 中的 fragment 中不起作用

c++ - 强制 cv::Mat 使用 RGB 数据顺序