From 09bf2208e5fd00395bd4540ff6c2acb3d4e59964 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Sokolov" Date: Sun, 3 Feb 2019 15:05:01 +0100 Subject: [PATCH] depth map raytracing --- .gitpod.yml | 12 +++++ Dockerfile | 6 +++ doc/depthmap.jpg | Bin 0 -> 30573 bytes geometry.h | 68 +++++------------------ out.jpg | Bin 34411 -> 0 bytes tinyraytracer.cpp | 134 ++++++++++++++++++++++------------------------ 6 files changed, 95 insertions(+), 125 deletions(-) create mode 100644 .gitpod.yml create mode 100644 Dockerfile create mode 100644 doc/depthmap.jpg delete mode 100644 out.jpg diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..2be156f --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,12 @@ +image: + file: Dockerfile +tasks: +- command: > + mkdir --parents build && + cd build && + cmake .. && + make && + ./tinyraycaster && + pnmtopng out.ppm > out.png && + open out.png && + cd .. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..aa1f8a5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM gitpod/workspace-full + +USER root +# add your tools here +RUN apt-get update && apt-get install -y \ + netpbm diff --git a/doc/depthmap.jpg b/doc/depthmap.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb9b77000d85880b1de6210b3923d315b2a7d710 GIT binary patch literal 30573 zcmdqJXIPWj*8h)Vp@{{ht0=uAy~79+NN5t8K!BkJ5(0!OMHojw=|c!%2u(_W(3IXm zsZv4>z4wlEP(=PWGtcw<-kfthum9OxNw~w6?C;tuYwx|*XLCM!K1*>60s@05E?uIa zxCAtc^9c$yip#%T+%E1f1Gg*Ju3X%xu3fu&jhc#vhMJ0+n&$e=>ol}CXsM~`Zqwbk zdF$5gTQt|{@6g}613bTV{*i)~>N3R@;B9YHoVQRs0NxpRuS*x7@;^7=w<}jEsjgAe z0Iyr#qWI;~FPE=gyK?#RHA-q)I-oPZT)uMkw)HjoM`AXVRCn$^(P!Z>Av1_)bE-m_ zHPElp3Dk^SvBjl>OxzMr4ZY&91JY_n!69XzTKX4uC1qsQK?ZgXuj9)Xch1Kts4hNO zh2neO|9<-ae;OLrBA*e1@tm+Uj$P)LM#H9uQPD+<7wqLnf2C8V(8%8>H=xaJ%xcwC{Xl*7L7 zE_Od|WxdDz#@O|nRJ$rPp9%`CAwBOrO zAC;Ww3aXpW|7Bme#MkvwwVs(Aj?;l-<4hN4?(6cblnO^wWkQ3G3}_<}>Yr-7{|v?; z2lT-?dA^y;yCR>Y8Mni8P;f6>Zs8SZNOv;6IjW>Zkw9Ws~#3WN|@&~vt2=`^nc{%UPO2X0`ni!tFAkoZ# zs%VraONU7^V=m*Ur~EKeYu)ML%BAX> zgg4hKeXyAC0}&*<1;(m#3SEoR(wEZ}eqDaqDqiLc$))uUz3uqvvP{<_G=gxTwwNaZy`k z6IDwi=Dl%d@BGo%<)-d}@fk<_Dfqz9a;>}P6rQuYQ_&xf{)l-UX)Qg1*2i+J59&UH znreB&=1)ZUb3Xasw<^Cs{b3@kXTf*1Q;IgQoBbkHXZJGYulT_={M|8ILWYT@jkIAOA~hQBF8p+12Wm@8_VQ!8?=k zXm=B@wI6}h?e26rT*nEdCOLS!RNNP(_)Q<%BX@#eo~$drme3}{1l{FIJ=(*>EJns@ z@nqn;(iDGu3uR~C3#-*7iK;m;R{JrjP9*#?Ib65kIitaOxoHt-P6(0 zoR#&Cp(ju7Dpi1=PO7aoa)XWGCq47w=vzy7| z7MM>*xTfbWQr5Ki8xVwW*#dV5Q7G9;3LlUJOH$k#r?h+C@LA?%=*cLK^>{Le)vByg zOXl=xb-Pz!Ag$!S{#=^X@Bfv21@_X0wq1+-cttI?DCBh>f(ku0V?J-BSFzHd*IT)| z18r)D_k9m?-tL@}y_ziaI8r&PkZNgfFxtGAt1|0rrzv-mZ)F1GO9tAfC9^IA6S+mwGgIR(o(I4@}~&Xz%|q? z3HRv`Ws;Kl<|}EJqiRZ_IxZ=<$Kf`AX6i27AN_V`2I_^h-UYY&h$z!&Ne+^>(Y=b9 zIEX0W*Z)Q(<%=Wp(G&qJ|3VVnwh@}WxwVOKh?l}6j7$nrtzvhylolsCm3EzM-T}i0 zVI1>gE6a668KeU; z^7pB`|4sLGqgY3zh!Yb7DQ4w%=~SvBP;62MR|4b2ffCD@s2%pmAz7@>1uHOrXuH=Q zoQY(tY7>o1f-RkCg}PWYIyqoqH*`Z9v|{Tap`laq@@%)VtZ2*_+hU!aaG*pfZA`XS zv&3A?%_o1WnpGcsxb~-K=aP2bKe|YMSP}wDf|Qj>=J)CK&2MiR#?AUJRP>P6tw&_o zoI(}kwV@VGj9aTJh<=APcA{b%C<_SNGG|< ze&J5LH>j8D6!81c^g(cGnZ6d6 z`_X}T*Q-WQbm)?R8Jpo+LQ~@3%Ito7{!Zst%q#B83ZXvN)}lUDseg=k#q`UKtM0F0 z?~M5Fc3!>nN?nt6=pn)=+sT-a-Zt4!Ql@M^3M-NHE`^KiB!XzlG8<8H_NVgw3rwjx zgfvP_uUCf%JkC{Ei{Lv6Ms6ax`8|^EFpFPR>ob_{AFGuX}r)r^g-rnpqR8k&)z>S8s_3qol8XTBI+4rOEjv>|=(TRNk*c z`E+y;GKuD(hi5y~X-9Es;;18#J-lx`-_ag&D(Ii8m=97BoIj`VyWPcAV#)qMTps&V zA(uU_HMycUjYlY(*S<_z3`Oy|p@hD6EGFq|Nl(M*oe!s*oI|2JfAbzykCzSX;U6Y4 zZ`TaDn-8%w?xXzca9}shQ*$#G?vG1+P#L0u^xB{_aZogvcHx)Rk0p;;y^>BSLdEv{i-FfT5^{qyc2LaH#|u(FCEZ{!39=1rJA3oqcg{5h+? z{#5n-yxHK`_zfU$|igv$w)g!Iq) zIqB7q)X*tewp*_P9$GOowq1=4vk8-;hj3xFb64R$`n9=JWS3a0)%R0yS9vALKP@(9y=B`cdqPCaW`NZVX(kDT_EOoiP+3a>D%`!ii@UNxN< zsHn)KF(f`wy%lU|%S^z4MZlb^g}H#jxODAl!ey6ax;!`ONAxF8E5w8&wQT7TTx2jG zMqi>Pa(h+AQ>^yg6i7z1Di(eGa9&maVLvR^5Kst=-W~Nj|0B;U!_nkbtHt1K&tG4z z{th~J;9qzgsR$FPae>C^HRY1I?yM7GB$%b-!!$gyNaYOt9qPaaMQEmYOE|S@>q8fVy2?R9a> z^HDO=bC`qZ4IMwbVT~I%dwF&TnxfWb$PluET|IH8Cw}!?`YyJTLzBAaZgJed_bCZp=+V| z$HR7J#~i~?Ss(UOb5wH>ftHvNmJya|nIVPXgyu;iIiss!J*?jpS(YA*J8uj7tF{OX z=hV{X>KCdnryelKeyUe?1f!3X@BK`H68F^p#<;+3DT4~NFH#z?odvdH|GEPq?a_%_br5{GjMr1^AMA(E8R&_*G!G0WI7Ks|T z7u_I>#5L9<4nV?z9qYlvk#tyn=VJI`cviSWI8QiF6yoi0ZWJW9zaUzE4xZRzS#*7$ z=><1#eEgh(RCZ1=JS6}5r=89$9@U#YdB7eb-yj-SK~QU%nwpsmkM?!g>lM)$9asBf z)_r(aX0;udYr#pI!hW%sLr#wBTbN~& z3rpYa&ah{o^9wChgTChk6}L~i!*BX`q}qI;Jg4v;Zrn$y9G2@A|Ez}|Y;5)?(ZjRD z(DMDq`7fUs5~>>rIy!R8^|m!hfr-3{Ti3-?^}`Mrix=IooS$bhqB=Flv!njvI04#d z#%RXp476p|d_9;u@gdHxMDu#2RO}z(mf3QDK0JG?{FKXxquMWCJKO#aUt;02VdCe( z{0_WPwERMB^K`@Y{hKdTPAkgKDUzJdDGKwv{`^UAFK?dSGoQ-(ZNu!GVqM@tZSw+F zzh|8AadDM15F^9SiNH%cWt?!VW~}0#7P|xH69?Nx5)vO$aGXe7(QL3|7r#j^Qg=TT zh&AkV&=(KG57C*05-dSc@a~182d2qV`?I}5-WzZA>nA!U1|!J@C?|8WyB05RiuQ1# zq1ABW$h)8P@CIr7q;$eR>TI4-c@EvQvlhRMeq(GY z_PYb?;Bc_9qqwe>_{SA1@tcX1>n0c0(jsTu8%QndKO4>^nH3D?kytkuTh_cVQNoXX&nasC-+!&h`8KXW z6q4gisyL97zjny!9b2jwTYTB(>W2f7H|ci1j3Ra;;#!FkVvBYZR1FU799)_z?vxZhz4euB-;!0ufZ0<%es=$kn>4#l0h~gO+$u28+(WHeBsH z5ROTA2ESKr?T&q%`tz>DeGvgv4Ntj017mFOZV$DW0NNdgdJux_P-yIA>=5F6 z&w_j+QFv<68gzXW=Fk{2{{pu?;o~oQVoY4=8Vpjbckg<&^t1j^oKClh(F|LpoAwcy zWoPsYUG+N@$%gl}hpPu;4jue@Zzf#vz>yZCbzd*K_B&kk*`b9cfW_0)Q;V~^L@}(0 z5AU1F|BYTe7385NY27vYDRhrRz3#J2;kE=C51_ht_X0|M$s}};z|zLRZ$D9R>7X7zuM&b< zruLe9ku;)T+2t=(XSlX)pNk1gL6<-w} zEg3Cw`iA3;<=W%2S8@OKGTrHIj%hpd1CE(=SXw%@c(phYXo)3ZrIzke>zYGEPThhi z)_vKD#C=(XY){p!+@qnL0raew)T z<4;6T@Pf*b2=cb@dJm9=GYFpJ1+s9hgqt03F0OSo`^RSivO*)ow zpJS$&@w4=kM%C(n#A#-@^Cd_5VWjdjhw?cgWh9z?+1k81mf`v$l(x64ovX_uV{~;* zL|KJfTx2{ryAq3;oyQW^zPgj7WB7mnnXU(fO@;g4&8-U_L04J}ZI<8$i&K-6L0rCE zd)aHdRwL~a6+$a`4N+GSjYlBR7C)QkqVuPuTlRhS#Xt*-)5ZiY4u0-&>~WoR6{~A= zZgY&VGe6=OyY?9z->D9bg=HDY-PKjU6Z;+tDg?8}J2;snwoMwYw9I|UUrf8xl~TPW zDOO(?&4xnHo6kv3G2%AD-vc2KKYzlfp40JZ=Xm31ftuoSr9$l%Q(W7Z3cq?-y1x!g zADWNZebfYbe2C2ynt-|IY^<$CuvQaVmQi_b8r&d1bkN zxz55|Ipt2pl2{r&Sk`U*N1Fo|VQ;H%xeH>$mpH05v!VRS;k+DS-NQr);{uYvpd^wE z48|C|Wg~USyZyVtn1B8^iO%iHuSz-B_wu>+5_lR62|{UN#3 z6n=uEQ%b6TpEAtS7Jbm*G*Q_sG~w#?y^bC%@A!pQevHtvw6zYbw4~@dfsJJMXmHmY z$Li+_apA}?;vFa#fta$OFrGL~c175}XpUv#5P1pA2D4CmcR!$>(W%VWioWH2am4y)DzAq^M1GhnnW&69r%31S z;QqvgnMM9w`lZRK;G+mgoBrse&HCN79^bhEEYy4e)tQt~>ngikRWTeC{~)5IT1P0c zYht)pg!d7sD0@o)pJcd>a8^wZ5MTn?$0ph&N{K`4u-(MO8MbAa&tGCaIF_Gu7a0g* zI|Kg#Jk{_b34Y7kz?`TcmN&imzP~YOz%IxBsZ`@|Pq34=zJT zaqiv|oL+E{Q9R2~BVwX?DS47-NaJp*Z=0wh-n2Y+^o6KLA+dTlh<$ugx=VP5wxf^e z(b((nAJjb61$;45U2(9$_Uqf|lDnI0%}nFYh~+i-yivtYu0aA5?irS6PK4S0|N?yDFnGi(X?ZKiJ0gzO~*w;%0i;Q}Muf$kx70_Dt{%wSYlBG)fcX z>*gMw!^D+pO5jebSq@0$og86KheKb0Ce1A@gzDr?80ph>VaC2a5=k(Lp!nrIm;}jd zdBDeK%hut0tEuxuOJU)$it8IAqwhMKjocy(mO6_+bXjD&!bVP_+1}0`$3NaQzgb;U zo0$-%I*%oiL!G3O?cz+c(+(t&6x98NX5-}w5q_lvV=Q(~7Tl(f@y*81;{$VY6}Y!V z29X~+y%VI4(MSl|L~;q^<=*k4xPxncMlzvu8kTInrJ#i!n0GG|%t^T87jL1{>810R zp=gNeDp@#6wbcNMup@T}-~pdl2x$BIMqI=%)K+wGlGX!&xD?-h-26$w`| zmlX?v%(3aosKQL4In|r}{vC^@2}NOC4FUh!FJ5N19*K>oIU3HPOB8O0S&ox)f|af zxvmxtF338OO4XBWXr|h}6m8PHX4LKvE-h{FpB84*7Wa|N+*hnbKnOBI3vs@m?0|WU zv>l+F|I)U=m$Mw0%a@uP)M8M zdj!Aavbxr7=uUjoaw< z=UH<#6q};Y)shxRRYZZ4#Y9sXrz9Q<0cY)@;Q8{RsM-u?(xJeyIYSt1PDXE;fI{=?N`it*+E!VOh*`FLl{COyMq z?Xi3F^D#Jz#R?zCVhdcWlP$AS`y0!IYiZ1eZwk2TZGe%GiUX$-H}}i#iK5)9rpNS} z-)r$rPC!h1B4@tY?D=Yq#PHy)d{G`hDgx%ZrVN)=26zg5SPdx-Pj4$YR_yWK502qx* zP1@Y3su)@DT(h~KVO!=#W65=|K-iWoKheMdlWecA)lA@JU}6zv2soz@*Kuit9{G&2 zJ1F7%D*RWT|=qX7e*g3{hxLIY<5tK;u&5MzFs z%4W(f79~dl@fm?{NT@dsr%aXJsanV*s~fGvwsXq*0|?ePvCuo6ccj;GT|EDDZ5lha?mN;>2ll{DYLc0gpm+AJMw_R z55^i`4ZWGnQ*Q%=ST$2g{GkebDt*r1DI|YF?!@HoUKFW}ki6P^PN8k7$M3f~sP#p- zXizKcbAJ_iieP1cNI_}MJ+G1S5{|OaVz2<`)nJUYPihi(O{%=S#OBx4hd9>PpA3CEid7Q!Q?l1O$Xr1w%=jQuvX2H`_(Vi7Tn^}4sUg84tW2Qy_E2d%kEPXzqyy`X|b zao|Vq!HWFxflqb!R47Y`G(Im<$o6xsmG{>@GZMBCxk_7;16sms8h&!88zq5F6|^Oa zDqYSEO!Jm{FO6Ha7ibd7Gv#>Z1i}URgh%bE2<-9F$w_gWc;gQ4kE0=Uw3!;Jts1J9 zw{{}s86kkTfV1!+U9Oi2#EmcrZREG%?a_LIGSHP|eCJulv3A?D?2&*xgKl)lo%Hm4;~6zbeV)^fGG$pqr?+icfdI2hpE)^lRj;M8 zrV=5ws?63Y?o^P41DtMlkEH&d{wQHAyU*J?ri-%e(fq{lbV~dt$B;sv)4o+RH-0+Q zH+w{Kfp_oM$tHBN$))rOK5@F6d z9%od}l~2E0{y-$N_3;KmeV80kNQC7hOa#W`fxo-+p7lO5$>RyyxC+Mr|` zYOcF~t3DH@nreQCG<+890T2|kRb`C@tMv_A>jWP~1)C)OujVbhHM+Wlb-0!j zsh?HqMhqiIbPQ&XFc0Y1%SS{zHHrHB8J-=MB=Np-4yA;b`pbmse`t2*&oe$cNT4c0 zRh)F{R7@th=m62Ebd~>E-*|{HZKh_4KQGX_m}9Cucn zQ{t?=jmqwBS+wJuis`=29n&LQ&=KZ+xd~r1{1l;`;Or9LHWi9X6Kt0zvU!7bact!n zqCY@=we9~nRh6^f=W28;1+RQk3r!*l}T1g!^`n3I=MH#z|SMB{WE zQgz_1>}slqDhA&11A*DyB3`0VZ3G}r7MqYU?}?)92FkL#-SXdJy$&C4teXf%LF~~) z?QLKoY=J-+)oGCzw$aS3Du1m{6>m*Axan*-^8`g&h-&!~Kq~RO`K`)yKa2pfDz;z2 zv{FI6!pBls?8SHPnmHu6Q}W>eQi^eg)Vk~2AO{Buxc}0|(Gc;`kHtXYI|Z03#^^{YA7pR4J>p}4Bx0MM&~}u)e8LVjkEn4gYLZsJn5e z9{>Iν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 #include #include -#include -template struct vec { - vec() { for (size_t i=DIM; i--; data_[i] = T()); } - T& operator[](const size_t i) { assert(i Vec2f; -typedef vec<3, float> Vec3f; -typedef vec<3, int > Vec3i; -typedef vec<4, float> Vec4f; - -template struct vec<2,T> { - vec() : x(T()), y(T()) {} - vec(T X, T Y) : x(X), y(Y) {} - template vec<2,T>(const vec<2,U> &v); - T& operator[](const size_t i) { assert(i<2); return i<=0 ? x : y; } - const T& operator[](const size_t i) const { assert(i<2); return i<=0 ? x : y; } - T x,y; -}; - -template struct vec<3,T> { - vec() : x(T()), y(T()), z(T()) {} - vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {} +template struct vec3 { T& operator[](const size_t i) { assert(i<3); return i<=0 ? x : (1==i ? y : z); } const T& operator[](const size_t i) const { assert(i<3); return i<=0 ? x : (1==i ? y : z); } - float norm() { return std::sqrt(x*x+y*y+z*z); } - vec<3,T> & normalize(T l=1) { *this = (*this)*(l/norm()); return *this; } + vec3 & normalize(T l=1) { *this = (*this)*(l/std::sqrt((*this)*(*this))); return *this; } T x,y,z; }; -template struct vec<4,T> { - vec() : x(T()), y(T()), z(T()), w(T()) {} - vec(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {} - T& operator[](const size_t i) { assert(i<4); return i<=0 ? x : (1==i ? y : (2==i ? z : w)); } - const T& operator[](const size_t i) const { assert(i<4); return i<=0 ? x : (1==i ? y : (2==i ? z : w)); } - T x,y,z,w; -}; - -template T operator*(const vec& lhs, const vec& rhs) { +template T operator*(const vec3& lhs, const vec3& rhs) { T ret = T(); - for (size_t i=DIM; i--; ret+=lhs[i]*rhs[i]); + for (size_t i=3; i--; ret+=lhs[i]*rhs[i]); return ret; } -templatevec operator+(vec lhs, const vec& rhs) { - for (size_t i=DIM; i--; lhs[i]+=rhs[i]); +template vec3 operator+(vec3 lhs, const vec3& rhs) { + for (size_t i=3; i--; lhs[i]+=rhs[i]); return lhs; } -templatevec operator-(vec lhs, const vec& rhs) { - for (size_t i=DIM; i--; lhs[i]-=rhs[i]); +template vec3 operator-(vec3 lhs, const vec3& rhs) { + for (size_t i=3; i--; lhs[i]-=rhs[i]); return lhs; } -template vec operator*(const vec &lhs, const U& rhs) { - vec ret; - for (size_t i=DIM; i--; ret[i]=lhs[i]*rhs); +template vec3 operator*(const vec3 &lhs, const U& rhs) { + vec3 ret; + for (size_t i=3; i--; ret[i]=lhs[i]*rhs); return ret; } -template vec operator-(const vec &lhs) { +template vec3 operator-(const vec3 &lhs) { return lhs*T(-1); } -template vec<3,T> cross(vec<3,T> v1, vec<3,T> v2) { - return vec<3,T>(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x); -} +typedef vec3 Vec3f; -template std::ostream& operator<<(std::ostream& out, const vec& v) { - for(unsigned int i=0; i}M~Y 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 +#define _USE_MATH_DEFINES #include +#include #include #include #include +#include #include "geometry.h" -struct Material { - Material(const Vec3f &color) : diffuse_color(color) {} - Material() : diffuse_color() {} - Vec3f diffuse_color; -}; - struct Sphere { Vec3f center; float radius; - Material material; - - Sphere(const Vec3f &c, const float &r, const Material &m) : center(c), radius(r), material(m) {} - - bool ray_intersect(const Vec3f &orig, const Vec3f &dir, float &t0) const { - Vec3f L = center - orig; - float tca = L*dir; - float d2 = L*L - tca*tca; - if (d2 > radius*radius) return false; - float thc = sqrtf(radius*radius - d2); - t0 = tca - thc; - float t1 = tca + thc; - if (t0 < 0) t0 = t1; - if (t0 < 0) return false; - return true; - } }; -bool scene_intersect(const Vec3f &orig, const Vec3f &dir, const std::vector &spheres, Vec3f &hit, Vec3f &N, Material &material) { +bool sphere_ray_intersect(const Sphere &sphere, const Vec3f &orig, const Vec3f &dir, float &t0) { + Vec3f L = sphere.center - orig; + float tca = L*dir; + float d2 = L*L - tca*tca; + if (d2 > pow(sphere.radius, 2)) return false; + float thc = sqrtf(pow(sphere.radius, 2) - d2); + t0 = tca - thc; + float t1 = tca + thc; + if (t0 < 0) t0 = t1; + if (t0 < 0) return false; + return true; +} + +float scene_intersect(const Vec3f &orig, const Vec3f &dir, const std::vector &spheres) { float spheres_dist = std::numeric_limits::max(); - for (size_t i=0; i < spheres.size(); i++) { + for (size_t i=0; i::max(); + if (fabs(dir.y)>1e-3) { + float d = -(orig.y+4)/dir.y; // the checkerboard plane has equation y = -4 + Vec3f pt = orig + dir*d; + if (d>0 && fabs(pt.x)<10 && pt.z<-10 && pt.z>-30) { + checkerboard_dist = d; + } + } + + return std::min(spheres_dist, checkerboard_dist); } -Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector &spheres) { - Vec3f point, N; - Material material; - - if (!scene_intersect(orig, dir, spheres, point, N, material)) { - return Vec3f(0.2, 0.7, 0.8); // background color - } - - return material.diffuse_color; -} - -void render(const std::vector &spheres) { - const int width = 1024; - const int height = 768; - const int fov = M_PI/2.; - std::vector framebuffer(width*height); - - #pragma omp parallel for - for (size_t j = 0; j &spheres, std::vector &zbuffer) { +#pragma omp parallel for + for (size_t j=0; j::max(); // clamp the zbuffer by the far plane and normalize it between 0 and 1 + float maxval = -std::numeric_limits::max(); + for (size_t i=0; i spheres = { {{-3,0,-16}, 2}, {{-1,-1.5,-12}, 2}, {{1.5,-.5,-18}, 3}, {{7,5,-18}, 4} }; + const size_t width = 1024; + const size_t height = 768; + const float fov = M_PI/3.; + std::vector zbuffer(width*height); + compute_depthmap(width, height, fov, 23.f, spheres, zbuffer); - std::vector spheres; - spheres.push_back(Sphere(Vec3f(-3, 0, -16), 2, ivory)); - spheres.push_back(Sphere(Vec3f(-1.0, -1.5, -12), 2, red_rubber)); - spheres.push_back(Sphere(Vec3f( 1.5, -0.5, -18), 3, red_rubber)); - spheres.push_back(Sphere(Vec3f( 7, 5, -18), 4, ivory)); + std::vector framebuffer(width*height*3); + for (size_t j=0; j(framebuffer.data()), 3*height*width); + ofs.close(); return 0; }