晚香玉 1.6.1

晚香玉 1.6.1

Reza Ali 维护。



晚香玉 1.6.1

晚香玉 - 基于苹果Metal构建的3D图形框架

关于👋

晚香玉是一个3D图形框架(受threejs启发),它帮助设计师和开发者与苹果的Metal API一起工作。晚香玉提供了创建网格、材料、缓冲区、统一变量、几何体、管道(着色器)、计算核心等有用的类,并将它们渲染到屏幕或纹理上。

晚香玉使简单的图形任务变得有趣且易于快速完成,同时使复杂的图形任务更容易完成,而无需编写大量样板代码。它通过提供结构、观点以及在Metal上提供许多有用的抽象来做到这一点,以帮助您在几分钟内开始渲染/编码。

晚香玉主要基于Swift编写,然而当进行昂贵的CPU操作时,晚香玉使用SatinCore,它是用C编写的(用于几何生成、三角化、边界和计算几何计算等任务),以确保尽可能快。

示例

要求⚙️

  • macOS 10.15。
  • Xcode 11.0。
  • Swift 5.0。

支持的平台💻 📱 📺

  • macOS 10.15。
  • iOS 13.0.
  • tvOS 13.0.

安装

Swift Package Manager

Swift Package Manager 是一个用于自动分发 Swift 代码的工具,并集成到 Swift 编译器中。一旦您设置了 Swift 包,添加 Satin 作为依赖项就像将其添加到 Package.swiftdependencies 值一样简单。

  dependencies: [
      .package(url: "https://github.com/Hi-Rez/Satin.git", .branch("master"))
  ]

CocoaPods

CocoaPods 是 Cocoa 项目的集中式依赖管理器。有关使用和安装说明,请访问他们的网站。要使用 CocoaPods 将 Satin 集成到您的 Xcode 项目中,请在 Podfile 中指定它。

pod 'Satin'

功能📋

  • 大量示例,展示如何使用 API(2D、3D、光线追踪、计算、导出、实时编码、AR 等)。
  • 对象、网格、材质、着色器、几何形状和渲染器类。
  • 您可以实时编写着色器🔥.
  • 一些内置的材质(基础颜色、基础纹理、基础漫反射、法线、UV 颜色、天空盒、MatCap 等)。
  • 大量几何形状(盒子、球体、IcoSphere、圆形、圆锥体、四边形、平面、胶囊、圆角矩形、文本等)。
  • 摄像机(正交、透视)。
  • 2D 和 3D 摄像机控制器。
  • 通过参数使用缓冲区和统一变量创建实时和动态结构。
  • 金属着色器编译器(实时编码时很有用),用于 LiveShader(在 LiveMaterial 中使用)。
  • 用于高速处理数据的缓冲区和纹理计算系统。
  • 快速的GPU光线投射器(非常有助于查看您点击或轻触的位置)。
  • 自定义Metal渲染钩子:Mesh的preDraw、Material的onBind、Buffer & Texture Computes的preCompute等
  • FileWatcher用于检查资源或着色器文件是否已更改。

用法🚀

Satin帮助在Metal支持的视图中绘制事物。为了快速启动并运行,而不需要大量样板代码,也不必担心三缓冲或事件(设置、更新、调整大小、键盘、鼠标、触摸)回调,Satin与Forge配合良好,但也可以单独使用。下面的示例显示了如何协同使用Forge & Satin来渲染一个查看场景中移动点的颜色变化的盒子。

简单示例

import SwiftUI
import MetalKit

import Forge
import Satin

// Subclass Forge's Renderer to get triple buffered rendering and 
// callbacks for Setup, Update, Draw, Resize and Events
class SimpleRenderer: Forge.Renderer {

    // A Context contains important information that is needed to help compile shaders 
    // and ensure we are drawing with the right color and depth pixel formats and sample count
    var context: Context!

    // A Satin Renderer handles setting the Content on all the objects in the scene graph 
    // and drawing the scene either to a texture or on screen  
    var renderer: Satin.Renderer!
    
    // A PerspectiveCamera is used to render the scene using perspective projection 
    // All Satin Cameras inherit from Object, so it has 
    var camera: PerspectiveCamera!
    
    // An Object is just an empty node in Satin's Scene Graph, it can have children and a parent
    // Objects have a position, orientation, scale and label 
    var scene: Object = Object("Scene")
        
