WebGL之绘制三维地球
通过Three.js也许可以很方便的展示出3D模型,但是你知道它是怎么一步一步从构建网格到贴图到最终渲染出3D模型的吗?现在我们直接使用底层的webgl加上一点点的数学知识就可以实现它。
本节实现的效果: WebGL三维地球

内容大纲
构建网格
编写着色器
实现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();
});
WebGL之绘制三维地球的更多相关文章
- 无插件,跨平台,基于WebGL的三维地球来了!!!
用户通过浏览器即可递交数据到同一个地理信息系统中,操作简单,跨平台 ,无插件,可扩展,高效共享 ,完美匹配超大数据量发布! 近年来,随着计算机图形学.虚拟现实.卫星遥感.航空摄影.激光雷达等技术的迅猛 ...
- 开源三维地球GIS引擎Cesium常用功能的开发
Cesium是一个非常优秀的三维地球GIS引擎(开源且免费).能够加载各种符合标准的地图图层,瓦片图.矢量图等都支持.支持3DMax等建模软件生成的obj文件,支持通用的GIS计算:支持DEM高程图. ...
- [js] webgl 初探 - 绘制三角形
摘要: 1. webgl 概念挺多的, 顶点着色器.片段着色器, 坐标 2. 绘制前期准备工作好多 目前看的比较好的教材: https://developer.mozilla.org/zh-CN/do ...
- matlab绘制三维图形
原文地址:种三维曲面图. 程序如下: [x,y]=meshgrid(-8:0.5:8); z=sin(sqrt(x.^2+y.^2))./sqrt(x.^2+y.^2+eps); subplot(2, ...
- Python学习(一) —— matplotlib绘制三维轨迹图
在研究SLAM时常常需要对其输出的位姿进行复现以检测算法效果,在ubuntu系统中使用Python可以很好的完成相关的工作. 一. Ubuntu下Python的使用 在Ubuntu下使用Python有 ...
- Matlab绘图基础——绘制三维表面
%绘制三维表面 ------------------------------------- %1.绘制线框图:mesh:每一条曲线称为mesh line %首先利用meshgrid函数产生平面区域内的 ...
- Matlab绘图基础——绘制三维曲线
%% 绘制三维曲线 %plot3函数,其中每一组x,y,z组成一组曲线的坐标参数,选项的定义和plot函数相同. %1.当x,y,z是同维向量时,则x,y,z 对应元素构成一条三维曲线. x0 = 0 ...
- Matlab绘制三维曲面(以二维高斯函数为例)
原文地址为:Matlab绘制三维曲面(以二维高斯函数为例) 寒假学习了一下Python下的NumPy和pymatlab,感觉不是很容易上手.来学校之后,决定继续看完数字图像处理一书.还是想按照上学期的 ...
- Python使用matplotlib绘制三维曲线
本文主要演示如何使用matplotlib绘制三维图形 代码如下: # -*- coding: UTF-8 -*- import matplotlib as mpl from mpl_toolkits. ...
随机推荐
- 开工大吉:TcaplusDB将持续为您提供可靠的数据服务
开工大吉 新的一年 新的开始 我们也带着新的心意 向您奔赴而来 在此,TcaplusDB祝广大客户朋友,开工大吉,2021,我们将一如既往地守护您的数据,继续做您最坚实的后盾. 作为专为游 ...
- 逆向基础 C++ Primer Plus 第二章 开始学习C++
C++ Primer Plus 第二章 开始学习C++ 知识点梳理 本章从一个简单的C++例子出发,主要介绍了创建C++程序的步骤,以及其所包含的预处理器编译指令.函数头.编译指令.函数体.注释等组成 ...
- Vue框架简介及简单使用
目录 一.前端框架介绍 二.vue框架简介 三.vue使用初体验 1. vue如何在页面中引入 2. 插值表达式 3. 文本指令 4. 方法指令(事件指令) 5. 属性指令 四.js数据类型补充 1. ...
- 清晰图解深度分析HTTPS原理
前言 很高兴遇见你~ Https现在基本已经覆盖所有的http请求了,作为一个伟大的发明,保障了我们的通信安全.在Android中对于HTTPS其实感知不多,因为这些内容都有成熟的框架帮我们完成了,例 ...
- MySQL:字段约束与索引
字段约束 MySQL的字段约束共四种: 约束名 关键字 描述 主键约束 PRIMARY KEY 字段值唯一,且不能为NULL 非空约束 NOT NULL 字段值不能为NULL 唯一约束 UNIQUE ...
- fastjson 请求dnslog
目录 payload 利用java.net.Inet[4|6]Address 参考 Fastjson <= 1.2.47 远程命令执行漏洞利用工具及方法记录 payload rmi://.lda ...
- 关于Laravel框架中Guard的底层实现
1. 什么是Guard 在Laravel/Lumen框架中,用户的登录/注册的认证基本都已经封装好了,开箱即用.而登录/注册认证的核心就是: 用户的注册信息存入数据库(登记) 从数据库中读取数据和用户 ...
- 精确率precession和召回率recall
假设有两类样本,A类和B类,我们要衡量分类器分类A的能力. 现在将所有样本输入分类器,分类器从中返回了一堆它认为属于A类的样本. 召回率:分类器认为属于A类的样本里,真正是A类的样本数,占样本集中所有 ...
- LNMP配置——Nginx配置 —— 配置静态文件不记录日志并添加过期时间
一.配置 #vi /usr/local/nginx/conf/vhost/test.com.conf 写入; server { listen 80; server_name test.com test ...
- P4285 [SHOI2008]汉诺塔 题解 (乱搞)
题目链接 P4285 [SHOI2008]汉诺塔 解题思路 提供一种打表新思路 先来证明一个其他题解都没有证明的结论:\(ans[i]\)是可由\(ans[i-1]\)线性递推的. (\(ans[i] ...