[MetalKit]14-Ray-tracing-in-a-Swift-playground5射線追蹤5

本系列文章是對 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, metalglass.而後把這些球體添加到一個列表裏,做爲返回值.咱們還添加一個大球體,還有咱們初始的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

raytracing.png

這張圖片建立參數是:ns=50,球體產生器範圍 -7..<7,圖片分辨率800 x 400.整個渲染花費752秒,若是你想要快一些,5秒渲染的話,我建議使用參數:ns=10,球體產生器範圍 -2..<3,圖片分辨率400 x 200. 源代碼source code 已發佈在Github上.

下次見!

相關文章
相關標籤/搜索