Last active
July 29, 2025 07:34
-
-
Save fritschy/a1171ca5e4a1cd0791f8ed37d6a4b6a8 to your computer and use it in GitHub Desktop.
Not so smallpt rust port...
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
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