Michael Petrie
March 21, 2019
1.7k

# Graphics like Pixar using Swift

These are the slides for my 5 minute lightning talk, Graphics like Pixar using Swift, given at try! Swift Tokyo 2019.

Project Github: https://github.com/kapsy/swift_ray_tracer

Video of output: https://youtu.be/0dSVm-v8W5w

March 21, 2019

## Transcript

4. ### Why ray trace in Swift? • Well, it’s try! Swift…

• Try something I have never done before in the language • Try Swift as a bare bones language • No Platform Speciﬁc APIs or hardware • Purpose was learning

6. ### Line-sphere intersection Equation for a sphere’s surface: P · P

= R 2 Equation for a ray: P = O + tD So we are looking for any t where: (O + tD) · (O + tD) O D P = O + tD P R
7. ### Equation for a sphere’s surface: P · P = R

2 Equation for a ray: P = O + tD So we are looking for any t where: (O + tD) · (O + tD) R 2 = 0 We can rearrange into a quadratic: O 2 + t 2 D 2 + 2ODt R 2 = 0 <latexit sha1_base64="mldwIYThF30z/Reu3EmQH8CvCPg=">AAADyHichVHLbtNAFL2ueZTwaAobJDZX9EERIpqEBahSpAqChNi0TUhbqW6jsTNxrTgzZjxJCFE2LPkBFqxAQgjxGWzgA1j0ExALFkUCJBbcOFZ5NKUz8twzd+45PnPHjcIgNoztWhP2seMnTk6eypw+c/bcVHb6/Fqs2toTVU+FSm+4PBZhIEXVBCYUG5EWvOWGYt1t3hmer3eEjgMlH5heJLZa3JdBI/C4oVRt2nIdV/iB7PMw8OUggzjvGPHI9O8+bCcl2FAaOcbRjtDiSoxxWze4JxYHOE9zBR2vrgzFIpa3C+hIZbiPjnOokOa9fW4Rl/EamtIftDECFYVdgVwLDJVqBtIfKckezppZ7A59pYoLI7mrqan97fXEWxHZOH/rAj0ukZqmNZe+wEAaRUbJdl2Tcy8VXyYJktsulBJQWC6ZscIjlHGErKdNrWVnWI4lAw+CfApmIB0rKvsaHKiDAg/a0AIBEgzhEDjENDchDwwiym1Bn3KaUJCcCxhAhrhtqhJUwSnbpNWn3WaalbQfasYJ26O/hPRpYiLMsY/sDdtj79lb9on9PFSrn2gMvfQouiOuiGpTTy9Wvh3JalE0sPOb9V/PBhpwK/EakPcoyQxv4Y34ncfP9iqL5bn+PHvJPpP/F2yXvaMbyM5X79WqKD+HDD1A/t92HwRrhVz+Ro6tFmaWbqdPMQmX4DIsUL9vwhLcgxWogmd9sL5Y360f9n07srt2b1Q6YaWcC/DXsJ/8Aqi4+yc=</latexit> We want to ﬁnd t
8. ### What’s a quadratic? A quadratic can have one, two, or

