VisionPro开发 - PBR基本概念


首页:漫游Apple Vision Pro

Code Repo: github.com/xuchi16/vis...

Project Path: github.com/xuchi16/vis...


本文主要包含以下内容:

  • PBR 的基本概念
  • Metallic, roughness 和 opacity 的改变对材质的影响

目标及设计

PBR(Physically based renderring)通过模拟真实世界中光线和材质的相互作用进行物体渲染。它有两种工作流用于定义材料表现:

  • Metallic Roughness Workflow
  • Specular-Glossiness Workflow

两者贴图参数有所区别,但效果相同。从下图可以发现,它们均包含了 6 种贴图,其中有 3 个是相同的(Ambient Occlusion, Normal 和 Height),而另外 3 个有所区别:

  • Metallic Roughness Workflow 使用 baseColor、metallic 和 roughness 贴图来表示材质的颜色、金属度和粗糙度

  • Specular-Glossiness Workflow 则使用 diffuse、glossiness 和 specular 贴图来表示材质的颜色、光泽度和镜面反射率

Apple 推荐了三种 Renderer:RealityKit,SceneKit 和 Storm,均支持 Metallic Roughness Workflow,后续也只详述该工作流。

Metallic Roughness Workflow

Metallic Roughness Workflow 工作流的着色器以金属、粗糙度和基础颜色值作为其核心输入。包含如下 6 种贴图

  • Base Color:提供颜色信息
  • Roughness:提供材料的粗糙程度,浅色表示粗糙,深色表示光滑,可以用来表示镜面上的指纹、桌上的杯子水渍等
  • Metallic:提供对应位置材质是否是金属,如果是金属则为白色,如果不是金属则为黑色
  • Ambient Occlusion:用于表示环境光遮蔽
  • Normal:法线贴图,引擎会根据法线决定光的反射方向
  • Height:表示材质表面的深浅

Metallic 值:0-1 之间,越接近 1,金属度越高

Roughness 值:0-1 之间,越接近 1,粗糙度越高

PBR 的 3 个主要理论

  • 微平面理论:物体表面从微观上看总是粗糙的
  • 能量守恒:出射光线能量不能超过入射光线能量
  • 菲涅尔反射:入射角越大,反射率越高

    • 入射角在 0°到 45°时反射率较低
    • 45°到 75°时反射率逐渐升高
    • 75°到 90°之间时反射率快速趋近于 100%

PBR 光照

Lighting = Ambient + Diffuse + Specular + Emissive

最终颜色 = 环境光 + 漫反射 + 高光反射 + 自发光

双向反射分布函数 BRDF: Bidirectional Reflectance Distribution Function

第一项表示的是物体自发光,后续积分项表示了其他光线的反射情况,其中 BRDF 决定了不同光线的反射方式。不同的光照采用不同的 BRDF 模型,如:

  • Lambertian BRDF:常用于计算漫反射 Diffuse

  • Cook-Torrance BRDF: 常用于计算高光反射 Specular

另外在 PBR 中,环境光通常用 IBL(Image Based Lighting)来计算,RealityKit 也支持 IBL 光照。IBL 的核心概念是生成一张环境贴图,其中包含了场景中的光照信息,在渲染时候引擎根据相机位置从贴图中获取到每个像素的光照信息,再结合物体材质属性,计算出场景中各个像素的光照。

示例基本实现

选定基准位置,在 3 个方向上分别对 roughness,metallic 和 opacity 进行改变即可。

  • x 轴方向:roughness 改变
  • y 轴方向:metallic 改变
  • z 轴方向:opacity 改变
swift 复制代码
private let radius: Float = 0.08
private let interval: Float = 0.2
private let initPosition = SIMD3<Float>(x: 0, y: 0.4, z: -3)
private let matrixSize = 5
    
for roughness in 0...matrixSize {
    for metallic in 0...matrixSize {
        for opacity in 0...matrixSize {
            let r = Float(roughness)
            let m = Float(metallic)
            let o = Float(opacity)
            let xOffset = interval * r
            let yOffset = interval * m
            let zOffset = interval * o
            let position = SIMD3<Float>(x: initPosition.x + xOffset, 
                y: initPosition.y + yOffset, z: initPosition.z + zOffset)
            
            var material = PhysicallyBasedMaterial()
            material.baseColor = PhysicallyBasedMaterial.BaseColor(tint:.orange)
            material.roughness = PhysicallyBasedMaterial.Roughness(floatLiteral: 0.2 * r)
            material.metallic = PhysicallyBasedMaterial.Metallic(floatLiteral: 0.2 * m)
            material.blending = .transparent(opacity: .init(floatLiteral: 0.2 * o))
            
            let sphere = ModelEntity(
                mesh: .generateSphere(radius: radius),
                materials: [material],
                collisionShape: .generateSphere(radius: radius),
                mass: 0.0
            )
            sphere.components.set(InputTargetComponent(allowedInputTypes: .indirect))
            sphere.position = position
            outerEntity.addChild(sphere)
        }
    }
}

最终效果

参考

developer.apple.com/documentati...

developer.apple.com/documentati...

developer.apple.com/documentati...

help.sketchfab.com/hc/en-us/ar...

www.bilibili.com/video/BV1CC...

www.youtube.com/watch?v=_Zb...

相关推荐
Мартин.3 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。4 小时前
案例-表白墙简单实现
前端·javascript·css
数云界4 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd4 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常4 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer4 小时前
Vite:为什么选 Vite
前端
小御姐@stella4 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing4 小时前
【React】增量传输与渲染
前端·javascript·面试
eHackyd4 小时前
前端知识汇总(持续更新)
前端
万叶学编程7 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js