射线追踪器很容易写。在屏幕上的每个像素,你拍摄一条光线到现场,看看它击中了什么。对于最基本的射线追踪器,光线获取它击中的物体的颜色。
如果你正在做阴影,那么你不会立即给像素着色,而是尝试将光线追溯到光源。然后,阴影颜色是光线对光源的角度余弦(点积)*(表面的颜色)。如果无法到达光源,那么物体就处于阴影中。
这个挑战是用你能用的任何语言写射线追踪器。赢家是最简洁的代码,同时仍然保持可读性(有关更多的优雅的定义,请参见这里)。
第一个是不可读的。第二个只是一个非常紧凑的C++程序。
这是一个困难的项目,所以您可能想要书签,然后再回来。我会把这个打开大约一个月,然后再颁发支票。
(稍后将添加更多内容)
发布于 2014-01-03 04:32:34
这需要更多的工作来满足需求(阴影,交互反射),但大部分工作。它在回调过程中向image操作符逐行生成像素.可读性的代价是浪费内存,任意创建和丢弃临时数组。
使用外部矩阵库。
(mat.ps) run % load matrix library
/div { dup 0 eq { pop 10000 }{ div } ifelse } bind def % make divide-by-zero safe
/tan { dup sin exch cos div } def
%[vector] scalar {op} . [vector']
%create a new vector and fill with the scalar,
%call matrix library's vector-op
/sop {
exch % [] {} s
[ exch % [] {} [ s
3 index length 1 sub{dup}repeat % [] {} [ s*n-1
] exch % [] [] {}
vop
} def
/normalize { dup mag {div} sop } def
<< % parameters
/Cam [ 0 0 0 ] % camera location
/Lookat [ 0 0 -1 ] % camera lookat point
/Up [ 0 1 0 ] % up vector
/fovx 45 % horizontal field of view
/W 320 % image width
/H 200 % image height
/Sc [ 1 1 -5 ] % sphere center
/Sr 2 % sphere radius
>> begin
<< % dependent constants
/Left Lookat Cam {sub} vop Up cross
/buf W string
/fovy H W div fovx mul
/ang 0
/pos 3
>> {def} forall % add these values to existing dictionary
% place the light in the scene according to the /ang parameter
/setLight { /Light [ ang cos pos mul 3 ang sin pos mul ] def } def
0 10 360 { /ang exch def % for-loop sets /ang, calls image and showpage
setLight % place the light
150 200 translate % position lower left corner of image on page
/y 0 def % initial y-value
W H 8 % put width height depth on stack for `image` call
[ 1 0 0 1 0 0 ] % 1-to-1 matrix, so width*height points is the image size
{ % image procedure yields a string with one image row
0 1 W 1 sub { /x exch def % for-loop iterates over x-values
Left x 2 mul W sub W div fovx tan mul {mul} sop % construct vector from eye through center of pixel
Up y 2 mul H sub H div fovy tan mul {mul} sop
Lookat {add} vop {add} vop
Cam {sub} vop
normalize /R exch def
Cam Sc {sub} vop % use the quadratic formula to check for real intersection
dup R dot 2 mul /B exch def
dup dot Sr dup mul sub /C exch def
B dup mul C 4 mul sub /disc exch def % discriminant, the part under the radical-sign
% ray hits sphere? no:0 yes:calculate
disc 0 lt { 0 }{
disc sqrt /sdisc exch def % complete the quadratic formula to yield t value
B neg sdisc sub .5 mul /t exch def
t 0 le { B neg sdisc add .5 mul /t exch def } if
R t {mul} sop
Cam {add} vop /ri exch def %intersection point
ri Sc {sub} vop
1 Sr div {mul} sop %normalize
/rn exch def %surface normal
Light
ri
{sub} vop %normalize
rn dot % normal .dot. light-ray
1 add .3 mul
%.3 mul
dup 0 lt {pop 0} if % clip value into 8-bit range
dup 1 gt {pop 1} if
255 mul truncate cvi
} ifelse % pixel_color = 0..255
buf x 3 2 roll put % put pixel value in string
} for
/y y 1 add def % increase y for next row
buf % yield string buffer to image
}
%exec % image doesn't report internal errors, debug the procedure with `exec`
image
showpage
} bind for可以使用幽灵脚本生成一系列编号的图像。ImageMagick的convert可以将它们编译成动画gif。

https://codegolf.stackexchange.com/questions/17270
复制相似问题