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

本节实现的效果: WebGL三维地球

内容大纲

  1. 构建网格

  2. 编写着色器

  3. 实现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之绘制三维地球的更多相关文章

  1. 无插件,跨平台,基于WebGL的三维地球来了!!!

    用户通过浏览器即可递交数据到同一个地理信息系统中,操作简单,跨平台 ,无插件,可扩展,高效共享 ,完美匹配超大数据量发布! 近年来,随着计算机图形学.虚拟现实.卫星遥感.航空摄影.激光雷达等技术的迅猛 ...

  2. 开源三维地球GIS引擎Cesium常用功能的开发

    Cesium是一个非常优秀的三维地球GIS引擎(开源且免费).能够加载各种符合标准的地图图层,瓦片图.矢量图等都支持.支持3DMax等建模软件生成的obj文件,支持通用的GIS计算:支持DEM高程图. ...

  3. [js] webgl 初探 - 绘制三角形

    摘要: 1. webgl 概念挺多的, 顶点着色器.片段着色器, 坐标 2. 绘制前期准备工作好多 目前看的比较好的教材: https://developer.mozilla.org/zh-CN/do ...

  4. matlab绘制三维图形

    原文地址:种三维曲面图. 程序如下: [x,y]=meshgrid(-8:0.5:8); z=sin(sqrt(x.^2+y.^2))./sqrt(x.^2+y.^2+eps); subplot(2, ...

  5. Python学习(一) —— matplotlib绘制三维轨迹图

    在研究SLAM时常常需要对其输出的位姿进行复现以检测算法效果,在ubuntu系统中使用Python可以很好的完成相关的工作. 一. Ubuntu下Python的使用 在Ubuntu下使用Python有 ...

  6. Matlab绘图基础——绘制三维表面

    %绘制三维表面 ------------------------------------- %1.绘制线框图:mesh:每一条曲线称为mesh line %首先利用meshgrid函数产生平面区域内的 ...

  7. Matlab绘图基础——绘制三维曲线

    %% 绘制三维曲线 %plot3函数,其中每一组x,y,z组成一组曲线的坐标参数,选项的定义和plot函数相同. %1.当x,y,z是同维向量时,则x,y,z 对应元素构成一条三维曲线. x0 = 0 ...

  8. Matlab绘制三维曲面(以二维高斯函数为例)

    原文地址为:Matlab绘制三维曲面(以二维高斯函数为例) 寒假学习了一下Python下的NumPy和pymatlab,感觉不是很容易上手.来学校之后,决定继续看完数字图像处理一书.还是想按照上学期的 ...

  9. Python使用matplotlib绘制三维曲线

    本文主要演示如何使用matplotlib绘制三维图形 代码如下: # -*- coding: UTF-8 -*- import matplotlib as mpl from mpl_toolkits. ...

随机推荐

  1. JS语法-ES6

    1.介绍 ECMAScript 6简称ES6,是JavaScript语言的下一代标准. 2.常用属性及方法 2.1常量与变量的定义 在JavaScript中,我们一般使用var来定义变量,实际上它是有 ...

  2. Svelte 极简入门

    ​弹指之间即可完成.   注意:原文发表于 2017-8-7,随着框架不断演进,部分内容可能已不适用.     Svelte 是一种新型框架.   以往我们要引入一个框架或者类库,可以通过在页面上放置 ...

  3. 基于docker部署skywalking实现全链路监控

    一.概述 简介 skywalking是一个开放源码的,用于收集.分析,聚合,可视化来自于不同服务和本地基础服务的数据的可观察的平台,skywalking提供了一个简单的方法来让你对你的分布式系统甚至是 ...

  4. PAT-1154(Vertex Coloring )+map使用+vector建图+set的使用

    Vertex Coloring PAT-1154 #include<iostream> #include<cstring> #include<string> #in ...

  5. POJ-3268(来回最短路+dijkstra算法)

    Silver Cow Party POJ-3268 这题也是最短路的模板题,只不过需要进行两次求解最短路,因为涉及到来回的最短路之和. 该题的求解关键是:求解B-A的最短路时,可以看做A是起点,这就和 ...

  6. C#无损压缩图片

    /// <summary> /// 根据指定尺寸得到按比例缩放的尺寸,返回true表示以更改尺寸 /// </summary> /// <param name=" ...

  7. CVE-2019-2618 任意文件上传

    漏洞描述:CVE-2019-2618漏洞主要是利用了WebLogic组件中的DeploymentService接口,该接口支持向服务器上传任意文件.攻击者突破了OAM(Oracle Access Ma ...

  8. Celery:进一步探索

    一.创建Celery专用模块 对于大型项目,一般需要创建一个专用模块,便于管理. 1.1 模块结构 proj/__init__.py /celery.py /tasks.py proj/celery. ...

  9. Java流程控制:三种基本结构

    顺序结构: Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行顺序结构是最简单的算法结构语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的, ...

  10. java基础:变量、常量与作用域

    变量就是可以变化的量,每个变量都必须声明其类型,Java 变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域.作用域 类变量 实例变量 局部变量常量初始化后不能在改变值,不会变动的值,它 ...