Commit 402a9663181551ec222919db3d7df239df388e56

Thomas de Grivel 2024-01-28T20:39:37

fix compilation

diff --git a/Makefile b/Makefile
index 10bd1c3..c632a9d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,118 +1,12 @@
-# smallpt Makefile
-#
-# 
 
+PROG = smallpt
 
-# Select appropriate compiler.
-#CPP=g++
-CPP=g++-4.2
-CPPFLAGS=-O3 -fopenmp       # Use this for gcc >= 4.2
-#CPPFLAGS=-O3               # Use this for gcc <  4.2
+CXX_SOURCES = smallpt.cpp
 
-ifdef DEBUG
-CPPFLAGS=-g
-endif
-
-default: all
-
-all: smallpt smallpt4k
-
-smallpt: smallpt.cpp Makefile
-	$(CPP) $(CPPFLAGS) -o smallpt smallpt.cpp 
+${PROG}: ${CXX_SOURCES}
+	${CXX} ${CPPFLAGS} ${CXXFLAGS} ${LDFLAGS} ${CXX_SOURCES} -o ${PROG}
 
 clean:
-	-rm smallpt smallpt4k
-
-tkdiff:
-	for i in `svn st -q | cut -c 8-`; do tkdiff $$i; done
-
-# Requires sstrip utility, which is part of ELFkickers:
-# http://www.muppetlabs.com/~breadbox/software/elfkickers.html
-# Also requires, 7z, part of p7zip:
-# http://p7zip.sourceforge.net/
-# The compile options were found with GC masher:
-# http://ftp.kameli.net/pub/fit/misc/gcmasher11082005.tar.gz
-# Guides I followed:
-# http://in4k.untergrund.net/index.php?title=Linux
-# http://ftp.kameli.net/pub/fit/misc/presis_asm06.pdf
-# http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html
-#
-# compiles to 4049 bytes on 32-bit kubuntu fiesty
-# compiles to 4054 bytes on 64-bit kubuntu hardy (to a 32 bit binary)
-smallpt4k: smallpt4k.cpp Makefile
-	$(CPP) -m32 -march=native -O1 -nostdlib -fpeephole2 -ftree-vectorize -fopenmp -ffast-math -fomit-frame-pointer -fno-exceptions -c smallpt4k.cpp
-	ld -dynamic-linker /lib/ld-linux.so.2 smallpt4k.o /usr/local/lib/libgomp.so /lib/libm.so.6 -o usmallpt4k            # 32-bit OS
-#	ld -dynamic-linker /lib32/ld-linux.so.2 smallpt4k.o /usr/lib32/libgomp.so /lib32/libm.so.6 -o usmallpt4k -melf_i386 # 64-bit OS
-	strip -R .note -R .comment -R .eh_frame -R .eh_frame_hdr -R .gnu.version usmallpt4k
-	./sstrip usmallpt4k         # 32-bit OS
-#	./sstrip32 usmallpt4k       # 64-bit OS
-	echo 'HOME=/tmp/S;cp $$0 ~;tail -n+2 $$0|zcat>~;~;rm ~;exit' > smallpt4k
-	7z a -tgzip -mx=9 -so dummy usmallpt4k >> smallpt4k
-	#gzip -n --best -c usmallpt4k >> smallpt4k
-	chmod +x smallpt4k
-	ls -l smallpt4k
-
-# This builds a self assembling (SA) binary.
-# File size is 2666 bytes (2.7KB) on 32-bit Ubuntu gutsy with g++ 4.2.
-smallptSA: smallpt.cpp Makefile
-	echo 'a=/tmp/I;tail -n+2 $$0|zcat>$$a.cpp;g++-4.2 -O3 -fopenmp -o $$a $$a.cpp;$$a $$*;rm $$a $$a.cpp;exit' > smallptSA
-	7z a -tgzip -mx=9 -so dummy smallpt.cpp >> smallptSA
-	chmod +x smallptSA
-	ls -l smallptSA
-
-DISTNAME = smallpt
-DISTFILES = README LICENSE.txt smallpt.cpp smallpt4k.cpp Makefile result_25k.png
-
-SRCS = $(CFILES) $(C++FILES) $(C++FILES:%.cxx=%.h)
-
-SCENES=sky nightsky island vista overlap wada wada2 forest
-SAMPLES=8 40 200 1000 5k 25k
-IMAGES=$(SCENES:%=%.png) $(SCENES:%=%_t.jpg) $(SAMPLES:%=result_%.png) $(SAMPLES:%=result_t_%.jpg) $(SAMPLES:%=result_crop_%.jpg)
-
-WEBFILES = $(DISTFILES) smallpt.txt smallpt4k.txt index.php cpp2html.css cpp2html_9.css result640.jpg smallpt.tar.gz top.html bot.html smallpt.html extraScenes.txt $(IMAGES)
-
-results: smallpt smallpt4k
-	-mv result{,4k}_5k.ppm /tmp
-	-(time ./smallpt 5000 && mv image.ppm result_5k.ppm) 2>&1 |tee result.txt
-	-(time ./smallpt4k && mv image.ppm result4k_5k.ppm) 2>&1 |tee result4k.txt
-	-compare -metric AE result5k.ppm result_5k.png /tmp/garbage.ppm
-	-compare -metric AE result4k_5k.ppm result_5k.png /tmp/garbage.ppm
-
-results2: smallpt smallpt4k
-	for i in $(SAMPLES); do \
-	  (time ./smallpt $i && mv image.ppm image_$i.ppm) 2>&1 |tee result_$i.txt; \
-	  compare -metric AE image_$i.ppm result_$i.png /tmp/diff_$i.png; \
-        done
-
-dist: $(DISTFILES)
-	-rm -rf $(DISTNAME)
-	mkdir $(DISTNAME)
-	ln $(DISTFILES) $(DISTNAME)
-	tar cvzf $(DISTNAME).tar.gz $(DISTNAME)
-	chmod 644 $(DISTNAME).tar.gz
-	-rm -rf $(DISTNAME)
-
-thumbs:
-	for i in $(SCENES); do \
-convert "$${i}.ppm" "$${i}.png"; \
-convert -quality 92 -resize 150x150 "$${i}.ppm" "$${i}_t.jpg"; \
-done
-
-errthumbs:
-	-for i in 8 40 200 1000 5k 25k; do \
-convert "image_$${i}.ppm" -quality 92 "result_$${i}.png"; \
-convert "image_$${i}.ppm" -resize 100x100 -quality 92 "result_t_$${i}.jpg"; \
-convert "image_$${i}.ppm" -crop 100x100+205+530 -quality 92 "result_crop_$${i}.jpg"; \
-        done
-	-convert -resize 640x640 -quality 92 result_25k.png result640.jpg
-
-upload: $(WEBFILES)
-	perl -pe 's/\n/ \n/g' smallpt.cpp >/tmp/tmp.smallpt.cpp
-	source-highlight -f html -c cpp2html.css --no-doc -n -i /tmp/tmp.smallpt.cpp -o /tmp/tmp.smallpt.html
-	./source-highlight-finish.pl < /tmp/tmp.smallpt.html > smallpt.html
-	convert -geometry 640x640 -quality 92 result_25k.png result640.jpg
-	rsync -e ssh -avz $(WEBFILES) kbeason@kevinbeason.com:kevinbeason.com/smallpt/
-
-others:
-	$(CPP) $(CPPFLAGS)
+	rm -rf ${PROG}
 
