首页 > 其他分享 >Swift Metal渲染视频

Swift Metal渲染视频

时间:2022-10-09 16:02:52浏览次数:76  
标签:blendColor 渲染 Metal Da let Sa Swift 着色器

一、基本Metal概念 

Metal是iOS推出的图像渲染工具,类似于OpenGL,Metal为图形和数据并行计算工作负载提供单一,统一的编程接口和语言。 Metal使您能够更有效地集成图形和计算任务,而无需使用单独的API和着色器语言。

Metal框架提供以下内容:

  • Low-overhead interface - 低开销接口。 Metal旨在消除“隐藏”性能瓶颈,例如隐式状态验证。您可以控制GPU的异步行为,以实现用于并行创建和提交命令缓冲区的高效多线程。

有关Metal命令提交的详细信息,请参阅Command Organization and Execution Model

  • Memory and resource management - 内存和资源管理。 Metal框架描述了表示GPU内存分配的缓冲区和纹理对象。纹理对象具有特定的像素格式,可用于纹理图像或附件。

有关Metal内存对象的详细信息,请参阅Resource Objects: Buffers and Textures

  • Integrated support for both graphics and compute operations - 集成了对图形和计算操作的支持。 Metal为图形和计算操作使用相同的数据结构和资源(如缓冲区,纹理和命令队列)。此外,Metal着色语言支持图形和计算函数。 Metal框架允许在运行时接口,图形着色器和计算函数之间共享资源。

有关编写使用Metal进行图形渲染或数据并行计算操作的应用程序的详细信息,请参阅Graphics Rendering: Render Command EncoderData-Parallel Compute Processing: Compute Command Encoder

  • Precompiled shaders - 预编译着色器。可以在构建时编译Metal着色器以及应用程序代码,然后在运行时加载。此工作流程提供了更好的代码生成以及更简单的着色器代码调试。 (Metal还支持着色器代码的运行时编译。)

有关使用Metal框架代码中的Metal着色器的详细信息,请参阅Functions and Libraries。有关Metal Shading Language Guide本身的详细信息,请参见Metal Shading Language Guide

二、创建连接Metal文件

1、创建metal文件第一步要获取Metal设备就是手机等设备、获取命令队列

init(){
        guard let device = MTLCreateSystemDefaultDevice() else{
            fatalError("Could not create Metal Device")
        }
        self.device = device
        guard let queue = self.device.makeCommandQueue() else{
            fatalError("Could not create command queue")
        }
        self.commandQueue = queue
        
//        let frameworkBundle = Bundle.main
//        guard let metalLibraryPath = frameworkBundle.path(forResource: "default", ofType: "metallib")else{
//            fatalError("Could not load library")
//        }
        do {
            self.shaderLibrary = try device.makeDefaultLibrary(bundle: Bundle.main)
        } catch  {
            fatalError("Could not load library")
        }
    }

 2、创建metal文件、编写着色器代码

 

 编写顶点着色器和片元着色器代码

//
//  BlendModeConstants.metal
//  DQVideoEditor
//
//  Created by zhaoquan.du on 2022/9/26.
//

#include <metal_stdlib>
#include "OperationShaderTypes.h"
#include "BlendModeConstants.h"
using namespace metal;

vertex SingleInputVertexIO blendOperationVertex(const device packed_float2 *position [[ buffer(0) ]],
                                                const device packed_float2 *texturecoord [[ buffer(1) ]],
                                                constant float4x4& modelView [[ buffer(2) ]],
                                                constant float4x4& projection [[ buffer(3) ]],
                                                uint vid [[vertex_id]])
{
    SingleInputVertexIO outputVertices;
    
    outputVertices.position = projection * modelView * float4(position[vid], 0, 1.0);
    outputVertices.textureCoordinate = texturecoord[vid];
    
    return outputVertices;
}

half4 normalBlend(half3 Sca, half3 Dca, half Sa, half Da) {
    half4 blendColor;
    blendColor.rgb = Sca + Dca * (1.0 - Sa);
    blendColor.a = Sa + Da - Sa * Da;
    return blendColor;
}

half4 darken(half3 Sca, half3 Dca, half Sa, half Da) {
    half4 blendColor;
    blendColor.rgb = min(Sca * Da, Dca * Sa) + Sca * (1.0 - Da) + Dca * (1.0 - Sa);
    blendColor.a = Sa + Da - Sa * Da;
    return blendColor;
}

half4 multiply(half3 Sca, half3 Dca, half Sa, half Da) {
    half4 blendColor;
    blendColor.rgb = Sca * Dca + Sca * (1.0 - Da) + Dca * (1.0 - Sa);
    blendColor.a = Sa + Da - Sa * Da;
    return blendColor;
}

fragment half4 blendOperationFragment(SingleInputVertexIO fragmentInput [[stage_in]],
                                      texture2d<half> inputTexture [[texture(0)]],
                                      half4 backColor [[color(0)]],
                                      constant int& blendMode [[ buffer(1) ]],
                                      constant float& blendOpacity [[ buffer(2) ]])
{
    constexpr sampler quadSampler;
    half4 sourceColor = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate);
    
    half3 Sca = sourceColor.rgb;
    half3 Dca = backColor.rgb;
    half Sa = sourceColor.a;
    half Da = backColor.a;
    
    half4 blendColor;
    if (blendMode == BlendModeNormal) {
        blendColor = normalBlend(Sca, Dca, Sa, Da);
    } else if (blendMode == BlendModeDarken) {
        blendColor = darken(Sca, Dca, Sa, Da);
    } else if (blendMode == BlendModeMultiply) {
        blendColor = multiply(Sca, Dca, Sa, Da);
    } else {
        blendColor = half4(0.0, 0.0, 0.0, 1.0);
    }

    return mix(backColor, blendColor, blendOpacity);
}

 3.创建渲染管道,保存着色器参数类型

func generateRenderPipelineState(vertexFunctionName:String, fragmentFunctionName:String, oprationName:String) -> (MTLRenderPipelineState, [String: UniformInfor], [String: UniformInfor]){
    //获取顶点着色器函数
    guard let vertexFunction = sharedMetalRenderingDevice.shaderLibrary.makeFunction(name: vertexFunctionName) else{
        fatalError("\(oprationName):could not compile vertex function \(vertexFunctionName)")
    }
    //获取片元着色器函数
    guard let fragmentFuntion = sharedMetalRenderingDevice.shaderLibrary.makeFunction(name: fragmentFunctionName) else{
        fatalError("\(oprationName): could not compile fragment function \(fragmentFunctionName)")
    }
    //配置渲染管道描述符
    let descriptor = MTLRenderPipelineDescriptor()
    descriptor.colorAttachments[0].pixelFormat = MTLPixelFormat.bgra8Unorm
    descriptor.rasterSampleCount = 1
    descriptor.vertexFunction = vertexFunction
    descriptor.fragmentFunction = fragmentFuntion
    
    do {
        //创建渲染管道
        var reflection: MTLAutoreleasedRenderPipelineReflection?
        let pipLinState = try sharedMetalRenderingDevice.device.makeRenderPipelineState(descriptor: descriptor,options: [.bufferTypeInfo, .argumentInfo],reflection: &reflection)
        //获取着色器函数 参数类型,以便之后传惨
        var vertexUniforms: [String: UniformInfor] = [:]
        var fragmentUniforms = [String : UniformInfor]()
        if #available(iOS 16.0, *) {
            if let vertexBudings = reflection?.vertexBindings as? [MTLBufferBinding]{
                for bufferBuding in vertexBudings {
                    let uniformInfor = UniformInfor(locationIndex: bufferBuding.index, dataSize: bufferBuding.bufferDataSize)
                    vertexUniforms[bufferBuding.name] = uniformInfor
                }

            }
            //片元着色器中参数 banging中有 MTLTextureBinding 和 MTLBufferBinding,需要过滤一下
            if let fragmentBudings = reflection?.fragmentBindings.compactMap({$0 as? MTLBufferBinding}) as? [MTLBufferBinding]{
                for bufferBuding in fragmentBudings {
                    let uniformInfor = UniformInfor(locationIndex: bufferBuding.index, dataSize: bufferBuding.bufferDataSize)
                    fragmentUniforms[bufferBuding.name] = uniformInfor
                }

            }
            
        } else {
            if let vertexArguments = reflection?.vertexArguments  {
                for vertexArgument in vertexArguments where vertexArgument.type == .buffer {
                    let uniformInfor = UniformInfor(locationIndex: vertexArgument.index, dataSize: vertexArgument.bufferDataSize)
                    vertexUniforms[vertexArgument.name] = uniformInfor
                }
                
            }
            
            if let fragmentArguments = reflection?.fragmentArguments {
                for fragmentArgument in fragmentArguments where fragmentArgument.type == .buffer {
                    let uniformInfor = UniformInfor(locationIndex: fragmentArgument.index, dataSize: fragmentArgument.bufferDataSize)
                    fragmentUniforms[fragmentArgument.name] = uniformInfor
                }
            }
        }
        
        return (pipLinState, vertexUniforms, fragmentUniforms)
        
    } catch  {
        fatalError("Could not create render pipeline state for vertex:\(vertexFunctionName), fragment:\(fragmentFunctionName), error:\(error)")
    }
    
}

 

标签:blendColor,渲染,Metal,Da,let,Sa,Swift,着色器
From: https://www.cnblogs.com/duzhaoquan/p/16772428.html

相关文章

  • 微信小程序使用wx.request请求服务器json数据并渲染到页面操作示例
    wx.request({url:'http://www.likeyunba.com/test/test.json',headers:{'Content-Type':'application/json'},success:function(res){//......
  • nuxt 服务端渲染注意事项
    1.路由nuxt按照pages文件夹的目录结构自动生成路由http://localhost:3000/user/reg相当于去访问pages文件夹下的user文件夹下的reg.vuevue需在src/router/in......
  • Qt WA_TranslucentBackground 导致视频渲染不了的问题
    在使用 WA_TranslucentBackground 做蒙板时出现渲染不会自动清除出现堆叠现象。博客园中找到一个解释:QtWA_TranslucentBackground导致视频渲染不......
  • vue-5 条件渲染/ 列表渲染
    <template> <div>  <h1style="background-color:yellowgreen;width:auto;">--------v-if--------</h1>  条件:type==  <selectv-model="type"> ......
  • 浏览器的渲染过程、回流、重绘
    一、浏览器的渲染过程1.根据HTML生成DOM树浏览器在接收到服务器发来的HTML文件是字节形式的,首先要将字节形式的HTML组建成字符串,然后将字符串转换成token,再将token组装......
  • React的零渲染问题及源码分析
    开门见山,先来看一张bug图(状态下面有个00)。预期是:状态为0时,2个组件不做渲染。现状:状态为0时,2个组件不做渲染,但是渲染出了00。零渲染bug代码如何修复零渲染问题初窥源码源......
  • Swift 周报 第十期
    前言前几期周报内容是同步翻译的英文版周报,目前英文版停更,周报停滞半年多。经过多次讨论,我们决定重启周报,分模块整理内容同步给大家。周报内容模块分为:新闻、提案、Swift论......
  • C4D 2023插件:Arnold for mac(C4D S2023阿诺德渲染器)
     Arnold是一款先进的蒙特卡洛光线追踪渲染器,专为动画长度和视觉效果的需求而打造。C4DtoA4.4.0使用Arnold7.1.3.1 ,是一个功能版本,带来了对Cinema4D2023中OCI......
  • ImGui渲染3d元素的方法
    目前主要有2种方法:一是简单场景,可以自己处理3维坐标向屏幕坐标的转换,然后调用ImGui的二维绘制函数进行渲染;二是复杂场景,首先在3d引擎侧渲染到bufferframe,然后调用ImGui的......
  • 计算机视觉与图形学-神经渲染专题-动态场景下的时序视图合成
    在低计算设备上渲染高帧速率视频的问题可以通过定期预测未来帧来解决,以增强虚拟现实应用程序中的用户体验。这是通过时间视图合成(TVS)问题来研究的,其目标是在给定前一帧以及......