save code
This commit is contained in:
@@ -49,6 +49,15 @@ struct InitArg
|
||||
};
|
||||
|
||||
|
||||
// 推送给 shader 的常量。前 9 个 float 是「业务原始值」,单位以 480x480 设计画布
|
||||
// 为基准(向后兼容):业务给 radius=240 / offset_x=200 / offset_y=-200 等都按这个画布
|
||||
// 思考。后 3 个 float 是 SDK 在每次 render() 时根据当前 swapchain 尺寸计算并写入的
|
||||
// 「画布几何」,shader 通过它把「画布坐标」映射到「屏幕坐标」并把圆形 mask 中心
|
||||
// 锚定在屏幕中心。
|
||||
//
|
||||
// ★ 字段顺序和命名必须和 GLSL 中的 layout(push_constant) 块严格一致,否则会读到
|
||||
// 错位数据。修改时四个 shader (bg.vert / bg.frag / texture.vert / texture.frag)
|
||||
// 都要同步更新。
|
||||
struct PushConstants {
|
||||
float zoom = 0.5f;
|
||||
float r = 0;
|
||||
@@ -59,6 +68,32 @@ struct PushConstants {
|
||||
float uy = 0;
|
||||
float offset_x = 0;
|
||||
float offset_y = 0;
|
||||
// 由 SDK 在 FaceApp::render() 内每帧写入,业务无感。
|
||||
// canvas_size = min(swapchain.w, swapchain.h),单位:物理像素
|
||||
// screen_w / screen_h = swapchain 当前实际尺寸,单位:物理像素
|
||||
// 设计画布始终居中铺在屏幕中央正方形区域;外围是 letterbox 黑边。
|
||||
float canvas_size = 480.0f;
|
||||
float screen_w = 480.0f;
|
||||
float screen_h = 480.0f;
|
||||
|
||||
// 相机帧元信息,由 SDK 在收到第一帧 / 帧尺寸变化时更新。shader 用来:
|
||||
// 1) 把相机帧(任意 raw aspect)正确 cover 到 1:1 画布;
|
||||
// 2) 按 camera_rotation 旋转 UV,让画面在屏幕上正立——这是不同手机的
|
||||
// sensor orientation 不同导致画面侧着 / 倒着的根因。
|
||||
// camera_aspect = camera_raw_w / camera_raw_h(典型 4:3 = 1.333…)
|
||||
// camera_rotation = CameraX 的 ImageInfo.getRotationDegrees(),
|
||||
// 表示「图像顺时针旋转多少度才能正立」,离散 0/90/180/270。
|
||||
// 默认值 4/3 + 90° 是兼容老 hardcode 行为(大部分 Android 手机后置主摄竖屏)。
|
||||
float camera_aspect = 4.0f / 3.0f;
|
||||
float camera_rotation = 90.0f;
|
||||
|
||||
// 镜像标志:1.0 表示前置摄像头需要"镜子效果",所有顶点 shader 会把
|
||||
// gl_Position.x 翻转一次(NDC 水平翻转)。配合 FaceLandmarkerHelper 在
|
||||
// bitmap 阶段做的 postScale(-1,1),bg 与 face 同步翻转、互相对齐。
|
||||
// 后置摄像头此值为 0.0,shader 短路无开销。
|
||||
// 用 float 而不是 bool/int 是为了和 Vulkan push constant 4-byte 对齐 + GLSL
|
||||
// 端 layout 简单一致;shader 里 `1.0 - 2.0 * mirror_x` 实现无分支翻转。
|
||||
float mirror_x = 0.0f;
|
||||
};
|
||||
|
||||
using Callback = std::function<void()>;
|
||||
@@ -163,13 +198,64 @@ private:
|
||||
|
||||
|
||||
//float myFloatValue = 1.5f;
|
||||
// 「业务原始值」缓存:SetInitArg 把 InitArg 拷到这里,render() 每帧读出来再
|
||||
// 缩放 + 注入屏幕几何。注意 ux/uy 由 motion 帧每帧写入,也保留在这里。
|
||||
PushConstants pushConstants;
|
||||
|
||||
// ===== 屏幕分辨率适配 =====
|
||||
// 原 SDK 把屏幕写死 480x480,所有业务参数都按 480 像素画布给。现在改成支持
|
||||
// 任意分辨率:把"屏幕中央 min(w,h) 边长的正方形"作为设计画布,画布外是黑边。
|
||||
// 业务参数语义不变,SDK 在 render() 里按 (canvas_size / 480) 缩放成屏幕物理
|
||||
// 像素后再推给 shader。
|
||||
// m_canvasSize = min(swapChainExtent.w, swapChainExtent.h)
|
||||
// m_screenW / m_screenH = swapChainExtent.w / swapChainExtent.h
|
||||
// updateCanvasMetrics() 由 render() 在每次 vkCmdPushConstants 之前调用。
|
||||
// 因为 swapchain 重建会走 onWindowLost -> onWindowInit ->
|
||||
// recreatePipelinesForSwapchain,而 render() 永远在 drawFrame 里被调,所以
|
||||
// 这套数值天然会跟随 swapchain 变化。
|
||||
float m_canvasSize = 480.0f;
|
||||
float m_screenW = 480.0f;
|
||||
float m_screenH = 480.0f;
|
||||
void updateCanvasMetrics();
|
||||
|
||||
// ===== 相机帧元信息适配 =====
|
||||
// 不同手机摄像头物理分辨率和 sensor orientation 都不一样,CameraX 给的图像
|
||||
// 既不一定是精确 4:3,也不一定是「正立」朝向。SDK 在这里缓存最近一帧的
|
||||
// (raw_aspect, rotation),render() 时塞进 push constant 让 shader 自己处理:
|
||||
// - bg.vert 按 m_cameraRotation 旋转 UV,让画面在屏幕上方向正确
|
||||
// - bg.vert 按 m_cameraAspect 自适应 cover 画布,避免拉扁/拉长
|
||||
// 由 processCameraFrame() 根据每次相机帧实际 width / height / rotation 更新。
|
||||
// 第一帧之前用安全默认值(4:3 + 90°,对应大部分 Android 后置主摄竖屏行为)。
|
||||
float m_cameraAspect = 4.0f / 3.0f;
|
||||
float m_cameraRotation = 90.0f;
|
||||
// 镜像标志缓存:与 m_cameraAspect 同写者(相机分析线程),由 render() 拷到
|
||||
// push constant 的 mirror_x 字段。前置=1.0,后置=0.0。
|
||||
float m_mirrorX = 0.0f;
|
||||
public:
|
||||
// JNI 入口(main.cpp)调用,用来在每帧上传相机纹理之前同步元信息。
|
||||
// 内部会:
|
||||
// 1) 检测 width × height 与已有 tex_bg 是否一致,不一致就 destroy + recreate;
|
||||
// 2) 更新 m_cameraAspect / m_cameraRotation / m_mirrorX;
|
||||
// 3) 调用 base 的 processWithVulkan 走 staging buffer 上传。
|
||||
// mirrorX 来自 Java 层 lensFacing == LENS_FACING_FRONT,表示是否需要镜子效果。
|
||||
// 必须由唯一的相机分析线程调用(FaceActivity backgroundExecutor),
|
||||
// 内部依赖 createTextureMtx 序列化与 drawFrame / cleanup 的并发。
|
||||
void processCameraFrame(uint8_t* data, int width, int height,
|
||||
int rowStride, size_t dataSize, int rotation,
|
||||
bool mirrorX);
|
||||
private:
|
||||
|
||||
|
||||
|
||||
void create_pipelines_bg();
|
||||
void setup_descriptor_set_layout_bg();
|
||||
void setup_descriptor_set_bg();
|
||||
// 把 m_descriptor_set_bg 重新绑定到当前的 tex_bg.view / sampler。
|
||||
// 当相机分辨率变化导致 tex_bg 被 destroy + recreate 后,新建的 image
|
||||
// 有新的 VkImageView 句柄,旧的 descriptor set 里缓存的 handle 失效,
|
||||
// 必须 vkUpdateDescriptorSets 让 descriptor 指向新 view。该函数不重新
|
||||
// 分配 descriptor set,仅刷新绑定。
|
||||
void refresh_descriptor_set_bg();
|
||||
VkPipeline m_graphicsPipeline_bg = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_pipelineLayout_bg = VK_NULL_HANDLE;
|
||||
VkDescriptorSetLayout m_descriptorSetLayout_bg = VK_NULL_HANDLE;
|
||||
|
||||
Reference in New Issue
Block a user