ue4 android vulkan,在Android用vulkan完成蓝绿幕扣像
效果图(1080P处理)
因为摄像头开启自动曝光,画面变动时,亮度变化导致扣像在转动时如上。
这个demo主要测试二点,一是测试ndk camera集成效果,二是本项目对接外部实现的vulkan层是否方便,用于以后移植GPUImage里的实现。
我简化了在android下vulkan与opengles纹理互通里的处理,没有vulkan窗口与交换链这些逻辑,只用到vulkan compute shader计算管线得到结果然后交换给opengl里的纹理。
NDK Camera集成
主要参考 NdkCamera Sample的实现,然后封装成满足Aoce定义设备接口。
说下遇到的坑。
AIMAGE_FORMAT_YUV_420_888 可能是YUV420P,也可能是NV12,需要在AImageReader_ImageListener里拿到image通过AImage_getPlanePixelStride里的UV的plan是否为1来判断是否为YUV420P,或者看data[u]-data[y]=1来看是否为NV12.具体可以看getVideoFrame的实现。
AImageReader_new里的maxImages比较重要,简单理解为预先申请几张图,这个值越大,显示越平滑。
AImageReader_new如果不开线程,则图像处理加到这个线程里,导致读取图像变慢。打开线程处理,
我用的Redmi K10 pro,可以读40003000,在AImageReader_ImageListener回调不做特殊处理,如下错误。
首先是Unable to acquire a lockedBuffer, very likely client tries to lock more than.
可以看到,运行四次后报的,就是我设的maxImages,通过比对代码逻辑,应该是AImageReader_new读四次后,我还没处理完一桢,没有AImage_delete,也就读不了数据了.
然后检查 AImageReader_acquireNextImage 这个状态,不对不读,然后继续引发读取不可用内存问题,分析应该是处理数据的乱序线程AImage_delete可能释放别的处理线程上的image,然后处理图像线程上加上lock_guard(mutex),不会引发问题,但是会导致每maxImages卡一下,可以理解,读的线程快,处理的慢,后面想了下,直接让thread.join,图片读取很大时慢(比不开线程要快很多,40003000快二倍多,平均45ms),但是平滑的,暂时先这样,后面看能不能直接拿AImage的harderbuffer去处理,让处理速度追上读取速度。
Chroma Key
如上所说,项目对接外部实现的vulkan层是否方便,在这重新生成一个模块aoce_vulkan_extra,在这我选择UE4 Matting里的逻辑来测试,因为这个逻辑非常简单,也算让我对手机的性能有个初步的了解。
首先把相关逻辑整理下,UE4上有相关节点,看下实现整理成glsl compute shader实现。
#version 450
// https://www.unrealengine.com/en-US/tech-blog/setting-up-a-chroma-key-material-in-ue4
layout (local_size_x = 16, local_size_y = 16) in;// gl_WorkGroupSize
layout (binding = 0, rgba8) uniform readonly image2D inTex;
layout (binding = 1, rgba8) uniform image2D outTex;
layout (std140, binding = 2) uniform UBO {
// 0.2 控制亮度的强度系数
float lumaMask;
float chromaColorX;
float chromaColorY;
float chromaColorZ;
// 用环境光补受蓝绿幕影响的像素(简单理解扣像结果要放入的环境光的颜色)
float ambientScale;
float ambientColorX;
float ambientColorY;
float ambientColorZ;
// 0.4
float alphaCutoffMin;
// 0.5
float alphaCutoffMax;
float alphaExponent;
// 0.8
float despillCuttofMax;
float despillExponent;
} ubo;
const float PI = 3.1415926;
vec3 extractColor(vec3 color,float lumaMask){
float luma = dot(color,vec3(1.0f));
// 亮度指数
float colorMask = exp(-luma*2*PI/lumaMask);
// color*(1-colorMask)+color*luma
color = mix(color,vec3(luma),colorMask);
// 生成基于亮度的饱和度图
return color / dot(color,vec3(2.0));
}
void main(){
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = imageSize(outTex);
if(uv.x >= size.x || uv.y >= size.y){
return;
}
vec3 inputColor = imageLoad(inTex,uv).rgb;
vec3 chromaColor = vec3(ubo.chromaColorX,ubo.chromaColorY,ubo.chromaColorZ);
vec3 ambientColor = vec3(ubo.ambientColorX,ubo.ambientColorY,ubo.ambientColorZ);
vec3 color1 = extractColor(chromaColor,ubo.lumaMask);
vec3 color2 = extractColor(inputColor,ubo.lumaMask);
vec3 subColor = color1 - color2;
float diffSize = length(subColor);
float minClamp = diffSize-ubo.alphaCutoffMin;
float dist = ubo.alphaCutoffMax - ubo.alphaCutoffMin;
// 扣像alpha
float alpha= clamp(pow(max(minClamp/dist,0),ubo.alphaExponent),0.0,1.0);
// 受扣像背景影响的颜色alpha
float inputClamp = ubo.despillCuttofMax - ubo.alphaCutoffMin;
float despillAlpha = 1.0f- clamp(pow(max(minClamp/inputClamp,0),ubo.despillExponent),0.0,1.0);
// 亮度系数
vec3 lumaFactor = vec3(0.3f,0.59f,0.11f);
// 添加环境光收益
vec3 dcolor = inputColor*lumaFactor*ambientColor*ubo.ambientScale*despillAlpha;
// 去除扣像背景
dcolor -= inputColor*chromaColor*despillAlpha;
dcolor += inputColor;
// 为了显示查看效果,后面屏蔽
dcolor = inputColor*alpha + ambientColor*(1.0-alpha);
imageStore(outTex,uv,vec4(dcolor,alpha));
}
这里面代码最后倒数第二句实现混合背景时去掉,在这只是为了显示查看效果。
然后引用aoce_vulkan里给的基类VkLayer,根据接口完成本身具体实现,相关VkChromKeyLayer的实现可以说是非常简单,至少我认为达到我想要的方便。
还是一样,先说遇到的坑,
开始在glsl中的UBO,我特意把一个float,vec3放一起,想当然的认为是按照vec4排列,这里注意,vec3不管前后接什么,大部分结构定义下,都至少占vec4,所以后面为了和C++结构align一样,全部用float.
层启用/不启用会导致整个运算graph重置,一般情况下,运算线程与结果输出线程不在一起,在重置时,运算线程相关资源会重新生成,而此时输出线程还在使用相关资源就会导致device lost错误,在这使用VkEvent用来表示是否在资源重置中。
然后就是与android UI层对接,android的UI没怎么用过,丑也就先这样吧。
ue4 android vulkan,在Android用vulkan完成蓝绿幕扣像相关推荐
- 在Android用vulkan完成蓝绿幕扣像
Chroma Key 如上所说,项目对接外部实现的vulkan层是否方便,在这重新生成一个模块aoce_vulkan_extra,在这我选择UE4 Matting里的逻辑来测试,因为这个逻辑非常简单, ...
- 关于 Vulkan 简介 —— Android N 引入新的 3D 渲染引擎
关于 Vulkan Vulkan 被视作是 OpenGL 的后续产品. 它是一种多平台 API,可支持开发人员准备游戏.CAD 工具.性能基准测试等高性能图形应用. 它可在不同的操作系统(比如 Win ...
- 虚幻引擎UE4.25版本使用Android打包出错提示:ERROR: cmd.exe failed with args /c 和 :app:assembleDebug的解决方法
虚幻引擎 UE4.25版本使用Android打包出错提示:ERROR: cmd.exe failed with args /c 和 :app:assembleDebug的解决方法: 在虚幻引擎的jdk ...
- UE4查看材质在android设备上的性能开销
在材质编辑器中点击平台统计(Platform Stats)图标即可查看材质在不同平台上的开销. 要查看 Android 的统计数据,需要先安装 Mali离线编译器.没有离线编译器就无法看到Androi ...
- Vulkan与OpenGL对比——Vulkan的全新渲染架构
OpenGL是Khronos Group组织发布的跨平台图像渲染引擎.在这里科普一下Khronos组织,由Intel.Nvidia等公司共同创立,致力于创建开放标准的应用程序API.大名鼎鼎的Open ...
- vulkan学习_使用vulkan kompute在gpu中进行机器学习和数据处理
vulkan学习 Machine learning, together with many other advanced data processing paradigms, fits incredi ...
- android layout组件,Android UI学习 - Linear Layout, RelativeLayout
1.一些常用的公共属性介绍 1) layout_width -宽 fill_parent: 宽度和父元素相同,wrap_content: 宽度随本身的内容所调整,或者指定 px值来设置宽 2) lay ...
- android:layout_gravity 和 android:gravity 的区别
gravity 这个英文单词是重心的意思,在这里就表示停靠位置的意思. android:layout_gravity 和 android:gravity 的区别 从名字上可以看到,android:gr ...
- Android横向伸缩,Android 实现伸缩布局效果示例代码
最近项目实现下面的图示的效果,本来想用listview+gridview实现,但是貌似挺麻烦的于是就用flowlayout 来addview实现添加伸缩的效果,实现也比较简单. mainActivit ...
最新文章
- 蓝桥杯国赛知识点汇总
- Active Diretory 全攻略(八)--组策略(2)
- HBase 性能优化笔记
- Lesson 021 —— python 循环语句
- 用Android Studio开发Java App (Runnable Jar)
- CF1616F Tricolor Triangles(构造、高斯消元)
- 力扣231.2的幂 C语言
- U-Mail邮件服务器教你反垃圾邮件新方法
- linux下搭建apache+mysql+php环境(LAMP)
- 【 Codeforces Round #547 (Div. 3) F2】Same Sum Blocks (Hard)【思维贪心】
- Outlook2016邮箱配置说明文档
- 除了PS,这几款设计软件也是我的最爱
- C语言版本STFT/ISTFT
- mysql.sock介绍
- 让windows保持常亮(不息屏,不锁屏,不进入屏保)
- 驱动精灵 v9.61 去广告最终版绿色清爽单文件
- 一种高效的q+1准均匀量化(quasi-uniform quantization)方法及MATLAB实现
- 大数据和区块链技术是什么关系?
- 虚拟主机、云主机和云服务器有什么不同?
- MNIST是什么鬼?
热门文章
- mysql数据库名长可为64字符,MySQL数据库设计规范
- Java之接口的静态方法的定义和使用
- mysql事务回滚后,自增ID仍然增加
- Java IO流之PrintStream分析
- 在Spring Boot + Mybatis 中,使用@Repository失效
- flink checkpoint 恢复_Flink解析 | Apache Flink结合Kafka构建端到端的ExactlyOnce处理
- pythonweb面试常见问题_python和web框架面试题目整理(3)
- linux shell 执行目录,bash shell脚本执行的几种方法
- MySQL 基础 ———— 变量
- Swagger使用————接口参数注解的使用缺陷