From e21b1c797955a231f2bcf71818e0259fbb6aeba1 Mon Sep 17 00:00:00 2001 From: Runt <qingingrunt2010@qq.com> Date: Fri, 27 Jun 2025 15:57:25 +0000 Subject: [PATCH] 相机权限 --- LiveProject/tool/MetalRenderer.swift | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 44 insertions(+), 11 deletions(-) diff --git a/LiveProject/tool/MetalRenderer.swift b/LiveProject/tool/MetalRenderer.swift index 791dfc8..a2aa4ba 100644 --- a/LiveProject/tool/MetalRenderer.swift +++ b/LiveProject/tool/MetalRenderer.swift @@ -4,35 +4,68 @@ // 渲染工具 // Created by 倪路朋 on 6/26/25. // -import CoreVideo -import Metal import MetalKit class MetalRenderer: NSObject, MTKViewDelegate { - var device: MTLDevice! - var commandQueue: MTLCommandQueue! + private var device: MTLDevice! + private var commandQueue: MTLCommandQueue! + private var textureCache: CVMetalTextureCache! + private var currentPixelBuffer: CVPixelBuffer? func setup(view: MTKView) { self.device = view.device self.commandQueue = device.makeCommandQueue() - // 初始化 texture、pipeline 等 + CVMetalTextureCacheCreate(nil, nil, device, nil, &textureCache) } - // ✅ 必须实现的方法 1:窗口大小改变时调用 - func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { - // 可以留空或更新视图缩放、渲染区域等 + func updateFrame(pixelBuffer: CVPixelBuffer) { + self.currentPixelBuffer = pixelBuffer } - // ✅ 必须实现的方法 2:每一帧绘制时调用 + func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} + func draw(in view: MTKView) { guard let drawable = view.currentDrawable, - let descriptor = view.currentRenderPassDescriptor else { return } + let descriptor = view.currentRenderPassDescriptor, + let pixelBuffer = currentPixelBuffer else { return } + + var textureRef: CVMetalTexture? + let width = CVPixelBufferGetWidth(pixelBuffer) + let height = CVPixelBufferGetHeight(pixelBuffer) + + let status = CVMetalTextureCacheCreateTextureFromImage( + nil, textureCache, pixelBuffer, nil, + .bgra8Unorm, width, height, 0, &textureRef) + + guard status == kCVReturnSuccess, + let cvTexture = textureRef, + let texture = CVMetalTextureGetTexture(cvTexture) else { return } let commandBuffer = commandQueue.makeCommandBuffer()! let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor)! - // 渲染逻辑,如绘制纹理 + encoder.setFragmentTexture(texture, index: 0) encoder.endEncoding() + + // 简单拷贝(不做 shader 处理) + let blitEncoder = commandBuffer.makeBlitCommandEncoder()! + let dstTexture = drawable.texture + if dstTexture.width != texture.width || dstTexture.height != texture.height { + print("❌ 尺寸不一致,无法 blit:src = \(texture.width)x\(texture.height), dst = \(dstTexture.width)x\(dstTexture.height)") + return + } + blitEncoder.copy(from: texture, + sourceSlice: 0, + sourceLevel: 0, + sourceOrigin: MTLOrigin(x: 0, y: 0, z: 0), + sourceSize: MTLSize(width: width, height: height, depth: 1), + to: drawable.texture, + destinationSlice: 0, + destinationLevel: 0, + destinationOrigin: MTLOrigin(x: 0, y: 0, z: 0)) + blitEncoder.endEncoding() + commandBuffer.present(drawable) commandBuffer.commit() + print("绘制画面") } } -- Gitblit v1.9.1