    // Meshes inherit from Object, so they have all the properties an object has. 
    // A Mesh has unique properties like geometry, material and rendering properties
    // To create renderable object aka a Mesh, you passing it a Geometry and Material like so
    var boxMesh = Mesh(geometry: BoxGeometry(size: 1.0), material: BasicDiffuseMaterial(0.75))
    
    // Create a time variable so we can change things in our scene over time
    var time: Float = 0.0

    // Forge calls setup once after it has a valid MTKView (mtkView)
    override func setup() {
        // Forge's Renderer class provides a MTLDevice and convenience getters for the view's color pixel format, 
        // depth pixel format and stencil pixel format, by default a Forge Renderer has depth
        context = Context(device, sampleCount, colorPixelFormat, depthPixelFormat, stencilPixelFormat)
        
        // When creating a camera, you can specify an initial position and the near and far plane values
        camera = PerspectiveCamera(position: [0.0, 0.0, 5.0], near: 0.01, far: 100.0)
        
        // Create a Satin Renderer by passing in a context, scene and camera
        renderer = Satin.Renderer(context: context, scene: scene, camera: camera)
        // There are many properties you can set on the renderer, this is how to clear to white
        renderer.setClearColor([1, 1, 1, 1])
        
        //Finally add the box mesh created above to the scene
        scene.add(boxMesh)
    }
    
    // Forge calls update whenever a new frame is ready to be updated, make scene changes here
    override func update() {
        // We increment our time variable so we can procedurally set the box mesh's orientation and material color
        time += 0.05
        let sx = sin(time)
        let sy = cos(time)
        
        // Setting a material property done by using the set function, this modifies the material's uniforms
        boxMesh.material?.set("Color", [abs(sx), abs(sy), abs(sx + sy), 1.0])
        
        // You can manually an object's position, orientation, scale, and localMatrix. Here I'm using a 
        // convenience lookAt function to orient the box to face the point passed from its current position
        boxMesh.lookAt([sx, sy, 2.0])
    }

    // Forge calls draw when a new frame is ready to be encoded for drawing
    override func draw(_ view: MTKView, _ commandBuffer: MTLCommandBuffer) {
        guard let renderPassDescriptor = view.currentRenderPassDescriptor else { return }

        // To render a scene into a render pass, just call draw and pass in the render pass descriptor
        // You can also specify a render target and render to a texture instead
        renderer.draw(renderPassDescriptor: renderPassDescriptor, commandBuffer: commandBuffer)
    }
    
    // Forge calls resize whenever the view is resized
    override func resize(_ size: (width: Float, height: Float)) {
        // whenever the screen is resized we need to make sure:  
        
        // our camera's aspect ratio is set
        camera.aspect = size.width / size.height

        // our renderer's viewport & texture sizes are set 
        renderer.resize(size)
        // if you need to render to a custom viewport, you can specify that after the resize call: 
        // renderer.viewport = MTLViewport(...)
    }   
}

// Using SwiftUI you can use a ForgeView to easily create a MTKView and pass in a Forge.Renderer
struct ContentView: View {
    var body: some View {
        ForgeView(renderer: SimpleRenderer())
    }
}

待办事项

  • 更多文档
  • 实例化网格
  • 线网格
  • 基于物理的着色、光照、阴影
  • SDF文本渲染
  • 圆角Box几何结构
  • 灵活的顶点结构
  • 光线追踪计算系统

贡献🎉

  • 将您的想法作为功能请求提交给本项目。
  • 创建错误报告以帮助我们改进。
  • 启动讨论以给我们反馈需要改进或构建的内容。
  • 提出您自己的修复建议,并通过创建带有更改的pull request。

行为准则💬

保持友好。没有愚蠢的问题。

致谢😎

Satin 由 Reza Ali 拥有并维护。你可以在 Twitter 上关注我 @rezaali,或通过 邮件 联系我以获得项目更新、发布和问题。

支持🙌

Satin 是一项充满爱心的劳动成果,精心制作,使用方便,快速友好。如果您在使用项目中使用 Satin,请考虑支持该项目。以前的赞助商包括:The Frank-Ratchye STUDIO for Creative Inquiry

许可🎓

Satin 根据 MIT 许可证发布。有关详细信息,请参阅 LICENSE