WebGL之绘制三维地球
通过Three.js也许可以很方便的展现出3D模型,但是你知道它是怎样一步一步从构建网格到贴图到最终渲染出3D模型的吗?现在我们直接使用底层的webgl加上一点点的数学知识即可以实现它。
本节实现的效果: WebGL三维地球
earth3d
内容大纲
构建网格
编写着色器
实现3D地球
构建网格
首先我们要建立球体的三维模型,三维网格模型包括如下属性(不熟习请复习webgl教程):
- 顶点(position)
- 法线(normal)
- 贴图坐标(uv)
- 顶点索引(indices)
最后要构建出如下所示的经纬球模型
经纬球
首先可以从xy平面构建圆形,接着再从xz平面将圆形转化为圆球,这其中只要使用到三角函数而已,是不是非常简单。
- 法线使用的是顶点坐标,由于法线与顶点其实方向是一致的
- 顶点索引为6个点,是由于每个面由两个三角形构成
- 贴图uv坐标不需要深度信息,它对应上贴图的xy坐标就可
下面就是构建网格模型的基本逻辑:
const radius = 8;//半径const n = 20;//经纬度格数const position = [];//顶点const normal = [];//法线const texcoord = [];//uv坐标const indices = [];//顶点索引let x, y, z;for (let i = 0; i < n; i++) { const rad = Math.PI / n * i - Math.PI / 2;//从-90度开始计算 const r = radius * Math.cos(rad); y = radius * Math.sin(rad); for (let j = 0; j < n; j++) { x = r * Math.sin(xRadian * j); z = r * Math.cos(xRadian * j); position.push(x, y, z); texcoord.push(j / n, i / n); normal.push(x, y, z); //顶点作为法线,法线从圆心360度放射 const c = i * (n + 1) + j indices.push(c, c + 1, c + l + 1, c, c + l + 1, c + l);//平面的索引 }}
编写着色器
和普通着色器相比,只是添加了uv坐标,uv直接通过顶点着色器差值透传到片段着色器就可,在片段着色器使用texture2D函数获取uv坐标对应的颜色,整体上也是比较基础。
// 顶点着色器attribute vec4 aPosition;attribute vec4 aNormal;attribute vec2 aTexcoord;uniform mat4 modelMatrix;uniform mat4 vpMatrix;varying vec3 fragPos;varying vec3 fragNor;varying vec2 texcoord;void main() { gl_Position = vpMatrix * modelMatrix * aPosition; fragPos= vec3(modelMatrix * aPosition); fragNor = vec3(modelMatrix * aNormal); texcoord = aTexcoord;}// 片段着色器precision mediump float;uniform vec3 viewPos;uniform vec3 lightPos;uniform vec3 lightColor;uniform vec3 ambientColor;uniform sampler2D diffMap;varying vec3 fragPos;varying vec3 fragNor;varying vec2 texcoord;void main() { vec3 normal = normalize(fragNor); vec3 color = texture2D(diffMap, texcoord).rgb; // 光线方向 vec3 lightDir = normalize(lightPos - fragPos); // 光线方向和法向量夹角 float cosTheta = max(dot(lightDir, normal), 0.0); // 漫反射 vec3 diffuse = lightColor * color * cosTheta; // 环境光 // ... // 高光 // ... gl_FragColor = vec4(ambient + diffuse + specular, 1.0);}
实现3D地球
最后实现部分就和之前的webgl基本逻辑一致,不过要准备好地球贴图
地图
图片加载完将构建好的贴图sampler传入着色器就可,其余都是基础业务逻辑,不再详述,这样我们就将三维地球实现了
//...const vpMatrix = m4.identity();const uniforms = { modelMatrix: m4.identity(), lightPos: [20, 0, -20], lightColor: [1, 1, 1], ambientColor: [0.5, 0.5, 0.5],};gl.clearColor(0.1, 0.1, 0.1, 1);gl.enable(gl.DEPTH_TEST);//深度测试gl.enable(gl.CULL_FACE);//背面剔除gl.viewport(0, 0, canvas.width, canvas.height); //设置绘图区域gl.useProgram(program.program);function animate() { gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); m4.multiply(projection, m4.inverse(m4.lookAt(eye, [0, 0, 0], [0, 1, 0])), vpMatrix); setBuffersAndAttributes(gl, vao); setUniforms(program, { vpMatrix }); drawBufferInfo(gl, vao); gl.bindVertexArray(null); requestAnimationFrame(animate);};//加载贴图后执行createTexture(gl, { src: '/img/earth.jpg', flipY: true }, texture => { uniforms.diffMap = texture; setUniforms(program, uniforms ); animate();});
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » WebGL之绘制三维地球
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » WebGL之绘制三维地球