no solutions. ax2 + bx + c = 0 We can ﬁnd these solutions using the quadratic formula: x = b ± p b2 4ac 2a <latexit sha1_base64="N6cA7Zxz2TFB1vDOWvmI4LM3C50=">AAAD1nichVFLb9NAEB7XPEp4NIULEpcVUSuk0mgTIYEqIQW4cOyDNJHqEq03m2RVZ9ex1yHFMjeExIkbB04gIYT4ERy4cOEIqD8BcSwSFw6MHfdBq5ax7J35dr6Zbzyu78nQULplTdgnTp46PXmmcPbc+QtTxemLq6GOAi7qXHs6aLosFJ5Uom6k8UTTDwTru55ouBv30vvGUASh1OqB2fTFep91lexIzgxCrWmr5riiK1XMPNlVSYGgzTpGjEx8hwwi1g4wkRPOFOmxoSDZlTSxViK5vhuZRxojHewCSick1F6UNgnLCXGUNqxLHCdvMEhLEzZ6WCVzxB2ROU5uE7ov7SAhU9QQmZCOVG1ieiIUez1IFErVTdF9qjs66EceWziq/wibOrwTMB7Pu8Tx+8QJB4GJXZQ1T24wniRxlSWHZBUcodo7f6xVLNEyzYwcdiq5U4LcFnXxIzjQBg0cIuiDAAUGfQ8YhPisQQUo+IitQ4xYgJ7M7gUkUEBuhFkCMxiiG/jtYrSWowrjtGaYsTl28fANkElghn6l7+k2/Uw/0B/0z5G14qxGqmUTT3fMFX5r6vnlld//ZfXxNNDbYx3D2Mk1qDFVGmas42Y00IFb2WwSZ/UzJJ2aj/sNH7/cXllYnoln6Rv6E+d9TbfoJ5xYDX/xt0ti+RWkC6scXM9hZ7VartByZalaqt3NVzcJV+AqXMP93IQa3IdFqAO33llfrG/Wd7tpP7Gf2s/GqRNWzrkE/5j94i8BJgRK</latexit> <latexit sha1_base64="N6cA7Zxz2TFB1vDOWvmI4LM3C50=">AAAD1nichVFLb9NAEB7XPEp4NIULEpcVUSuk0mgTIYEqIQW4cOyDNJHqEq03m2RVZ9ex1yHFMjeExIkbB04gIYT4ERy4cOEIqD8BcSwSFw6MHfdBq5ax7J35dr6Zbzyu78nQULplTdgnTp46PXmmcPbc+QtTxemLq6GOAi7qXHs6aLosFJ5Uom6k8UTTDwTru55ouBv30vvGUASh1OqB2fTFep91lexIzgxCrWmr5riiK1XMPNlVSYGgzTpGjEx8hwwi1g4wkRPOFOmxoSDZlTSxViK5vhuZRxojHewCSick1F6UNgnLCXGUNqxLHCdvMEhLEzZ6WCVzxB2ROU5uE7ov7SAhU9QQmZCOVG1ieiIUez1IFErVTdF9qjs66EceWziq/wibOrwTMB7Pu8Tx+8QJB4GJXZQ1T24wniRxlSWHZBUcodo7f6xVLNEyzYwcdiq5U4LcFnXxIzjQBg0cIuiDAAUGfQ8YhPisQQUo+IitQ4xYgJ7M7gUkUEBuhFkCMxiiG/jtYrSWowrjtGaYsTl28fANkElghn6l7+k2/Uw/0B/0z5G14qxGqmUTT3fMFX5r6vnlld//ZfXxNNDbYx3D2Mk1qDFVGmas42Y00IFb2WwSZ/UzJJ2aj/sNH7/cXllYnoln6Rv6E+d9TbfoJ5xYDX/xt0ti+RWkC6scXM9hZ7VartByZalaqt3NVzcJV+AqXMP93IQa3IdFqAO33llfrG/Wd7tpP7Gf2s/GqRNWzrkE/5j94i8BJgRK</latexit> <latexit sha1_base64="N6cA7Zxz2TFB1vDOWvmI4LM3C50=">AAAD1nichVFLb9NAEB7XPEp4NIULEpcVUSuk0mgTIYEqIQW4cOyDNJHqEq03m2RVZ9ex1yHFMjeExIkbB04gIYT4ERy4cOEIqD8BcSwSFw6MHfdBq5ax7J35dr6Zbzyu78nQULplTdgnTp46PXmmcPbc+QtTxemLq6GOAi7qXHs6aLosFJ5Uom6k8UTTDwTru55ouBv30vvGUASh1OqB2fTFep91lexIzgxCrWmr5riiK1XMPNlVSYGgzTpGjEx8hwwi1g4wkRPOFOmxoSDZlTSxViK5vhuZRxojHewCSick1F6UNgnLCXGUNqxLHCdvMEhLEzZ6WCVzxB2ROU5uE7ov7SAhU9QQmZCOVG1ieiIUez1IFErVTdF9qjs66EceWziq/wibOrwTMB7Pu8Tx+8QJB4GJXZQ1T24wniRxlSWHZBUcodo7f6xVLNEyzYwcdiq5U4LcFnXxIzjQBg0cIuiDAAUGfQ8YhPisQQUo+IitQ4xYgJ7M7gUkUEBuhFkCMxiiG/jtYrSWowrjtGaYsTl28fANkElghn6l7+k2/Uw/0B/0z5G14qxGqmUTT3fMFX5r6vnlld//ZfXxNNDbYx3D2Mk1qDFVGmas42Y00IFb2WwSZ/UzJJ2aj/sNH7/cXllYnoln6Rv6E+d9TbfoJ5xYDX/xt0ti+RWkC6scXM9hZ7VartByZalaqt3NVzcJV+AqXMP93IQa3IdFqAO33llfrG/Wd7tpP7Gf2s/GqRNWzrkE/5j94i8BJgRK</latexit> <latexit sha1_base64="N6cA7Zxz2TFB1vDOWvmI4LM3C50=">AAAD1nichVFLb9NAEB7XPEp4NIULEpcVUSuk0mgTIYEqIQW4cOyDNJHqEq03m2RVZ9ex1yHFMjeExIkbB04gIYT4ERy4cOEIqD8BcSwSFw6MHfdBq5ax7J35dr6Zbzyu78nQULplTdgnTp46PXmmcPbc+QtTxemLq6GOAi7qXHs6aLosFJ5Uom6k8UTTDwTru55ouBv30vvGUASh1OqB2fTFep91lexIzgxCrWmr5riiK1XMPNlVSYGgzTpGjEx8hwwi1g4wkRPOFOmxoSDZlTSxViK5vhuZRxojHewCSick1F6UNgnLCXGUNqxLHCdvMEhLEzZ6WCVzxB2ROU5uE7ov7SAhU9QQmZCOVG1ieiIUez1IFErVTdF9qjs66EceWziq/wibOrwTMB7Pu8Tx+8QJB4GJXZQ1T24wniRxlSWHZBUcodo7f6xVLNEyzYwcdiq5U4LcFnXxIzjQBg0cIuiDAAUGfQ8YhPisQQUo+IitQ4xYgJ7M7gUkUEBuhFkCMxiiG/jtYrSWowrjtGaYsTl28fANkElghn6l7+k2/Uw/0B/0z5G14qxGqmUTT3fMFX5r6vnlld//ZfXxNNDbYx3D2Mk1qDFVGmas42Y00IFb2WwSZ/UzJJ2aj/sNH7/cXllYnoln6Rv6E+d9TbfoJ5xYDX/xt0ti+RWkC6scXM9hZ7VartByZalaqt3NVzcJV+AqXMP93IQa3IdFqAO33llfrG/Wd7tpP7Gf2s/GqRNWzrkE/5j94i8BJgRK</latexit>
9. ### Geometrically explained ax2 + bx + c = 0 <latexit

