Skip to content

Instantly share code, notes, and snippets.

@fritschy
Last active July 29, 2025 07:34
Show Gist options
  • Save fritschy/a1171ca5e4a1cd0791f8ed37d6a4b6a8 to your computer and use it in GitHub Desktop.
Save fritschy/a1171ca5e4a1cd0791f8ed37d6a4b6a8 to your computer and use it in GitHub Desktop.
Not so smallpt rust port...
use std::{f64::consts::*,io::*,ops::*,*};type B<T>=Vec<T>; type T=f64;#[
derive(Copy,Clone)]struct V(T,T,T);impl Add for V{ type Output=V;fn add(
self,o:V)->V{V(self.0+o.0, self.1+o.1, self.2+o.2)}} impl Sub for V{type
Output=V; fn sub(self,o:V) ->V{V(self.0-o.0,self.1-o.1,self.2-o.2)}}impl
Mul<T>for V{type Output=V;fn mul(self,o:T)->V{V(self.0*o,self.1*o,self.2
*o)}}impl Mul for V{type Output=V;fn mul(self,o:V)->V{V(self.0*o.0,self.
1*o.1,self.2*o.2)}}const fn b(f:T)->V{V(f,f,f)}impl V{fn n(self)->V{self
*(1./self.d(self).sqrt())}fn d(self,o:V)->T{self.0*o.0+self.1*o.1+self.2
*o.2}fn c(self,o:V)->V{V( self.1*o.2- self.2*o.1, self.2*o.0-self.0*o.2,
self.0*o.1-self.1*o.0)}}#[derive(Copy,Clone)]struct R(V,V);enum M{D,S,R}
struct S(T,V,V,V,M);fn r(x:&mut u32)->T{*x=*x^*x<<13;*x=*x^*x>>17;*x=*x^
*x<<5;*x as T/u32::MAX as T}const F:T=1e20; const E:T=1e-4;const Z:T=0.;
const VZ:V=b(Z);impl S{fn i(&self,r:&R)->T{let op=self.1-r.0;let b=op.d(
r.1);let d=b*b-op.d(op)+self.0; let d=if d<Z{return Z}else{d.sqrt()};let
t=b-d;if t>E{t}else{let t=b+d;if t>E{t}else{Z}}}}const SP:[S;9]=[S(1e10,
V(1e5+1.,40.8,81.6),VZ, V(0.75,0.25,0.25), M::D),S(1e10,V(-1e5+99.,40.8,
81.6),VZ,V(0.25,0.25,0.75),M::D),S(1e10,V(50.,40.8,1e5),VZ,b(0.75),M::D)
,S(1e10,V(50.,40.8,-1e5+170.), VZ,VZ,M::D), S(1e10,V(50.,1e5,81.6),VZ,b(
0.75),M::D),S(1e10, V(50.,-1e5+81.6,81.6), VZ,V(0.75,0.75,0.75),M::D),S(
16.5*16.5,V(27.,16.5,47.),VZ,b(0.999),M::S),S(16.5*16.5,V(73.,16.5,78.),
VZ,b(0.999),M::R),S(600.*600.,V(50.,681.6-0.27,81.6),b(12.),VZ,M::D)];fn
cl(x:T)->T{x.max(Z).min(1.)}fn ti(x:T)->u8{(cl(x).powf(0.45)*255.+0.5)as
u8}fn i(r:&R,t:&mut T,sph:&mut&S)->bool{let x=SP.iter().fold((&SP[0],F),
|acc,i|{let nt=i.i(r);if nt>Z&&nt<acc.1{(i,nt)}else{acc}});*sph=&x.0;*t=
x.1;*t<F}fn rd(y:&R,d:i32,xi:&mut u32)->V{let(mut t,mut o)=(Z,&SP[0]);if
d>100||!i(y,&mut t,&mut o){return VZ} let x=y.0+y.1*t;let n=(x-o.1).n();
let nl=if n.d(y.1)<Z{n}else{n*-1.};let mut f=o.3;let(d,p)=(d+1,f.0.max(f
.1).max(f.2));if d>5{if r(xi)<p{f=f*(1./p)}else{return o.2}}if let M::D=
o.4{let(r1,r2)=(2.*PI*r(xi),r(xi));let r2s=r2.sqrt();let w=nl;let u=((if
w.0.abs()>0.1{V(Z,1.,Z)}else{V(1.,Z,Z)}).c(w)).n();let v=w.c(u);return o
.2+f*rd(&R(x,(u*r1.cos()*r2s+v*r1.sin()*r2s+w*(1.-r2).sqrt()).n()),d,xi)
}else if let M::S=o.4{ return o.2+f*rd(&R(x,y.1-n*2.*n.d(y.1)),d,xi)}let
rr=R(x,y.1-n*2.*n.d(y.1));let into=n.d(nl)>Z;let(nc,nt)=(1.,1.5);let(nnt
,ddn)=(if into{nc/nt}else{ nt/nc},y.1.d(nl));let c2t=1.-nnt*nnt*(1.-ddn*
ddn);if c2t<Z{ return o.2+f*rd(&rr,d,xi)}let td=(y.1*nnt-n*((if into{1.}
else{-1.})*(ddn*nnt+c2t.sqrt()))).n();let(a,b)=(nt-nc,nt+nc);let r0=a*a/
(b*b);let c=1.- if into{-ddn} else{td.d(n)};let re=r0+(1.-r0)*c.powi(5);
let(tr,p)=(1.-re,0.25+0.5*re); let(rp,tp)=(re/p,tr/(1.-p));o.2+f*(if d>2
{if r(xi)<p{rd(&rr,d,xi)*rp}else{rd(&R(x,td),d,xi)*tp}}else{rd(&rr,d,xi)
*re+rd(&R(x,td),d,xi)*tr})} fn main()->Result<()>{let mut a=env::args().
skip(1);let mut a=||a.next().unwrap_or("4".into()).parse().unwrap_or(4);
let(ns,nt,w,h,c,(s,t),ss)=(a().max(1),a(),1024,768,R(V(50.,51.55,295.6),
V(Z,-0.042612,-1.).n()), sync::mpsc::channel(), &mut 7);let cx=V(w as T*
0.5135/h as T,Z,Z);let(cy,sm,mut ib)=(cx.c(c.1).n()*0.5135,&(0..ns).map(
|_|(r(ss),r(ss))).collect::<B<_>>(),vec![VZ;w*h]); let p=(0..h).fold(((0
..nt).map(|_|vec![]).collect::<B<_>>(),&mut ib[..]),|(mut t,i),r|{let(p,
o)=i.split_at_mut(w);t[r%nt].push(p);(t,o)}).0;thread::scope(|sc|{for(t,
mut p)in p.into_iter().enumerate(){let s=s.clone(); sc.spawn(move||{let(
mut xi,rs)=(t as u32+1,|xi:&mut _|{let r1=2.*r(xi);if r1<1.{r1.sqrt()-1.
}else{1.-(2.-r1).sqrt()}});for(y,ys)in(0..(h+nt-1)/nt).map(|x|(x,x*nt+t)
){ p[y].into_iter().enumerate().for_each(|(x, px)|{ let y=h-ys-1;*px=sm.
iter().fold(VZ, |acc,(sx,sy)|{acc+{let(dx,dy)=(rs(&mut xi),rs(&mut xi));
let f=|c,t,d,p,s|{c*(((t+0.5+d)/2.+p as T)/s as T-0.5)};let d=f(cx,sx,dx
,x,w)+f(cy,sy,dy,y,h) + c.1;rd(&R(c.0+d*140.,d.n()),0,&mut xi)}})*(1./ns
as T)});s.send(()).unwrap();}}); } let mut lp= 0;for ld in 0..h{let _=t.
recv().unwrap();let p=ld*100/h; if p!=lp{eprint!("Rendering ({ns} spp) \
... {p}%\r");}lp=p;}eprintln!();}); let mut f=fs::File::create("img.ppm"
)?;f.write_all(format!("P6\n{} {}\n255\n",w, h).as_bytes())?;f.write_all
(&ib.iter().flat_map(|i|[ti(i.0), ti(i.1), ti(i.2)]).collect::<B<_>>())}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment