Created
July 23, 2013 09:53
-
-
Save vinjn/6061267 to your computer and use it in GitHub Desktop.
smallpt.toy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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