sha1_base64="eKArD86Nc0L+IoDPd6w4Snc8niY=">AAACd3ichVHLSsNAFD2Nr1ofrXUjuDBYFUEoN3WhCILoxqWvquCjJHFaQ9MkJGlpLf6AP+BCEBRExc9w4w+48BPEpYIILrxNA6Ki3mFmzpy5586ZGc0xDc8neohILa1t7R3RzlhXd09vPNGXXPfssquLrG6btrupqZ4wDUtkfcM3xabjCrWkmWJDKy409jcqwvUM21rza47YKakFy8gbuuozlUskR9TqbkaekLWqPKHLszKN5BIpSlMQ8k+ghCCFMJbsxCW2sQcbOsooQcCCz9iECo/bFhQQHOZ2UGfOZWQE+wKHiLG2zFmCM1RmizwWeLUVshavGzW9QK3zKSZ3l5UyRumerumZ7uiGHun911r1oEbDS41nrakVTi5+NLD6+q+qxLOP/U/Vn5595DEdeDXYuxMwjVvoTX3l4Ph5dWZltD5G5/TE/s/ogW75BlblRb9YFisniPEHKN+f+ydYz6SVyTQtZ1Jz8+FXRDGIYYzze09hDotYQpbPreIUl7iKvElD0pg03kyVIqGmH19CUj4A1O6OrA==</latexit> x axis
10. ### As a sphere and ray We can have one, two,

or no intersections.
11. ### In Swift… let oc = ray.origin - sphere.center // Our

quadratic constants let a = dot(ray.dir, ray.dir) let b = dot(oc, ray.dir) let c = dot(oc, oc) - sphere.radius*sphere.radius // Obtain discriminant and check sign let discriminant = b*b - a*c; if discriminant > 0.0 { var t = (-b - sqrt(discriminant))/a if (tnear < t && t < tfar) { P = t*ray.dir // Intersection, find P using ray equation tfar = t } t = (-b + sqrt(discriminant))/a if (tnear < t && t < tfar) { P = t*ray.dir // Intersection, find P using ray equation tfar = t } }

15. ### Finally… • Really try to understand your domain… • …No

matter what that may be • Time invested in knowledge is never wasted • Always challenge yourself! https://github.com/kapsy/swift_ray_tracer
16. ### References • Ray Tracing Minibooks, Pete Shirley • Scratchapixel 2.0

• Ray-Triangle Intersection, Möller–Trumbore • Wikipedia: Cramer’s rule • On building fast kd-Trees for Ray Tracing, Wald-Havran • Realtime Ray Tracing and Interactive Global Illumination, Wald