# ray tracing example # modified from Artem Yashin's project Console3D # MIT License # Copyright (c) 2021 Artem Yashin # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. use module.libmat; use std.runtime; use std.math; func() { # allocate more spaces for(var i = 0; i<10; i+=1) { runtime.gc.extend("str"); runtime.gc.extend("vec"); } }(); var (max,min,sqrt,sin,cos,abs)=( math.max, math.min, math.sqrt, math.sin, math.cos, math.abs ); var (vec2,vec3)=( libmat.vec2.new, libmat.vec3.new ); var (vec2add,vec2sub,vec2mul,vec2div,vec2len)=( libmat.vec2.add, libmat.vec2.sub, libmat.vec2.mul, libmat.vec2.div, libmat.vec2.len ); var (vec3add,vec3sub,vec3mul,vec3div,vec3neg,vec3norm,vec3len,vec3dot)=( libmat.vec3.add, libmat.vec3.sub, libmat.vec3.mul, libmat.vec3.div, libmat.vec3.neg, libmat.vec3.norm, libmat.vec3.len, libmat.vec3.dot ); var (rotateX,rotateY,rotateZ)=( libmat.vec3.rx, libmat.vec3.ry, libmat.vec3.rz, ); var use_raw = func() { vec2 = func(x,y) {return [x,y];} vec2add = func(v1,v2) {return [v1[0]+v2[0],v1[1]+v2[1]];} vec2sub = func(v1,v2) {return [v1[0]-v2[0],v1[1]-v2[1]];} vec2mul = func(v1,v2) {return [v1[0]*v2[0],v1[1]*v2[1]];} vec2div = func(v1,v2) {return [v1[0]/v2[0],v1[1]/v2[1]];} vec3 = func(x,y,z) {return [x,y,z];} vec3add = func(v1,v2) {return [v1[0]+v2[0],v1[1]+v2[1],v1[2]+v2[2]];} vec3sub = func(v1,v2) {return [v1[0]-v2[0],v1[1]-v2[1],v1[2]-v2[2]];} vec3mul = func(v1,v2) {return [v1[0]*v2[0],v1[1]*v2[1],v1[2]*v2[2]];} vec3div = func(v1,v2) {return [v1[0]/v2[0],v1[1]/v2[1],v1[2]/v2[2]];} vec3neg = func(v) {return [-v[0],-v[1],-v[2]];} vec2len = func(v) {var (x,y)=(v[0],v[1]); return sqrt(x*x+y*y);} vec3len = func(v) {var (x,y,z)=(v[0],v[1],v[2]); return sqrt(x*x+y*y+z*z);} vec3norm = func(v) {var t=vec3len(v); return vec3div(v,[t,t,t]);} vec3dot = func(a,b) {return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];} rotateX = func(a,angle) {return [a[0],a[2]*sin(angle)+a[1]*cos(angle),a[2]*cos(angle)-a[1]*sin(angle)];} rotateY = func(a,angle) {return [a[0]*cos(angle)-a[2]*sin(angle),a[1],a[0]*sin(angle)+a[2]*cos(angle)];} rotateZ = func(a,angle) {return [a[0]*cos(angle)-a[1]*sin(angle),a[0]*sin(angle)+a[1]*cos(angle),a[2]];} } var clamp = func(value,_min,_max) { return max(min(value,_max),_min); } var sign = func(a) { return (0edge; } var vec3abs = func(v) { return [abs(v[0]),abs(v[1]),abs(v[2])]; } var vec3sign = func(v) { return [sign(v[0]),sign(v[1]),sign(v[2])]; } var vec3step = func(edge,v) { return [step(edge[0],v[0]),step(edge[1],v[1]),step(edge[2],v[2])]; } var vec3reflect = func(rd,n) { var d=vec3dot(n,rd); return vec3sub(rd,vec3mul(n,vec3mul([2,2,2],[d,d,d]))); } var sphere = func(ro,rd,r) { var b=vec3dot(ro,rd); var c=vec3dot(ro,ro)-r*r; var h=b*b-c; if (h<0.0) return [-1.0,-1.0]; h=sqrt(h); return [-b-h,-b+h]; } var box = func(ro,rd,boxSize,outNormal) { var m=vec3div([1.0,1.0,1.0],rd); var n=vec3mul(m,ro); var k=vec3mul(vec3abs(m),boxSize); var t1=vec3sub(vec3neg(n),k); var t2=vec3add(vec3neg(n),k); var tN=max(max(t1[0],t1[1]),t1[2]); var tF=min(min(t2[0],t2[1]),t2[2]); if (tN>tF or tF<0.0) return [-1.0,-1.0]; var yzx=[t1[1],t1[2],t1[0]]; var zxy=[t1[2],t1[0],t1[1]]; var tmp=vec3mul(vec3mul(vec3neg(vec3sign(rd)), vec3step(yzx,t1)),vec3step(zxy,t1)); outNormal[0]=tmp[0]; outNormal[1]=tmp[1]; outNormal[2]=tmp[2]; return [tN, tF]; } var plane = func(ro,rd,p,w) { return -(vec3dot(ro,p)+w)/vec3dot(rd,p); } var main = func(frame) { var height=15*2; var width=int(height*1/0.618)*2; var aspect=width/height; var pixelAspect=11.0/24.0; var gradient=split(""," .:!/r(l1Z4H9W8$"); var gradientSize=size(gradient)-1; var screen=[]; setsize(screen,width*height); var light=vec3norm([-0.5,0.5,-1.0]); var spherePos=[0,3,0]; var vec2_2_2=[2,2]; var vec2_1_1=[1,1]; var vec3_000=[0,0,0]; var vec3_00n1=[0,0,-1]; var vec3_111=[1,1,1]; print("\e[2J"); var stamp=maketimestamp(); for(var t=0;t0) { var itPoint=vec3add(vec3sub(ro,spherePos),vec3mul(rd,[intersection[0],intersection[0],intersection[0]])); minIt=intersection[0]; n=vec3norm(itPoint); } var boxN=[0,0,0]; intersection=box(ro,rd,vec3_111,boxN); if (intersection[0]>0 and intersection[0]0 and intersection[0]