Permalink
Browse files

Unity: use Unity.Mathematics

- Burst: 140 -> 162 Mray/s
- no burst: 10.18 -> 10.82 Mray/s
  • Loading branch information...
aras-p committed Mar 28, 2018
1 parent b15cdff commit ff42b31be7a379396c7fed134718943bf02b88ad
Showing with 47 additions and 85 deletions.
  1. +17 −52 Unity/Assets/Maths.cs
  2. +28 −32 Unity/Assets/Test.cs
  3. +2 −1 Unity/Packages/manifest.json
@@ -1,60 +1,30 @@
using UnityEngine;
using Debug = System.Diagnostics.Debug;
using Unity.Mathematics;
using static Unity.Mathematics.math;
public struct float3
{
public float x, y, z;
public float3(float x_, float y_, float z_) { x = x_; y = y_; z = z_; }
public float SqLength => x * x + y * y + z * z;
public float Length => Mathf.Sqrt(x * x + y * y + z * z);
public void Normalize() { float k = 1.0f / Length; x *= k; y *= k; z *= k; }
public static float3 operator +(float3 a, float3 b) { return new float3(a.x + b.x, a.y + b.y, a.z + b.z); }
public static float3 operator -(float3 a, float3 b) { return new float3(a.x - b.x, a.y - b.y, a.z - b.z); }
public static float3 operator *(float3 a, float3 b) { return new float3(a.x * b.x, a.y * b.y, a.z * b.z); }
public static float3 operator *(float3 a, float b) { return new float3(a.x * b, a.y * b, a.z * b); }
public static float3 operator *(float a, float3 b) { return new float3(a * b.x, a * b.y, a * b.z); }
public static float3 operator -(float3 a) { return new float3(-a.x, -a.y, -a.z); }
public static float Dot(float3 a, float3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
public static float3 Cross(float3 a, float3 b) { return new float3(a.y * b.z - a.z * b.y, -(a.x * b.z - a.z * b.x), a.x * b.y - a.y * b.x); }
public static float3 Normalize(float3 v) { float k = 1.0f / v.Length; return new float3(v.x * k, v.y * k, v.z * k); }
public bool IsNormalized => Mathf.Abs(SqLength - 1.0f) < 0.01f;
public static float3 Reflect(float3 v, float3 n)
{
//Debug.Assert(v.IsNormalized);
return v - 2 * Dot(v, n) * n;
}
public class MathUtil
{
public static bool Refract(float3 v, float3 n, float nint, out float3 outRefracted)
{
//Debug.Assert(v.IsNormalized);
float dt = Dot(v, n);
float dt = dot(v, n);
float discr = 1.0f - nint * nint * (1 - dt * dt);
if (discr > 0)
{
outRefracted = nint * (v - n* dt) - n * Mathf.Sqrt(discr);
//Debug.Assert(outRefracted.IsNormalized);
outRefracted = nint * (v - n * dt) - n * sqrt(discr);
return true;
}
outRefracted = new float3(0, 0, 0);
return false;
}
}
public class MathUtil
{
public static float PI => 3.1415926f;
public static float Schlick(float cosine, float ri)
{
float r0 = (1 - ri) / (1 + ri);
r0 = r0 * r0;
return r0 + (1 - r0) * Mathf.Pow(1 - cosine, 5);
return r0 + (1 - r0) * pow(1 - cosine, 5);
}
static uint XorShift32(ref uint state)
@@ -78,7 +48,7 @@ public static float3 RandomInUnitDisk(ref uint state)
do
{
p = 2.0f * new float3(RandomFloat01(ref state), RandomFloat01(ref state), 0) - new float3(1, 1, 0);
} while (p.SqLength >= 1.0);
} while (lengthSquared(p) >= 1.0);
return p;
}
@@ -88,7 +58,7 @@ public static float3 RandomInUnitSphere(ref uint state)
do
{
p = 2.0f * new float3(RandomFloat01(ref state), RandomFloat01(ref state), RandomFloat01(ref state)) - new float3(1, 1, 1);
} while (p.SqLength >= 1.0);
} while (lengthSquared(p) >= 1.0);
return p;
}
}
@@ -100,7 +70,6 @@ public struct Ray
public Ray(float3 orig_, float3 dir_)
{
//Debug.Assert(dir_.IsNormalized);
orig = orig_;
dir = dir_;
}
@@ -126,22 +95,19 @@ public struct Sphere
public bool HitSphere(Ray r, float tMin, float tMax, ref Hit outHit)
{
//Debug.Assert(invRadius == 1.0f / radius);
//Debug.Assert(r.dir.IsNormalized);
float3 oc = r.orig - center;
float b = float3.Dot(oc, r.dir);
float c = float3.Dot(oc, oc) - radius * radius;
float b = dot(oc, r.dir);
float c = dot(oc, oc) - radius * radius;
float discr = b * b - c;
if (discr > 0)
{
float discrSq = Mathf.Sqrt(discr);
float discrSq = sqrt(discr);
float t = (-b - discrSq);
if (t < tMax && t > tMin)
{
outHit.pos = r.PointAt(t);
outHit.normal = (outHit.pos - center) * invRadius;
//Debug.Assert(outHit.normal.IsNormalized);
outHit.t = t;
return true;
}
@@ -150,7 +116,6 @@ public bool HitSphere(Ray r, float tMin, float tMax, ref Hit outHit)
{
outHit.pos = r.PointAt(t);
outHit.normal = (outHit.pos - center) * invRadius;
//Debug.Assert(outHit.normal.IsNormalized);
outHit.t = t;
return true;
}
@@ -166,12 +131,12 @@ public Camera(float3 lookFrom, float3 lookAt, float3 vup, float vfov, float aspe
{
lensRadius = aperture / 2;
float theta = vfov * MathUtil.PI / 180;
float halfHeight = Mathf.Tan(theta / 2);
float halfHeight = tan(theta / 2);
float halfWidth = aspect * halfHeight;
origin = lookFrom;
w = float3.Normalize(lookFrom - lookAt);
u = float3.Normalize(float3.Cross(vup, w));
v = float3.Cross(w, u);
w = normalize(lookFrom - lookAt);
u = normalize(cross(vup, w));
v = cross(w, u);
lowerLeftCorner = origin - halfWidth*focusDist*u - halfHeight*focusDist*v - focusDist*w;
horizontal = 2*halfWidth * focusDist*u;
vertical = 2*halfHeight * focusDist*v;
@@ -181,7 +146,7 @@ public Ray GetRay(float s, float t, ref uint state)
{
float3 rd = lensRadius * MathUtil.RandomInUnitDisk(ref state);
float3 offset = u * rd.x + v * rd.y;
return new Ray(origin + offset, float3.Normalize(lowerLeftCorner + s*horizontal + t*vertical - origin - offset));
return new Ray(origin + offset, normalize(lowerLeftCorner + s*horizontal + t*vertical - origin - offset));
}
float3 origin;
@@ -2,10 +2,9 @@
#define DO_LIGHT_SAMPLING
#define DO_THREADED
using static float3;
using static MathUtil;
using UnityEngine;
using Debug = System.Diagnostics.Debug;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using Unity.Collections;
using Unity.Jobs;
@@ -83,7 +82,7 @@ static bool Scatter(Material mat, Ray r_in, Hit rec, out float3 attenuation, out
{
// random point inside unit sphere that is tangent to the hit point
float3 target = rec.pos + rec.normal + MathUtil.RandomInUnitSphere(ref randState);
scattered = new Ray(rec.pos, float3.Normalize(target - rec.pos));
scattered = new Ray(rec.pos, normalize(target - rec.pos));
attenuation = mat.albedo;
// sample lights
@@ -98,17 +97,17 @@ static bool Scatter(Material mat, Ray r_in, Hit rec, out float3 attenuation, out
// create a random direction towards sphere
// coord system for sampling: sw, su, sv
float3 sw = Normalize(s.center - rec.pos);
float3 su = Normalize(Cross(Mathf.Abs(sw.x) > 0.01f ? new float3(0, 1, 0) : new float3(1, 0, 0), sw));
float3 sv = Cross(sw, su);
float3 sw = normalize(s.center - rec.pos);
float3 su = normalize(cross(abs(sw.x) > 0.01f ? new float3(0, 1, 0) : new float3(1, 0, 0), sw));
float3 sv = cross(sw, su);
// sample sphere by solid angle
float cosAMax = Mathf.Sqrt(Mathf.Max(0.0f, 1.0f - s.radius * s.radius / (rec.pos - s.center).SqLength));
float cosAMax = sqrt(max(0.0f, 1.0f - s.radius * s.radius / lengthSquared(rec.pos - s.center)));
float eps1 = RandomFloat01(ref randState), eps2 = RandomFloat01(ref randState);
float cosA = 1.0f - eps1 + eps1 * cosAMax;
float sinA = Mathf.Sqrt(1.0f - cosA * cosA);
float sinA = sqrt(1.0f - cosA * cosA);
float phi = 2 * PI * eps2;
float3 l = su * Mathf.Cos(phi) * sinA + sv * Mathf.Sin(phi) * sinA + sw * cosA;
l.Normalize();
float3 l = su * cos(phi) * sinA + sv * sin(phi) * sinA + sw * cosA;
l = normalize(l);
// shoot shadow ray
Hit lightHit = default(Hit);
@@ -119,45 +118,42 @@ static bool Scatter(Material mat, Ray r_in, Hit rec, out float3 attenuation, out
float omega = 2 * PI * (1 - cosAMax);
float3 rdir = r_in.dir;
//Debug.Assert(rdir.IsNormalized);
float3 nl = Dot(rec.normal, rdir) < 0 ? rec.normal : -rec.normal;
outLightE += (mat.albedo * materials[i].emissive) * (Mathf.Max(0.0f, Dot(l, nl)) * omega / PI);
float3 nl = dot(rec.normal, rdir) < 0 ? rec.normal : -rec.normal;
outLightE += (mat.albedo * materials[i].emissive) * (max(0.0f, dot(l, nl)) * omega / PI);
}
}
#endif
return true;
}
else if (mat.type == Material.Type.Metal)
{
//Debug.Assert(r_in.dir.IsNormalized); Debug.Assert(rec.normal.IsNormalized);
float3 refl = Reflect(r_in.dir, rec.normal);
float3 refl = reflect(r_in.dir, rec.normal);
// reflected ray, and random inside of sphere based on roughness
scattered = new Ray(rec.pos, Normalize(refl + mat.roughness * RandomInUnitSphere(ref randState)));
scattered = new Ray(rec.pos, normalize(refl + mat.roughness * RandomInUnitSphere(ref randState)));
attenuation = mat.albedo;
return Dot(scattered.dir, rec.normal) > 0;
return dot(scattered.dir, rec.normal) > 0;
}
else if (mat.type == Material.Type.Dielectric)
{
//Debug.Assert(r_in.dir.IsNormalized); Debug.Assert(rec.normal.IsNormalized);
float3 outwardN;
float3 rdir = r_in.dir;
float3 refl = Reflect(rdir, rec.normal);
float3 refl = reflect(rdir, rec.normal);
float nint;
attenuation = new float3(1, 1, 1);
float3 refr;
float reflProb;
float cosine;
if (Dot(rdir, rec.normal) > 0)
if (dot(rdir, rec.normal) > 0)
{
outwardN = -rec.normal;
nint = mat.ri;
cosine = mat.ri * Dot(rdir, rec.normal);
cosine = mat.ri * dot(rdir, rec.normal);
}
else
{
outwardN = rec.normal;
nint = 1.0f / mat.ri;
cosine = -Dot(rdir, rec.normal);
cosine = -dot(rdir, rec.normal);
}
if (Refract(rdir, outwardN, nint, out refr))
{
@@ -168,9 +164,9 @@ static bool Scatter(Material mat, Ray r_in, Hit rec, out float3 attenuation, out
reflProb = 1;
}
if (RandomFloat01(ref randState) < reflProb)
scattered = new Ray(rec.pos, Normalize(refl));
scattered = new Ray(rec.pos, normalize(refl));
else
scattered = new Ray(rec.pos, Normalize(refr));
scattered = new Ray(rec.pos, normalize(refr));
}
else
{
@@ -214,7 +210,7 @@ static float3 Trace(Ray r, int depth, ref int inoutRayCount, NativeArray<Sphere>
struct TraceRowJob : IJobParallelFor
{
public int screenWidth, screenHeight, frameCount;
[NativeDisableParallelForRestriction] public NativeArray<Color> backbuffer;
[NativeDisableParallelForRestriction] public NativeArray<UnityEngine.Color> backbuffer;
public Camera cam;
[NativeDisableParallelForRestriction] public NativeArray<int> rayCounter;
@@ -243,24 +239,24 @@ public void Execute(int y)
col += Trace(r, 0, ref rayCount, spheres, materials, ref randState);
}
col *= 1.0f / (float)DO_SAMPLES_PER_PIXEL;
col = new float3(Mathf.Sqrt(col.x), Mathf.Sqrt(col.y), Mathf.Sqrt(col.z));
col = sqrt(col);
Color prev = backbuffer[backbufferIdx];
UnityEngine.Color prev = backbuffer[backbufferIdx];
col = new float3(prev.r, prev.g, prev.b) * lerpFac + col * (1 - lerpFac);
backbuffer[backbufferIdx] = new Color(col.x, col.y, col.z, 1);
backbuffer[backbufferIdx] = new UnityEngine.Color(col.x, col.y, col.z, 1);
backbufferIdx++;
}
rayCounter[0] += rayCount; //@TODO: how to do atomics add?
}
}
public void DrawTest(float time, int frameCount, int screenWidth, int screenHeight, NativeArray<Color> backbuffer, out int outRayCount)
public void DrawTest(float time, int frameCount, int screenWidth, int screenHeight, NativeArray<UnityEngine.Color> backbuffer, out int outRayCount)
{
int rayCount = 0;
#if DO_ANIMATE
s_SpheresData[1].center.y = Mathf.Cos(time)+1.0f;
s_SpheresData[8].center.z = Mathf.Sin(time)*0.3f;
s_SpheresData[1].center.y = cos(time)+1.0f;
s_SpheresData[8].center.z = sin(time)*0.3f;
#endif
float3 lookfrom = new float3(0, 2, 3);
float3 lookat = new float3(0, 0, 0);
@@ -1,6 +1,7 @@
{
"dependencies": {
"com.unity.burst": "0.2.3"
"com.unity.burst": "0.2.3",
"com.unity.mathematics": "0.0.7"
},
"registry": "https://staging-packages.unity.com"
}

0 comments on commit ff42b31

Please sign in to comment.