本系列文章是对 metalkit.org 上面MetalKit内容的全面翻译和学习.git
MetalKit系统文章目录github
让咱们继续上周的工做完成ray tracer射线追踪器
.如今咱们知道如何生成不一样材料的球体,也知道了如何从不一样角度来观察它们,让咱们再看看如何生成更多的球体.swift
在pixel.swift
中建立一个random_scene() 方法:多线程
func random_scene() -> Hitable_list {
var objects = [Hitable]()
objects.append(Sphere(c: float3(0, -1000, 0), r: 1000, m: Lambertian(albedo: float3(0.5, 0.5, 0.5))))
for a in -2..<3 {
for b in -2..<3 {
let materialChoice = drand48()
let center = float3(Float(a) + 0.9 * Float(drand48()), 0.2, Float(b) + 0.9 * Float(drand48()))
if length(center - float3(4, 0.2, 0)) > 0.9 {
if materialChoice < 0.8 { // diffuse
let albedo = float3(Float(drand48()) * Float(drand48()), Float(drand48()) * Float(drand48()), Float(drand48()) * Float(drand48()))
objects.append(Sphere(c: center, r: 0.2, m: Lambertian(albedo: albedo)))
} else if materialChoice < 0.95 { // metal
let albedo = float3(0.5 * (1 + Float(drand48())), 0.5 * (1 + Float(drand48())), 0.5 * (1 + Float(drand48())))
objects.append(Sphere(c: center, r: 0.2, m: Metal(albedo: albedo, fuzz: Float(0.5 * drand48()))))
} else { // glass
objects.append(Sphere(c: center, r: 0.2, m: Dielectric()))
}
}
}
}
objects.append(Sphere(c: float3(0, 0.7, 0), r: 0.7, m: Dielectric()))
objects.append(Sphere(c: float3(-3, 0.7, 0), r: 0.7, m: Lambertian(albedo: float3(0.4, 0.2, 0.1))))
objects.append(Sphere(c: float3(3, 0.7, 0), r: 0.7, m: Metal(albedo: float3(0.7, 0.6, 0.5), fuzz: 0.0)))
return Hitable_list(list: objects)
}
复制代码
这个方法生成了25个小球体,并用随机值给它们赋上不一样材料,lambertian
, metal
或glass
.而后把这些球体添加到一个列表里,做为返回值.咱们还添加一个大球体,还有咱们初始的3个小球体.app
而后在imageFromPixels() 方法里,咱们将之前添加球体的代码:dom
var objects = [Hitable]()
var object = Sphere(c: float3(0, -100.5, -1), r: 100, m: Lambertian(albedo: float3(0.7, 0.23, 0.12)))
objects.append(object)
object = Sphere(c: float3(1, 0, -1), r: 0.5, m: Metal(albedo: float3(0.8, 0.6, 0.2), fuzz: 0.1))
objects.append(object)
object = Sphere(c: float3(-1, 0, -1), r: 0.5, m: Dielectric())
objects.append(object)
object = Sphere(c: float3(-1, 0, -1), r: -0.49, m: Dielectric())
objects.append(object)
object = Sphere(c: float3(0, 0, -1), r: 0.5, m: Lambertian(albedo: float3(0.24, 0.5, 0.15)))
objects.append(object)
let world = Hitable_list(list: objects)
复制代码
替换为一行,建立随机场景:post
let world = random_scene()
复制代码
通常状况下,如今我会告诉你能够渲染场景了,可是我从 hyperjeff那里学到了一点加速的方法,能够让咱们更快获得更好的质量的图片.仍是在imageFromPixels() 方法里,将外层循环的第一行:学习
for i in 0..<width {
复制代码
替换为下面的代码:ui
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_apply(width, queue) { i in
复制代码
经过使用GCD
多线程,渲染速度提升了3倍!在playground主页面中,看看新生成的图像:spa
这张图片建立参数是:ns=50,球体产生器范围 -7..<7,图片分辨率800 x 400.整个渲染花费752秒,若是你想要快一些,5秒渲染的话,我建议使用参数:ns=10,球体产生器范围 -2..<3,图片分辨率400 x 200. 源代码source code 已发布在Github上.
下次见!