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