光线追踪(RayTracing)算法理论与实践(二)平面、材质、联合
提要
经过上次的学习,我们已经可以建立一个简单的光线追踪的场景,接下来,我们继续我们的征程。
今天要得到的最终效果如下:

平面
平面在空间几何中可以用一个向量(法向量)和平面中的一点P0来表示。
平面就是满足下式的点集:n.(P-P0)=0
得到:n.P=d;d=n.P0;
则平面类我们就可以用代码这样来描述:
材质
在真实世界中,白色物体在绿光照射下看起来是绿色而不是白色,红色物体在绿光照射下看起来是黑色,而有的同样颜色的物体在同样的光照下亮度却不同,这都是由物体的材质不同造成的。
首先在项目中添加一个颜色类,然后定义一些方法。color.h
材质这一块有很多东西可以来探讨,而且它和光照联系的很紧密,这里先不探讨。
联合之前的渲染测试我们都只渲染了单个的物体,现在我们需要在场景中显示多个物体,就上开篇的那副图一样。
首先回到光线追踪的原理,从摄像机发射一条射线之后,当场景中只有单个物体,只需计算一个,就可以得到一个result,当场景中又多个物体的时候,我们需要做的就是计算多次,取距离最近的那个result。
创建一个union类,在渲染的时候将要渲染的东西都进去。
union.h
最后我们来加一点反射的效果,在main.cpp中添加一个函数。
void renderRecursive(){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Reset The View glTranslatef(-0.5f,-0.5f,-1.0f); glPointSize(2.0); PerspectiveCamera camera( GVector3(0, 10, 10),GVector3(0, -0.5, -1),GVector3(0, 1, 0), 90); Plane* plane1=new Plane(GVector3(0, 1, 0),1.0); CSphere* sphere1=new CSphere(GVector3(-2, 5, -2), 4.0); CSphere* sphere2=new CSphere(GVector3(5, 5, -7), 3.0); plane1->material=new CheckerMaterial(0.1f,0.5f); sphere1->material=new PhongMaterial(Color::red(), Color::white(), 16,0.25); sphere2->material=new PhongMaterial(Color::green(), Color::white(), 16,0.25); Union scene; scene.push(plane1); scene.push(sphere1); scene.push(sphere2); long maxDepth=20; long maxReflect=5; float dx=1.0f/WINDOW_WIDTH; float dy=1.0f/WINDOW_HEIGHT; float dD=255.0f/maxDepth; glBegin(GL_POINTS); for (long y = 0; y < WINDOW_HEIGHT; ++y) { float sy = 1 - dy*y; for (long x = 0; x < WINDOW_WIDTH; ++x) { float sx =dx*x; CRay ray(camera.generateRay(sx, sy)); IntersectResult result = scene.isIntersected(ray); //IntersectResult result = plane1.isIntersected(ray); if (result.isHit) { Color color = rayTraceRecursive(&scene, ray, maxReflect); //Color color = result.object->material->sample(ray, result.position, result.normal); //Color color =plane1.material->sample(ray, result.position, result.normal); color.saturate(); //color.show(); glColor3ub(color.r*255,color.g*255,color.b*255); glVertex2f(sx,sy); } } } glEnd(); // 交换缓冲区 glfwSwapBuffers();}
结果就是最上面的那幅图了。结语
以前自己只玩过一些opengl的东西,不过那些都有现成的接口让你掉,原理上也不用理解得很深,往往一两句语句就可以实现一个简单的效果。
而现在,从原理到实现,每一句代码都需要先在真实世界中想清楚,然后抽象成代码,不管对编程技巧还是数学功底都会有很高的要求,所以在编写这些代码的时候我又回头去看C++ primer,学线性代数。。当然收获也很大。
源码可以点这里下载。
参考用JavaScript玩转计算机图形学(一)光线追踪入门-http://www.cnblogs.com/miloyip/archive/2010/03/29/1698953.html
光线追踪技术的理论和实践(面向对象)-http://blog.csdn.net/zhangci226/article/details/5664313Wikipedia, Ray Tracing
计算机图形学(第三版)(美)赫恩 著,(美)巴克 著。
