看到叶大的文章用JavaScript玩转计算机图形学(一)光线追踪入门 - Milo Yip - 博客园,里面有几个小例子,所以把这些效果用C++再实现一遍。
bajdcc/GameFramework,这一系列停更好久了,只是没想到比较有趣的点子,拿它来练习再好不过,原因有:Direct2D渲染、支持lua脚本、C++编写。由于是光线追踪,所以实际上可以说不依赖任何库,只要有一个CPU就能完成计算。
目前只做了两个效果,具体的讲述移步博客,我不再赘述。
代码:
- https://github.com/bajdcc/GameFramework/blob/master/CCGameFramework/base/pe2d/RenderSphere.cpp(光线追踪)
- https://github.com/bajdcc/GameFramework/blob/master/CCGameFramework/base/pe2d/PhysicsEngine2D.cpp#L73(色彩图)
色彩图
色彩图
这只是一个基本的例子,讲述如何通过像素操作来改变色彩。
我们一张图就如同一个二阶矩阵,每个颜色是一个int,就这么简单。
具体实现的过程:
- 窗口收到WM_PAINT消息,开始启用Direct2D绘制
- 我们的窗口里面是树状关系的窗口/控件组,所以递归执行绘制操作
- 展示控件执行绘制操作
- 创建一个颜色数组,修改之
- 根据数组创建一个位图,将它保存供重用
- 利用Direct2D的渲染操作将该位图渲染
简单的光线追踪
光线追踪(左) 以及 法向量图(右)
左边的光线追踪我一开始也没有搞明白,等到实现之后才明白。
实现原理很简单:
- 一个眼睛,一个球,没有光
- 最终的结果要投影到一块屏幕上,屏幕和眼睛是有一个距离的,就像拍照时手要比个相框一样
- 眼睛、屏幕、球,万事俱备(详见用JavaScript玩转计算机图形学(一)光线追踪入门 - Milo Yip - 博客园 第一张图)
最主要操作:
- 屏幕上给每个像素标记一个点
- 眼睛与那些点形成一个射线(光线)
- 射线无限延长(追踪),你把它看成激光
- 激光有可能就照在了球上,也有可能不在球上
- 对于照在球上的激光,我只要算一下激光出发点(眼睛)到激光结束点(激光与球交点)的距离即可。
- 将两者距离(正数)最终映射到0-255,即RGB,根据RGB值确定像素颜色
- 如果激光没有打中球,对应像素表现为黑色
理一下映射关系:3D空间-->2D屏幕,距离-->像素颜色。
右边是一个法向量图,不同的是:并非由距离确定像素颜色,而是由该点法向量确定颜色。
激光打中球时,我们计算出交点的坐标,同时也计算出激光到该点的直线,其实就是法向量。
法向量方程有四个参数,但是这里场景很简单——球的法向量(单位向量)经过球心,所以其实只有三个参数,我们将三个参数(-1~1)映射到RGB。
后面要完成的: