webgl模拟太阳系
demo: minicode——太阳系
文章同时发布于:我的个人网站。
这次做的MiniCode,是用webgl模拟太阳系的动画,绘制了太阳系和绕太阳旋转的八颗行星。各个部分的绘制方法我简要概述下。
1. 背景星空
这部分本来打算采用绘制天空盒的方式,绘制一个无边无际的宇宙的,由于我没有添加自动移动摄像机的功能,所以就简单的绘制了一张背景图片星空。
需要特别注意的是,绘制背景的时候,一定要预先关闭深度测试,绘制好星空背景后再开启深度测试,否则由于远近的关系,背景会遮住行星。
// ---space
spaceShader.useProgram();
gl.bindVertexArray(spaceVao);
gl.bindTexture(gl.TEXTURE_2D, backgroundTexture);
gl.disable(gl.DEPTH_TEST); // 禁用
gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.enable(gl.DEPTH_TEST); // 开启
程序用用到的图片纹理可以在这里获得。
2.行星和太阳
这部分最难的是计算球体的顶点坐标,在opengl(webgl)中绘制一个曲面,本质上是通过划分成无限个三角形绘制的,只要划分的足够细,我们也就看不出来曲面其实并不是曲面。计算顶点坐标的大概思路如下:
- 用多个经纬线划分地球。
- 从上至下,用三角函数求每一圈经纬线相交的点。
- 经过经纬线划分,此时球面被分割成很多很多的四边形。
- 用上面求到的点,分别绘制每个四边形(每个四边形由两个三角形组成)。
基本算法如上,具体可以参考源码。
球面绘制的纹理,需要用到纹理坐标和纹理图片,至于球体的纹理坐标思路是通过UV Map计算的,计算过程也是在计算球体顶点坐标同时计算的。
还需要考虑太阳光照影响,所以需要计算球面每个三角形的顶点的法向量,因为每个绘制的三角形的顶点坐标已经计算了,所以使用向量的叉积很容易计算出法向量。
计算顶点坐标、顶点法向量和纹理坐标使用的是如下函数,可以在[这里]查看源码。
const getSpherePositions_drawTriangles = (splitCountH: number, splitCountV: number, radius: number) => {...return {vertices, normals, textureCoords};
};
函数的三个参数:
- splitCountH: 分割球体的纬线数量(水平线)
- splitCountV: 分割球体的经线数量(竖直线)
- radius: 球体半径
3. 坐标变换
坐标变换,我在之前的文章已经介绍的足够详细了。想要了解可以在我的个人网站查找矩阵变换三篇文章和坐标系讲解的文章。
4. 附
github源码地址:https://github.com/pengfeiw/solar-system
(完)