+.PHONY: clean
diff --git a/smallpt.cpp b/smallpt.cpp
index aee3c5c..c5aee6b 100644
--- a/smallpt.cpp
+++ b/smallpt.cpp
@@ -9,7 +9,7 @@
 
 typedef double F;
 inline F Fsqrt (F x) { return sqrt(x); }
-inline F Fabs (F x) { return fabs(x); }
+inline F Fabs  (F x) { return fabs(x); }
 
 struct Vec {
   F x; // position, also color (r,g,b)
@@ -71,18 +71,23 @@ struct Ray {
 };
 
 // material types, used in radiance()
-enum Refl_t { DIFF, SPEC, REFR };
+enum ReflectionType {
+  DIFFUSE,
+  SPECULAR,
+  REFRACTION
+};
 
 struct Sphere {
   F radius;            // radius
   Vec position;
   Vec emission;
   Vec color;
-  Refl_t reflection_type;
+  ReflectionType reflection_type;
   
   Sphere (F radius_, Vec position_, Vec emission_, Vec color_,
-          Refl_t reflection_type_)
-    : radius(radius_), p(p_), e(e_), c(c_), refl(refl_)
+          ReflectionType reflection_type_)
+    : radius(radius_), position(position_), emission(emission_),
+      color(color_), reflection_type(reflection_type_)
   {}
 
   // returns distance, 0 if nohit
@@ -91,7 +96,7 @@ struct Sphere {
     /* Solve :
      * t^2 * d . d + 2 * t * (o - p) . d + (o - p) . (o - p) - R^2 = 0
      */
-    Vec op = p - r.origin;
+    Vec op = position - r.origin;
     F t;
     F eps = 1e-4;
     F b = op.dot(r.direction);
@@ -100,21 +105,63 @@ struct Sphere {
       return 0;
     else
       det = Fsqrt(det);
-    return (t = b-det) > eps ? t : ((t = b + det) > eps ? t : 0);
+    t = b - det;
+    if (t > eps)
+      return t;
+    t = b + det;
+    if (t > eps)
+      return t;
+    return 0;
   }
 };
 
 //Scene: radius, position, emission, color, material
 Sphere g_spheres[] = {
-  Sphere(1e5, Vec( 1e5+1,40.8,81.6), Vec(),Vec(.75,.25,.25),DIFF),//Left
-  Sphere(1e5, Vec(-1e5+99,40.8,81.6),Vec(),Vec(.25,.25,.75),DIFF),//Rght
-  Sphere(1e5, Vec(50,40.8, 1e5),     Vec(),Vec(.75,.75,.75),DIFF),//Back
-  Sphere(1e5, Vec(50,40.8,-1e5+170), Vec(),Vec(),           DIFF),//Frnt
-  Sphere(1e5, Vec(50, 1e5, 81.6),    Vec(),Vec(.75,.75,.75),DIFF),//Botm
-  Sphere(1e5, Vec(50,-1e5+81.6,81.6),Vec(),Vec(.75,.75,.75),DIFF),//Top
-  Sphere(16.5,Vec(27,16.5,47),       Vec(),Vec(1,1,1)*.999, SPEC),//Mirr
-  Sphere(16.5,Vec(73,16.5,78),       Vec(),Vec(1,1,1)*.999, REFR),//Glas
-  Sphere(600, Vec(50,681.6-.27,81.6),Vec(12,12,12),  Vec(), DIFF) //Lite
+  Sphere(1e5,                           // Left
+         Vec(1e5 + 1, 40.8, 81.6),
+         Vec(),
+         Vec(0.75, 0.25, 0.25),
+         DIFFUSE),
+  Sphere(1e5,                           // Right
+         Vec(-1e5 + 99, 40.8, 81.6),
+         Vec(),
+         Vec(0.25, 0.25, 0.75),
+         DIFFUSE),
+  Sphere(1e5,                           // Back
+         Vec(50, 40.8, 1e5),
+         Vec(),
+         Vec(0.75, 0.75, 0.75),
+         DIFFUSE),
+  Sphere(1e5,                           // Front
+         Vec(50, 40.8, -1e5 + 170),
+         Vec(),
+         Vec(),
+         DIFFUSE),
+  Sphere(1e5,                           // Bottom
+         Vec(50, 1e5, 81.6),
+         Vec(),
+         Vec(0.75, 0.75, 0.75),
+         DIFFUSE),
+  Sphere(1e5,                           // Top
+         Vec(50, -1e5 + 81.6, 81.6),
+         Vec(),
+         Vec(0.75, 0.75, 0.75),
+         DIFFUSE),
+  Sphere(16.5,                          // Mirror ball
+         Vec(27, 16.5, 47),
+         Vec(),
+         Vec(1, 1, 1) * 0.999,
+         SPECULAR),
+  Sphere(16.5,                          // Glass
+         Vec(73, 16.5, 78),
+         Vec(),
+         Vec(1, 1, 1) * 0.999,
+         REFRACTION),
+  Sphere(600,                           // Light
+         Vec(50, 681.6 - 0.27, 81.6),
+         Vec(12, 12, 12),
+         Vec(),
+         DIFFUSE)
 };
 
 inline F clamp (F x)
@@ -134,7 +181,7 @@ inline bool intersect (const Ray &r, F &t, int &id)
   F inf = 1e20;
   t = inf;
   while (i--) {
-    if ((d = spheres[i].intersect(r)) && d < t) {
+    if ((d = g_spheres[i].intersect(r)) && d < t) {
       t = d;
       id = i;
     }
@@ -148,18 +195,19 @@ Vec radiance (const Ray &r, int depth, unsigned short *Xi)
   int id = 0;                           // Id of intersected object
   if (! intersect(r, t, id))            // If miss, return black
     return Vec();
-  const Sphere &obj = spheres[id];      // The hit object
+  const Sphere &obj = g_spheres[id];      // The hit object
   Vec x = r.origin + r.direction * t;
   Vec n = (x - obj.position).normalize();
   Vec nl = n.dot(r.direction) < 0 ? n : n * -1;
-  Vec f = obj.c;
+  Vec f = obj.color;
   F p = f.x > f.y && f.x > f.z ? f.x : f.y > f.z ? f.y : f.z; // max refl
-  if (++depth > 5)
+  if (++depth > 5) {
     if (erand48(Xi) < p)
       f = f * (1 / p);
     else
       return obj.emission; //R.R.
-  if (obj.reflection_type == DIFF) {    // Ideal diffuse reflection
+  }
+  if (obj.reflection_type == DIFFUSE) {
     F r1 = 2 * M_PI * erand48(Xi);
     F r2 = erand48(Xi);
     F r2s = Fsqrt(r2);
@@ -171,40 +219,43 @@ Vec radiance (const Ray &r, int depth, unsigned short *Xi)
              w * Fsqrt(1 - r2)).normalize();
     return obj.emission + f.mult(radiance(Ray(x, d), depth, Xi));
   }
-  else if (obj.refl == SPEC)            // Ideal specular reflection
+  else if (obj.reflection_type == SPECULAR) {
     return obj.emission +
       f.mult(radiance(Ray(x, r.direction - n * 2 * n.dot(r.direction)),
                       depth, Xi));
-  else {                                // Ideal dielectric refraction
-  Ray reflRay(x, r.direction - n * 2 * n.dot(r.direction));
-  bool into = n.dot(nl) > 0;            // Ray from outside going in?
-  F nc = 1;
-  F nt = 1.5;
-  F nnt = into ? nc / nt : nt / nc;
-  F ddn = r.direction.dot(nl);
-  F cos2t;
-  cos2t = 1 - nnt * nnt * (1 - ddn * ddn);
-  if (cos2t < 0)                        // Total internal reflection
-    return obj.emission + f.mult(radiance(reflRay, depth, Xi));
-  Vec tdir = (r.direction * nnt - n *
-              ((into ? 1 : -1) *
-               (ddn * nnt + Fsqrt(cos2t)))).normalize();
-  F a = nt - nc;
-  F b = nt + nc;
-  F R0 = a * a / (b * b);
-  F c = 1 - (into ? -ddn : tdir.dot(n));
-  F Re = R0 + (1 - R0) * c * c * c * c * c;
-  F Tr = 1 - Re;
-  F P = .25 + .5 * Re;
-  F RP = Re / P;
-  F TP = Tr / (1 - P);
-  return obj.emission +
-    f.mult(depth > 2 ?
-           (erand48(Xi) < P ?           // Russian roulette
-            radiance(reflRay, depth, Xi) * RP :
-            radiance(Ray(x, tdir), depth, Xi) * TP) :
-           radiance(reflRay, depth, Xi) * Re +
-           radiance(Ray(x, tdir), depth, Xi) * Tr);
+  }
+  else if (obj.reflection_type == REFRACTION) {
+    Ray reflRay(x, r.direction - n * 2 * n.dot(r.direction));
+    bool into = n.dot(nl) > 0;            // Ray from outside going in?
+    F nc = 1;
+    F nt = 1.5;
+    F nnt = into ? nc / nt : nt / nc;
+    F ddn = r.direction.dot(nl);
+    F cos2t;
+    cos2t = 1 - nnt * nnt * (1 - ddn * ddn);
+    if (cos2t < 0)                        // Total internal reflection
+      return obj.emission + f.mult(radiance(reflRay, depth, Xi));
+    Vec tdir = (r.direction * nnt - n *
+                ((into ? 1 : -1) *
+                 (ddn * nnt + Fsqrt(cos2t)))).normalize();
+    F a = nt - nc;
+    F b = nt + nc;
+    F R0 = a * a / (b * b);
+    F c = 1 - (into ? -ddn : tdir.dot(n));
+    F Re = R0 + (1 - R0) * c * c * c * c * c;
+    F Tr = 1 - Re;
+    F P = .25 + .5 * Re;
+    F RP = Re / P;
+    F TP = Tr / (1 - P);
+    return obj.emission +
+      f.mult(depth > 2 ?
+             (erand48(Xi) < P ?           // Russian roulette
+              radiance(reflRay, depth, Xi) * RP :
+              radiance(Ray(x, tdir), depth, Xi) * TP) :
+             radiance(reflRay, depth, Xi) * Re +
+             radiance(Ray(x, tdir), depth, Xi) * Tr);
+  }
+  return Vec();
 }
 
 int main (int argc, char *argv[])
@@ -226,8 +277,9 @@ int main (int argc, char *argv[])
             samples * 4,
             100.0 * y / (h - 1));
     x = 0;
-    *Xi = (unsigned short [])
-      {0, 0, static_cast<unsigned short>(y * y * y)};
+    Xi[0] = 0;
+    Xi[1] = 0;
+    Xi[2] = static_cast<unsigned short>(y * y * y);
     while (x < w) {                     // Loop over image columns
       int sy = 0;
       int i = (h - y - 1) * w + x;