问题标签 [opengl-es-3.1]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
android - Android opengl 着色器程序将图像从相机复制到 SSBO 以进行 TF-lite GPU 推理
Tensorflow lite gpu 委托文档提供了一种在 Android[3] 中使用 Opengl 和 SSBO 运行 tflite 推理的更快方法。该文档提供了示例代码,用于创建和绑定 SSBO 与 GPU 中已有的图像。我们如何从 android live camera 复制或转换图像并使用 OpenGL 着色器代码将其复制到 SSBO?当我们只是将 CPU 内存转储到 SSBO 时,与正常的 gpu 委托执行相比,性能会变得更差。那么将相机图像传递给SSBO以使tflite推理更快的正确或最有效的方法是什么?
在下面的代码中,我们尝试将相机帧转换为位图,然后将其转换为纹理,最后将其复制到 SSBO。然而,这种方法比普通的 GPU 委托执行管道(其中数据从 CPU 复制到 GPU 的开销)要慢得多。目的是通过使图像数据在 GPU 内存中可用,然后将其传递给模型来减少 CPU 到 GPU 的图像数据复制。我们能够使用标准 GPU 委托推理机制在 40-50 毫秒内运行模型[1];而使用上述 SSBO 方法(未优化)需要 90-100 毫秒。以上时间是指interpreter.run()
tensorflow lite中运行方法的时间。此外,看起来这种 SSBO 机制仅适用于 OpenGL ES 3.1 或更高版本。
理想的用例(由 tensorflow 建议)如下[2]:
- 您以表面纹理的形式获得相机输入。
- 创建一个 OpenGL 着色器存储缓冲区对象 (SSBO)。
用于
GPUDelegate.bindGlBufferToTensor()
将该 SSBO 与输入张量相关联。编写一个小的着色器程序来有效地将 [1] 的表面纹理转储到 [2] 的 SSBO 中。
运行推理。
我们能够将相机帧作为原始字节获取或将其转换为纹理,甚至将其渲染到 GLSurface View。但是我们无法实现 tensorflow 所建议的加速。
- https://github.com/tensorflow/tensorflow/issues/26297
- https://github.com/tensorflow/tensorflow/issues/25657#issuecomment-466489248
- https://www.tensorflow.org/lite/performance/gpu_advanced#android_2
安卓代码:
计算着色器:-
android - 在使用 OpenGL-ES 的不同 Android 手机上,使用 alpha 混合的颜色是不同的
我在使用 OpenGL ES 3.1 的 Android 上遇到问题。我编写了一个应用程序,显示液体从屏幕顶部落下。这种液体由许多有点透明的粒子组成,但使用 alpha 混合的颜色在另一部手机上显示不同。
每一滴的颜色定义如下:
每个粒子颜色都存储在缓冲区中:
并将这个缓冲区传递给要绘制的 OpenGL 实体:
通过调用此函数来关闭渲染:
片段着色器只绘制它接收到的颜色:
它在一部手机(Nexus 5X)上运行良好:
但是在另一部手机(Galaxy S10)上,使用完全相同的代码,颜色就不一样了:
有没有人知道解决这个问题的方法?我也想在第二部手机上显示正确的颜色。
opengl-es - 将 glsl 模与 uint 一起使用
在我的计算机着色器中,我尝试根据图像矩形内的 gl_GlobalInvocation 变量计算每个本地调用的纹理坐标。对于高达 262144 的 gl_GlobalInvocation.x 的较大值,我会得到奇怪的结果。(gl_WorkGroupSize=1024 (1024,1,1), gl_NumWorkGroups=256 (256,1,1), width <= 512, height <= 512) 也许是因为 glsl 模无法处理 OpenGL ES 3.1 中的 uint 数据类型。
是否有替代方法来计算 uint 范围的坐标?
c - 为什么我的三角形在 Raspberry Pi 上的 OpenGL ES 3 中是白色的
我有一个非常简单的 OpenGL ES 程序示例,我试图在 Raspberry Pi 4 上的 RaspiOS Desktop(又名 Raspbian)上运行该程序。
我的目标很简单——在屏幕中央画一个红色三角形。但是,三角形显示为白色而不是红色。
我已经搜索并尝试了所有方法,但找不到任何帮助。在这一点上,我感到非常沮丧,因为这应该是第一个介绍 OpenGL ES 世界的教程,而我已经陷入困境,无法继续更复杂的示例。
无论如何,这是完整的例子
在运行它之前,您需要:
- 跑
sudo raspi-config
- 转到高级选项 > GL 驱动程序
- 启用 GL(假 KMS)
- 重启
然后你可以像这样编译和运行它:
起初我以为可能是驱动程序中的一些错误或其他东西。但是后来我找到了这个示例并尝试运行它,它绘制了一些具有多种颜色的图形,这很好。
我会很感激任何帮助。这几天我一直在尝试调试它。
android - 无法使用特定索引(Android11、Pixel3)进行 imageLoad()
我遇到了一个问题,我无法在“imageBuffer”的特定地址读取值。
一个数组有粒子位置,第一个和第二个元素有一个数组的长度,如果我尝试使用数组长度的第一个元素,它总是为零,以下返回。
int total_particle = int(imageLoad(particle_pos_in, 0).x);
这是 imageBuffer 的输入。
计算我可以读取第一个索引的着色器。
您可以假设 TOTAL_PARTICLE 为 100K,因此有1000 个工作组,每个工作组有 100 次调用。
也许我应该确保我访问的地址,但这个地址永远不会写在这里,也不会写在其他调用中。
注意
如果我使用 1 个大小的工作组(x=1,y=1 和 z=1),它工作正常
而不是第一个元素,使用统一的 vec4 可以正常工作。
上面的代码适用于大多数设备(10+ Android 设备),但是,Android11 的设备(Pixel3)(Android10 很好)。
这是一个测试代码,我有很多计算着色器程序,但只有使用 const integer index 访问 imageBuffer 才会在设备上出现问题。
android - Android 如何将相机流拆分为具有不同 fps/分辨率/water_marks 的多个流以进行预览/录制/实时流/AI
我正在开发一个具有预览/本地录制/实时流/AI 功能的项目。
所有这些功能都可能随时被激活/停用。
并且每个流在特定的帧速率下都有自己的分辨率,并带有自定义的水印。
所以我正在为此寻找解决方案,
如果解决方案能够在用户体验和效率上取得平衡,那就太好了。
我学到的潜在解决方案。
----
[Android 相机 API2]
通过将不同的目标输出表面激活为相机重复请求。
优点:
- 易于拆分为不同的分辨率。
缺点:
- 替换重复请求将引入帧间隙和明显的抖动。
- 无法控制每个输出表面的 fps,并且可能会减慢整个请求的 fps。(yuv 数据提取的输出表面和 ImageReader 太多)
- 支持有限的输出表面。(通常 3 个)
- 不知道如何对每个流进行帧后处理,例如添加水印。
[Android Camera API2 + libyuv]
将一个 ImageReader 添加到 Camera API2 并将 ImageReader 的数据复制到多个流中,并使用 libyuv 为每个流进行缩放/水印。
优点:
- 每个流的 FPS 可控。
- 即时添加/删除流。
缺点:
- 使用 libyuv 进行 sacle/water-mark 的 CPU 负载较高。
- 用于处理和传输过多数据缓冲区的高 CPU。
- 如果涉及 4K 分辨率,则会出现散热问题。
【安卓相机API2+OpenGLES】
- 生成纹理对象。
- 创建一个 TextureSurface(纹理对象)。
- 将 TextureSurface 馈送到 Camera API2。
- 当 FrameAvailable 时更新 TexImage。
通过以下方式添加流:
- 使用共享的 GlContext 创建一个线程。
- 为输出表面创建 EGLSurface。(SurfaceView/MediaCodec/ImageReader..)
- 设置一个周期性定时器(fps 控制)来绘制帧。
- 当铃声响起。
- BindTexture 并绘制到当前的 EGLSurface。
- 将位图混合为水印。
- 如果流需要 YUV420 输出,我可以
rgbaToYuv
通过片段着色器实现,然后 glReadPixels()。
通过以下方式删除流:
- 释放相关资源。
- 终止此线程。
优点:
- 动态添加/删除流而不影响其他流。
- 简单的fps控制
- 轻松添加水印
缺点:
- 可能是 GPU 加载过多?
我真的不确定。我对OpenGLES的东西不是很熟悉。
所以请发表评论。
您如何看待上述解决方案?
哪一个更好?
和任何其他方法?
如果我缺乏理解,请原谅我。
opengl-es - glsl 可以支持的最大整数(无符号整数)值是多少?
可以在着色器中使用的整数和无符号整数的最大值是多少?
c++ - glTexImage2D 纹理不能以正确的格式读取
我正在开发一个涉及 OpenGLES (3.1) 的跨平台项目。Windows
虽然代码在我和Ubuntu
机器上完美执行。在 Raspberry PI 4 上运行相同的代码会导致一个奇怪的问题,在使用glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, 0)
调用成功初始化纹理后,稍后在请求相同 FrameBuffer 的可用读取类型的代码中glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, ...)
返回 GL_GRBA。对于上下文创建,我将 GLFW 与 GLAD 一起使用。下面是纹理初始化的完整代码:
read_format
值等于GL_RGBA
哪个应该GL_RGB
!read_type
值等于GL_UNSIGNED_BYTE
预期
因此,在渲染调用尝试读取纹理到本地back_buf数组后,使用:glReadPixels(0, 0, 16, 256, GL_RGB, GL_UNSIGNED_BYTE, back_buf)
导致GL_INVALID_OPERATION
with glReadPixels(invalid format GL_RGB and/or GL_UNSIGNED_BYTE)
. 将读取类型从更改GL_RGB
为GL_RGBA
修复错误,但我的程序无法使用生成的数据格式(我严格寻找 GL_RGB 格式)。
我的问题是我做错了什么还是 Raspberry PI 4 OpenGLES 驱动程序有问题?
opengl-es-3.1 - 使用 OpenGL ES 3.1 调整图像大小
我想使用 OpenGL ES 3.1 调整图像大小。作为输入,我有一个 void 指针和输出,我也想要一个 void 指针。
有人知道我该怎么做吗?有没有人有这方面的例子?
谢谢 !