diff --git a/demos/ComputerGraphics/build.sh b/demos/ComputerGraphics/build.sh deleted file mode 100755 index 1003e1013..000000000 --- a/demos/ComputerGraphics/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -clang -Ofast -Xclang -add-plugin -Xclang clad -Xclang -load -Xclang /build/clad/build-clad-tracer/lib/clad.so -I../../include/ -I/usr/lib/gcc/x86_64-linux-gnu/10/include -x c++ -std=c++14 -lstdc++ -lm SmallPT-1.cpp -fopenmp=libiomp5 -o SmallPT-1 "$@" diff --git a/demos/ComputerGraphics/cpp-smallpt-d/build.sh b/demos/ComputerGraphics/cpp-smallpt-d/build.sh index 56eb18c05..6a847dd93 100755 --- a/demos/ComputerGraphics/cpp-smallpt-d/build.sh +++ b/demos/ComputerGraphics/cpp-smallpt-d/build.sh @@ -1,4 +1,4 @@ #!/bin/bash -clang -Ofast -Xclang -add-plugin -Xclang clad -Xclang -load -Xclang /build/clad/build-clad-tracer/lib/clad.so -I../../../include/ -x c++ -std=c++14 -lstdc++ -lm cpp-smallpt.cpp -fopenmp=libiomp5 -o cpp-smallpt "$@" +clang -Ofast -Xclang -add-plugin -Xclang clad -Xclang -load -Xclang ../../../build/lib/clad.so -I../../../include/ -x c++ -std=c++14 -lstdc++ -lm cpp-smallpt.cpp -fopenmp=libiomp5 -o cpp-smallpt "$@" -clang -Ofast -Xclang -add-plugin -Xclang clad -Xclang -load -Xclang /build/clad/build-clad-tracer/lib/clad.so -I../../../include/ -x c++ -std=c++14 -lstdc++ -lm diff-tracer-1.cpp -fopenmp=libiomp5 -o diff-tracer-1 "$@" +clang -Ofast -Xclang -add-plugin -Xclang clad -Xclang -load -Xclang ../../../lib/clad.so -I../../../include/ -x c++ -std=c++14 -lstdc++ -lm diff-tracer-1.cpp -fopenmp=libiomp5 -o diff-tracer-1 "$@" diff --git a/demos/ComputerGraphics/cpp-smallpt-d/cpp-smallpt b/demos/ComputerGraphics/cpp-smallpt-d/cpp-smallpt deleted file mode 100755 index 32dc9fdcd..000000000 Binary files a/demos/ComputerGraphics/cpp-smallpt-d/cpp-smallpt and /dev/null differ diff --git a/demos/ComputerGraphics/smallpt/SmallPT b/demos/ComputerGraphics/smallpt/SmallPT new file mode 100755 index 000000000..fc23c2e79 Binary files /dev/null and b/demos/ComputerGraphics/smallpt/SmallPT differ diff --git a/demos/ComputerGraphics/smallpt/SmallPT-1.cpp b/demos/ComputerGraphics/smallpt/SmallPT-1.cpp new file mode 100644 index 000000000..f5e3909d0 --- /dev/null +++ b/demos/ComputerGraphics/smallpt/SmallPT-1.cpp @@ -0,0 +1,606 @@ +//--------------------------------------------------------------------*- C++ -*- +// clad - The C++ Clang-based Automatic Differentiator +// +// A demo, describing how to use clad in simple Path tracer. +// +// author: Alexander Penev +// Based on smallpt, a Path Tracer by Kevin Beason, 2008 +//----------------------------------------------------------------------------// + +// To compile the demo please type: +// path/to/clang -O3 -Xclang -add-plugin -Xclang clad -Xclang -load -Xclang \ +// path/to/libclad.so -I../../include/ -x c++ -std=c++11 -lstdc++ SmallPT.cpp \ +// -o SmallPT +// +// To run the demo please type: +// ./SmallPT 500 && xv image.ppm + +// A typical invocation would be: +// ../../../../../obj/Debug+Asserts/bin/clang -O3 -Xclang -add-plugin -Xclang clad \ +// -Xclang -load -Xclang ../../../../../obj/Debug+Asserts/lib/libclad.dylib \ +// -I../../include/ -x c++ -std=c++11 -lstdc++ SmallPT.cpp -o SmallPT +// ./SmallPT 500 && xv image.ppm + +// Necessary for clad to work include +#include "clad/Differentiator/Differentiator.h" + +#include +#include +#include + +//TODO: Remove this define and fix float precision issues +#define float double + +// Test types (default is TEST_TYPE_BY_CLAD) +//#define TEST_TYPE_BY_HAND +#define TEST_TYPE_BY_CLAD +//#define TEST_TYPE_BY_NUM + +struct Vec { + float x, y, z; // position, also color (r,g,b) + + Vec(float x_=0, float y_=0, float z_=0) { x=x_; y=y_; z=z_; } + + Vec operator+(const Vec &b) const { return Vec(x+b.x, y+b.y, z+b.z); } + Vec operator-(const Vec &b) const { return Vec(x-b.x, y-b.y, z-b.z); } + Vec operator*(float b) const { return Vec(x*b, y*b, z*b); } + float operator*(const Vec &b) const { return x*b.x+y*b.y+z*b.z; } // dot + Vec operator%(const Vec &b) const { return Vec(y*b.z-z*b.y, z*b.x-x*b.z, x*b.y-y*b.x); } // cross + Vec mult(const Vec &b) const { return Vec(x*b.x, y*b.y, z*b.z); } + Vec& norm() { return *this = *this * (1/sqrt(x*x+y*y+z*z)); } +}; + +struct Ray { + Vec o, d; // Origin and direction + + Ray(Vec o_, Vec d_): o(o_), d(d_) {} +}; + +enum Refl_t { DIFF, SPEC, REFR }; // material types, used in radiance() + +#define inf 1e6 +#define eps 1e-6 + +// Abstract Solid + +class Solid { + public: + Vec e, c; // emission, color + Refl_t refl; // reflection type (DIFFuse, SPECular, REFRactive) + + Solid(Vec e_, Vec c_, Refl_t refl_): e(e_), c(c_), refl(refl_) {} + + // returns distance, 0 if nohit + virtual float intersect(const Ray &r) const { return 0; }; + + // returns normal vector to surface in point pt + virtual Vec normal(const Vec &pt) const { return Vec(1,0,0); }; +}; + +// Abstract Implicit Solid + +class ImplicitSolid : public Solid { + public: + + ImplicitSolid(Vec e_, Vec c_, Refl_t refl_): Solid(e_, c_, refl_) {} + + // TODO: Make this method virtual + // Return signed distance to nearest point on solid surface + float distance_func(float x, float y, float z) const { + return 0; + } + + // implicit surface intersection + // returns distance, 0 if nohit + float intersect(const Ray &r) const override { + float t=2*eps, t1, f; + Vec pt; + do { + pt=r.o+r.d*t; + f=fabs(distance_func(pt.x, pt.y, pt.z)); + t1=t; + t+=f; + if (feps ? t : ((t=b+det)>eps ? t : 0); + } +*/ + + //TODO: Remove this implementation when we make distance_func virtual + + // implicit surface intersection + // returns distance, 0 if nohit + float intersect(const Ray &ray) const override { + float t=2*eps, t1, f; + //float start_sgn = sgn(sphere_distance_func(ray.o.x, ray.o.y, ray.o.z, p, r)), current_sgn; + Vec pt; + do { + pt=ray.o+ray.d*t; + f=fabs(sphere_distance_func(pt.x, pt.y, pt.z, p, r)); + //current_sgn = sgn(f); + //if (current_sgn != start_sgn) return t; + //f=fabs(f); + t1=t; + t+=f; + if (f1 ? 1 : x; +} + +inline int toInt(float x) { + return int(pow(clamp(x),1/2.2)*255+.5); +} + +inline bool intersect(const Ray &ray, float &t, int &id) { + float d; + + t = inf; + for(int i=sizeof(scene)/sizeof(scene[0]); i--; ) { + if ((d = scene[i]->intersect(ray)) && df.y && f.x>f.z ? f.x : f.y>f.z ? f.y : f.z; // max refl + + // object intersection id map test + //return obj.c; + + cl = cl + cf.mult(obj.e); + + if (++depth>5) { + if (erand48(Xi).1 ? Vec(0,1) : Vec(1))%w).norm(), v=w%u; + Vec d = (u*cos(r1)*r2s+v*sin(r1)*r2s+w*sqrt(1-r2)).norm(); + //return obj.e + f.mult(radiance(Ray(x,d), depth, Xi)); + r = Ray(x, d); + continue; + } else if (obj.refl == SPEC) { // Ideal SPECULAR reflection + //return obj.e + f.mult(radiance(Ray(x,r.d-n*2*(n*r.d)), depth, Xi)); + r = Ray(x, r.d-n*2*(n*r.d)); + continue; + } + + // Ideal dielectric REFRACTION + Ray reflRay(x, r.d-n*2*(n*r.d)); + bool into = n*nl>0; // Ray from outside going in? + float nc=1, nt=1.5, nnt=into ? nc/nt : nt/nc, ddn=r.d*nl, cos2t; + + if ((cos2t=1-nnt*nnt*(1-ddn*ddn))<0) { // Total internal reflection + //return obj.e + f.mult(radiance(reflRay, depth, Xi)); + r = reflRay; + continue; + } + + Vec tdir = (r.d*nnt-n*((into?1:-1)*(ddn*nnt+sqrt(cos2t)))).norm(); + float a=nt-nc, b=nt+nc, R0=a*a/(b*b), c=1-(into?-ddn:tdir*n); + float Re=R0+(1-R0)*c*c*c*c*c, Tr=1-Re, P=.25+.5*Re, RP=Re/P, TP=Tr/(1-P); + + //return obj.e + f.mult(depth>2 ? // Russian roulette + // (erand48(Xi)