|
|
Here's the source for the raytraced texture. No tricks. Just a simple
raytracer.
- Ricky
// Camera point
#declare cpx = -2.5;
#declare cpy = 2;
#declare cpz = -4;
// Light point
#declare lpx = -7.0;
#declare lpy = 5.0;
#declare lpz = -2.0;
#declare rad = 1.0;
// Parts of solution of ray-sphere intersection
#declare sa = function(u,v,w) { u*u+v*v+w*w }
#declare sb = function(x0,y0,z0,u,v,w) {2*(x0*u+y0*v+z0*w)}
// Determinant
#declare det = function(x0,y0,z0,u,v,w,r) {sb(x0,y0,z0,u,v,w)*
sb(x0,y0,z0,u,v,w)-4*
sa(u,v,w)*(x0*x0+y0*y0+z0*z0-r*r)}
// Value of t for parameterized ray hitting sphere
#declare spht = function(x0,y0,z0,u,v,w,r) {(-sb(x0,y0,z0,u,v,w)-
sqrt(det(x0,y0,z0,u,v,w,r)))/2/sa(u,v,w)}
// Location of ray-sphere intersection
#declare xsph = function(x0,y0,z0,u,v,w,r) {x0+u*spht(x0,y0,z0,u,v,w,r)}
#declare ysph = function(x0,y0,z0,u,v,w,r) {y0+v*spht(x0,y0,z0,u,v,w,r)}
#declare zsph = function(x0,y0,z0,u,v,w,r) {z0+w*spht(x0,y0,z0,u,v,w,r)}
// Vector from intersection to light
#declare lsx = function(x,y,z) {lpx - xsph(cpx,cpy,cpz,x,y,z,rad)}
#declare lsy = function(x,y,z) {lpy - ysph(cpx,cpy,cpz,x,y,z,rad)}
#declare lsz = function(x,y,z) {lpz - zsph(cpx,cpy,cpz,x,y,z,rad)}
// Distance from light to sphere
#declare lsd = function(x,y,z) {sqrt(pow(lsx(x,y,z),2)+
pow(lsy(x,y,z),2)+
pow(lsz(x,y,z),2))}
// Intersection of ray with plane{y,-1}
#declare px = function(x0,y0,u,v,h) {x0 + u/v*(h-y0)}
#declare pz = function(y0,z0,v,w,h) {z0 + w/v*(h-y0)}
// Checker pattern for plane
#declare check = function(x,y) { 0.5+0.1*mod(abs(floor(x))+abs(floor(y)),2) }
#declare f = function(x,y,z) {
// First, figure out if ray hits sphere
select(det(cpx,cpy,cpz,x,y,z,rad),
// If not, then draw the plane
select(y,
// Now figure out if the plane is shadowed by the sphere
select(det(px(cpx,cpy,x,y,-1), -1, pz(cpy,cpz,y,z,-1),
lpx-px(cpx,cpy,x,y,-1), lpy+1, lpz-pz(cpy,cpz,y,z,-1),1),
// If not, then draw the regular pattern
check( px(cpx,cpy,x,y,-1), pz(cpy,cpz,y,z,-1))*
// Add some fading with a gaussian
exp(-(pow(px(cpx,cpy,x,y,-1)+5,2)+pow(pz(cpy,cpz,y,z,-1),2))/pow(6,2)/2.0),
// Else, then darken the shadow
0.1*check( px(cpx,cpy,x,y,-1), pz(cpy,cpz,y,z,-1))),
//sky
0),
// Draw the sphere, 0.05 ambient + 0.85 diffuse
// First, check if it's pointed away from the light. If so, then we'll
// have to set the lighting to zero manually, otherwise it will be negative
0.05 + 0.85*select(
(xsph(cpx,cpy,cpz,x,y,z,rad)*lsx(x,y,z) +
ysph(cpx,cpy,cpz,x,y,z,rad)*lsy(x,y,z) +
zsph(cpx,cpy,cpz,x,y,z,rad)*lsz(x,y,z))/lsd(x,y,z)/rad,
// Dark half:
0,
// Illuminated half:
(xsph(cpx,cpy,cpz,x,y,z,rad)*lsx(x,y,z) +
ysph(cpx,cpy,cpz,x,y,z,rad)*lsy(x,y,z) +
zsph(cpx,cpy,cpz,x,y,z,rad)*lsz(x,y,z))/lsd(x,y,z)/rad
)
)
};
// Put the camera at the same point as the ray-tracing
camera{
location <cpx,cpy,cpz>
look_at <0,0,0>
}
light_source{<lpx,lpy,lpz> rgb 2.5
fade_distance 10
fade_power 3
area_light 5*x,5*y,10,10
circular
orient
jitter
adaptive 2
}
box{-1,1
// The main function will draw a ray from the camera point to whichever point
the
// texture is sampled at. This achieves the illusion.
pigment{function{f(x-cpx,y-cpy,z-cpz)}}
finish{ ambient 1.1 diffuse 0.0 }
}
plane{
y,-1
pigment{ checker rgb 0.6, rgb 0.5 }
finish{ambient 0 diffuse 0.5}
}
Post a reply to this message
|
|