├── .gitignore ├── smallpt.exe ├── smallpt.sln ├── README.md ├── LICENSE.txt └── smallpt ├── smallpt.vcxproj └── smallpt.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | Debug/ 2 | Release/ 3 | *.opensdf 4 | *.sdf 5 | *.suo 6 | -------------------------------------------------------------------------------- /smallpt.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randyridge/smallpt-cplusplus/HEAD/smallpt.exe -------------------------------------------------------------------------------- /smallpt.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smallpt", "smallpt\smallpt.vcxproj", "{C85194E2-53AB-486A-9150-B955C5C98863}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {C85194E2-53AB-486A-9150-B955C5C98863}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {C85194E2-53AB-486A-9150-B955C5C98863}.Debug|Win32.Build.0 = Debug|Win32 14 | {C85194E2-53AB-486A-9150-B955C5C98863}.Release|Win32.ActiveCfg = Release|Win32 15 | {C85194E2-53AB-486A-9150-B955C5C98863}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | smallpt-cplusplus 2 | ============== 3 | 4 | smallpt: Global Illumination in 99 lines of C++ 5 | (http://www.kevinbeason.com/smallpt/) 6 | 7 | This is a simple 'port' of Kevin Beason's smallpt to make it run on Windows via Visual C++ and Visual Studio 2012. Please visit Kevin's site for more information. 8 | 9 | My purpose is to have a comparison point as I'm going to port the code over to C# (http://github.com/randyridge/smallpt-csharp) and refactor for my own amusement and education... This is similar to what Ronald Chen did in Java (http://pyrolistical.github.com/smallpt/). 10 | 11 | I made a few modifications which increased line count to 105, they are all noted with comments starting with // ***. I've also supplied a compiled version of smallpt.exe for Windows. Also, on Windows you may need an application to view the .PPM file output... 12 | 13 | For handy timing use the following from PowerShell: 14 | Measure-Command {.\smallpt.exe 5000} 15 | 16 | Please note that running 5000 samples will take quite a long time (perhaps start with a much lower number) and I've disabled status indicators. 17 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | LICENSE 2 | 3 | Copyright (c) 2006-2008 Kevin Beason (kevin.beason@gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /smallpt/smallpt.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {C85194E2-53AB-486A-9150-B955C5C98863} 15 | Win32Proj 16 | smallpt 17 | 18 | 19 | 20 | Application 21 | true 22 | v110 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v110 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | $(SolutionDir)$(Configuration)\ 45 | 46 | 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 56 | None 57 | true 58 | 59 | 60 | Console 61 | true 62 | 63 | 64 | 65 | 66 | Level3 67 | 68 | 69 | MaxSpeed 70 | true 71 | true 72 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 73 | true 74 | 75 | 76 | Console 77 | true 78 | true 79 | true 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /smallpt/smallpt.cpp: -------------------------------------------------------------------------------- 1 | #include // smallpt, a Path Tracer by Kevin Beason, 2008 2 | #include // Make : g++ -O3 -fopenmp smallpt.cpp -o smallpt 3 | #include // Remove "-fopenmp" for g++ version < 4.2 4 | #define M_PI 3.1415926535897932384626433832795// *** Added for VS2012 5 | double erand48(unsigned short seed[3]){return (double)rand() 6 | / (double)RAND_MAX;}// *** Added for VS2012 7 | struct Vec { // Usage: time ./smallpt 5000 && xv image.ppm 8 | double x, y, z; // position, also color (r,g,b) 9 | Vec(double x_=0, double y_=0, double z_=0){ x=x_; y=y_; z=z_; } 10 | Vec operator+(const Vec &b) const { return Vec(x+b.x,y+b.y,z+b.z); } 11 | Vec operator-(const Vec &b) const { return Vec(x-b.x,y-b.y,z-b.z); } 12 | Vec operator*(double b) const { return Vec(x*b,y*b,z*b); } 13 | Vec mult(const Vec &b) const { return Vec(x*b.x,y*b.y,z*b.z); } 14 | Vec& norm(){ return *this = *this * (1/sqrt(x*x+y*y+z*z)); } 15 | double dot(const Vec &b) const { return x*b.x+y*b.y+z*b.z; } // cross: 16 | Vec operator%(Vec&b){return Vec(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);} 17 | }; 18 | struct Ray { Vec o, d; Ray(Vec o_, Vec d_) : o(o_), d(d_) {} }; 19 | enum Refl_t { DIFF, SPEC, REFR }; // material types, used in radiance() 20 | struct Sphere { 21 | double rad; // radius 22 | Vec p, e, c; // position, emission, color 23 | Refl_t refl; // reflection type (DIFFuse, SPECular, REFRactive) 24 | Sphere(double rad_, Vec p_, Vec e_, Vec c_, Refl_t refl_): 25 | rad(rad_), p(p_), e(e_), c(c_), refl(refl_) {} 26 | double intersect(const Ray &r) const { // returns distance, 0 if nohit 27 | Vec op = p-r.o; // Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0 28 | double t, eps=1e-4, b=op.dot(r.d), det=b*b-op.dot(op)+rad*rad; 29 | if (det<0) return 0; else det=sqrt(det); 30 | return (t=b-det)>eps ? t : ((t=b+det)>eps ? t : 0); 31 | } 32 | }; 33 | Sphere spheres[] = {//Scene: radius, position, emission, color, material 34 | Sphere(1e5, Vec( 1e5+1,40.8,81.6), Vec(),Vec(.75,.25,.25),DIFF),//Left 35 | Sphere(1e5, Vec(-1e5+99,40.8,81.6),Vec(),Vec(.25,.25,.75),DIFF),//Rght 36 | Sphere(1e5, Vec(50,40.8, 1e5), Vec(),Vec(.75,.75,.75),DIFF),//Back 37 | Sphere(1e5, Vec(50,40.8,-1e5+170), Vec(),Vec(), DIFF),//Frnt 38 | Sphere(1e5, Vec(50, 1e5, 81.6), Vec(),Vec(.75,.75,.75),DIFF),//Botm 39 | Sphere(1e5, Vec(50,-1e5+81.6,81.6),Vec(),Vec(.75,.75,.75),DIFF),//Top 40 | Sphere(16.5,Vec(27,16.5,47), Vec(),Vec(1,1,1)*.999, SPEC),//Mirr 41 | Sphere(16.5,Vec(73,16.5,78), Vec(),Vec(1,1,1)*.999, REFR),//Glas 42 | Sphere(600, Vec(50,681.6-.27,81.6),Vec(12,12,12), Vec(), DIFF) //Lite 43 | }; 44 | inline double clamp(double x){ return x<0 ? 0 : x>1 ? 1 : x; } 45 | inline int toInt(double x){ return int(pow(clamp(x),1/2.2)*255+.5); } 46 | inline bool intersect(const Ray &r, double &t, int &id){ 47 | double n=sizeof(spheres)/sizeof(Sphere), d, inf=t=1e20; 48 | for(int i=int(n);i--;) if((d=spheres[i].intersect(r))&&df.y && f.x>f.z ? f.x : f.y>f.z ? f.y : f.z; // max refl 58 | if (depth > 100) return obj.e; // *** Added to prevent stack overflow 59 | if (++depth>5) if (erand48(Xi).1?Vec(0,1):Vec(1))%w).norm(), v=w%u; 63 | Vec d = (u*cos(r1)*r2s + v*sin(r1)*r2s + w*sqrt(1-r2)).norm(); 64 | return obj.e + f.mult(radiance(Ray(x,d),depth,Xi)); 65 | } else if (obj.refl == SPEC) // Ideal SPECULAR reflection 66 | return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi)); 67 | Ray reflRay(x, r.d-n*2*n.dot(r.d)); // Ideal dielectric REFRACTION 68 | bool into = n.dot(nl)>0; // Ray from outside going in? 69 | double nc=1, nt=1.5, nnt=into?nc/nt:nt/nc, ddn=r.d.dot(nl), cos2t; 70 | if ((cos2t=1-nnt*nnt*(1-ddn*ddn))<0) // Total internal reflection 71 | return obj.e + f.mult(radiance(reflRay,depth,Xi)); 72 | Vec tdir = (r.d*nnt - n*((into?1:-1)*(ddn*nnt+sqrt(cos2t)))).norm(); 73 | double a=nt-nc, b=nt+nc, R0=a*a/(b*b), c = 1-(into?-ddn:tdir.dot(n)); 74 | double Re=R0+(1-R0)*c*c*c*c*c,Tr=1-Re,P=.25+.5*Re,RP=Re/P,TP=Tr/(1-P); 75 | return obj.e + f.mult(depth>2 ? (erand48(Xi)