当然这个球是画在之前的背景图上。
通过画第一张图,已经直到画图有两个步骤:其一,确定位置(范围、大小);其二,设置颜色。
画球也不例外。
第一步:确定球的位置。球上每个像素点的位置即为光线与球的交点,所有这些交点就组成了球。所以,问题转化为找光线和球的交点。
第二步:设置球的颜色。即设置光线和球交点的颜色。
(图都是一个像素点一个像素点画出来的,一个光线代表着一个像素点。此处和球有交点的光线对应的像素点就设置成球的颜色)
13.1 光线撞上球
先抄相关源代码:(红色字体为新增代码)
boolhit_sphere(const vec3& center, float radius, const ray& r)
{
vec3oc = r.orgin() - center;
float a = oc.dot(r.direction(), r.direction());
float b = 2.0 * oc.dot(oc, r.direction());
float c = oc.dot(oc, oc) - radius*radius;
float discriminant = b*b - 4*a*c;
return (discriminant > 0);
}
vec3 color(const ray&r)
{
if(hit_sphere(vec3(0,0,-1), 0.5, r))
return vec3(1, 0, 0);
vec3 unit_direction =unit_vector(r.direction());
float t =0.5*(unit_direction.y() + 1.0);
return(1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0);//white, light blue
// return(1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(1.0, 0, 0.7);//white, pink
}
先解释“光线撞上球”的情况:
球上任一点的坐标(向量)为P,球心坐标(向量)为C,球的半径为R,则球的方程为
|P-C|2=R2即(P-C)( P-C)= R2,注意这里的P,C都是向量,所以,
方程等价于:dot((P-C),( P-C))=R2
光线的方程:R(t)=A+t*B (参考“问题十二”)
“光线撞上球”意味着光线和球在“撞点”上相交,将光线方程代入球方程,得到:
dot((A+t*B-C),( A+t*B -C))= R2
(B*t +(A-C))·(B*t + (A-C)) = R2
(B·B)*t2 + 2*(B·(A-C))*t +(A-C)·(A-C) - R2=0
所以,
a = (B·B)=dot(B,B),
b=2*(B·(A-C))=2*dot(B,(A-C)),
c= (A-C)·(A-C) - R2=dot((A-C),(A-C))- R2,
当方程有实根时,说明光线和球有交点,也就是说这条光线撞上了球。至于方程在什么情况下有实根,哦也,请初中数学老师!!!
b2-4ac= ……
对照源代码:
boolhit_sphere(const vec3& center, float radius, const ray& r)
{
vec3oc = r.orgin() - center;
//得到向量A-C=oc
float a = oc.dot(r.direction(), r.direction());
//B即为光线的方向向量。a = (B·B)=dot(B,B),
float b = 2.0 * oc.dot(oc, r.direction());
// b=2*(B·(A-C))=2*dot(B,(A-C)),
float c = oc.dot(oc, oc) - radius*radius;
//c= (A-C)·(A-C) - R2=dot((A-C),(A-C)) - R2,
float discriminant = b*b - 4*a*c;
return (discriminant > 0);
//判别式>0,有实根,光线撞上球,返回1;
//判别式<0,没有实根,光线没有撞上球,返回0;
}
13.2 给球上每个像素点设置颜色
vec3 color(const ray&r)
{
if(hit_sphere(vec3(0,0,-1), 0.5, r))
return vec3(1, 0, 0);
//此处判断这条光线是否撞上球。
//如果撞上,则执行return vec3(1, 0, 0),将这个像素点设置为红色。
//如果没有撞上,则不执行returnvec3(1, 0, 0),程序向下运行,将这个像素点设置为背景色。
vec3 unit_direction =unit_vector(r.direction());
float t =0.5*(unit_direction.y() + 1.0);
return(1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0);//white, light blue
// return(1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(1.0, 0, 0.7);//white, pink
}
结果图片: