Skip to content

Instantly share code, notes, and snippets.

@vinjn
Created July 23, 2013 09:53
Show Gist options
  • Select an option

  • Save vinjn/6061267 to your computer and use it in GitHub Desktop.

Select an option

Save vinjn/6061267 to your computer and use it in GitHub Desktop.
smallpt.toy
// The first version is //sw/devtools/SDK/9.5/SDK/MEDIA/HLSL/scene_raytrace.fx
// The second version is https://HlslradiancerToy/samples/scene_raytrace.toy
// Checkered.jpg
// #define REFLECTION_ENABLED
static float4 backgroundColor = { 0.1, 0.1, 0.1, 1.0 };
#define kAspect .5135
#define kEpsilon 0.001
struct Ray
{
float3 orig;
float3 dir;
};
static int DIFFUSE = 0;
static int SPECULAR = 1;
struct Sphere
{
float3 pos;
float rad2; // radius^2
float3 color;
float3 emission;
int refl; // DIFFUSE or SPECULAR
};
#define SQR(N) (N*N)
#define NOBJECTS 10
static Sphere objects[NOBJECTS] =
{
// left wall
{
1e5+1,40.8,81.6,
SQR(1e5),
.75,.25,.25,
0.0, 0.0, 0.0,
DIFFUSE,
},
// right wall
{
-1e5+99,40.8,81.6,
SQR(1e5),
.25,.25,.75,
0.0, 0.0, 0.0,
DIFFUSE,
},
// back wall
{
50,40.8, 1e5,
SQR(1e5),
.75,.75,.75,
0.0, 0.0, 0.0,
DIFFUSE,
},
// front wall
{
50,40.8,-1e5+170,
SQR(1e5),
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
DIFFUSE,
},
// bottom wall
{
50, 1e5, 81.6,
SQR(1e5),
.75,.75,.75,
0.0, 0.0, 0.0,
DIFFUSE,
},
// top wall
{
50,-1e5+81.6,81.6,
SQR(1e5),
.75,.75,.75,
0.0, 0.0, 0.0,
DIFFUSE,
},
// three balls
{
27,16.5,47,
SQR(16.5),
1.0, 1.0, 1.0,
0.0, 0.0, 0.0,
SPECULAR,
},
{
73,16.5,78,
SQR(20.5),
1.0, 1.0, 1.0,
0.0, 0.0, 0.0,
SPECULAR,
},
{
27,16.5,100,
SQR(10.5),
1.0, 1.0, 1.0,
0.0, 0.0, 0.0,
SPECULAR,
},
// top light
{
50,681.6-.27,81.6,
SQR(600),
0, 0, 0,
12, 12, 12,
DIFFUSE,
},
};
float sphereIntersect(Sphere s, Ray ray)
{
float3 v = s.pos - ray.orig;
float b = dot(v, ray.dir);
float disc = (b*b) - dot(v, v) + s.rad2;
if (disc<=0) return -1.0; // ray misses
disc = sqrt(disc);
float t2 = b + disc;
if (t2<=kEpsilon) return -1.0; // behind ray origin
float t1 = b - disc;
if ((t1>kEpsilon) && (t1<t2)) // return nearest intersection
return t1;
else
return t2;
}
// find nearest hit, stored in hitId
// returns intersection point
float3 sceneIntersect(Ray ray, out int hitId)
{
float mint = 1e10;
hitId = -1;
for(int i=0; i<NOBJECTS; i++)
{
float t = sphereIntersect(objects[i], ray);
if (t > 0)
{
if (t < mint)
{
hitId = i;
mint = t;
}
}
}
return ray.orig + ray.dir*mint;
}
// test for any hit (for shadow rays)
bool anyHit(Ray ray)
{
for(int i=0; i<NOBJECTS; i++)
{
if (sphereIntersect(objects[i], ray) > 0)
return true;
}
return false;
}
struct radianceResult
{
float3 color;
float3 emission;
};
float3 radiance(Ray ray_, int depth_)
{
#if 0
float3 l = normalize(lightPosition - pt);
// check if shadowed
Ray shadowray;
shadowray.orig = pt;
shadowray.dir = l;
bool shadowed = anyHit(shadowray);
#endif
int hitId = 0;
Ray ray = ray_;
int depth = depth_;
float3 cl = {0,0,0}; // accumulated color
float3 cf = {1,1,1}; // accumulated reflectance
while (1)
{
float3 hitPt = sceneIntersect(ray, hitId);
if (hitId == -1)
return cl;
Sphere hitObj = objects[hitId];
float3 hitNorm = normalize(hitPt - hitObj.pos);
float3 f = hitObj.color;
// r.r.
if (++depth>100)
return cl;
cl = cl + cf * hitObj.emission;
cf = cf * f;
// if (hitObj.mtrl == DIFFUSE)
{
ray.orig = hitPt;
ray.dir = reflect(ray.dir, hitNorm);
}
}
return cl;
}
float4 main(float4 pos : SV_POSITION) : SV_TARGET
{
Ray cam = {float3(50,52,295.6), normalize(float3(0,-0.042612,-1))};
float3 cx = float3(resolution.x * kAspect / resolution.y, 0, 0);
float3 cy = normalize(cross(cx, cam.dir)) * kAspect;
float3 d = cx*(pos.x / resolution.x - .5 ) - cy*((pos.y + 4)/ resolution.y - .5) + cam.dir;
// Camera rays are pushed ^^^^^ forward to start in interior
Ray ray = {cam.orig+d*140, normalize(d)};
return float4(radiance(ray, 0), 1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment