问题十三:怎么用ray tracing画个球

198 篇文章 12 订阅
195 篇文章 27 订阅

当然这个球是画在之前的背景图上。

通过画第一张图,已经直到画图有两个步骤:其一,确定位置(范围、大小);其二,设置颜色。

画球也不例外。

第一步:确定球的位置。球上每个像素点的位置即为光线与球的交点,所有这些交点就组成了球。所以,问题转化为找光线和球的交点。

第二步:设置球的颜色。即设置光线和球交点的颜色。

 

(图都是一个像素点一个像素点画出来的,一个光线代表着一个像素点。此处和球有交点的光线对应的像素点就设置成球的颜色)

 

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

}

 

结果图片:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值