WebGL 踩坑系列-3

绘制球体

在 WebGL 中绘制物体时需要的顶点是以直角坐标表示的,

当然了,gl_Position 是一个四维的向量,一般将顶点赋值给 gl_Position 时,最后一维会设为 1,

gl_Position = uMVPMatrix * vec4(aVertexPosition, 1.0);

这个时候的 aVertexPosition 三维向量就代表了顶点的直角坐标。

如果我们计算出球面上的顶点,并以直角坐标的形式传入着色器中,用合适的方式绘制,就能画出球面了。

但是,绘制球体需要用到顶点,如果直接用直角坐标,并不好计算,

这时候需要用到球坐标系将球面上的各个顶点表示出来,然后再将球坐标表示成直角坐标。

/**
* 假设球心即为原点,将球面坐标系转换成平面直角坐标系
* @param theta 球心到顶点的连线与 Z 轴正方向的夹角为 theta,范围是 [0, 180]
* @param beta 球心到顶点的连线在 xoy 平面上的投影与 X 轴正方向的夹角为 beta,范围是 [0, 360]
* @param r 球半径
* @return 顶点的坐标,用三维数组表示
*/
function calcVertex(theta, beta, r) {
var st = Math.sin(Math.PI * theta / 180);
var ct = Math.cos(Math.PI * theta / 180);
var sb = Math.sin(Math.PI * beta / 180);
var cb = Math.cos(Math.PI * beta / 180);
var x = r * st * cb;
var y = r * st * sb;
var z = r * ct;
return [x, y, z];
}

这个 calcVertex 函数就够把特定角度和半径的球坐标转换成相应的直角坐标了。

现在只需要从 0 - 180 遍历 theta,0 - 360 遍历 beta 角,就可以得到球面上的所有顶点了。

var n = 48;
var vetices = [];
var r = 1;
for( var j = 0; j < n; j++ ) {
for( var i = 0; i < n: i++ ) {
vertices.push.apply( vertices, calcVertex( i * 180 / n, j * 360 / n, r ) );
// 或者用数组的 concat 方法,效果是一样的,不过据说 concat 方法更高效
// vertices = vertices.concat( calcVertex( i * 180 / n, j * 360 / n, r ) );
}
}

接下来把得到的顶点传入 gl 的缓冲区中,

var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

如果只是利用这些顶点,还不能画出球面,借助索引缓冲区可以实现:

var index = [];
for ( j = 0; j < n; j++ ) {
for ( i = 0; i < n+1; i++ ) {
index.push(
i + j * (n+1), // 0
i+1 + j * (n+1), // 1
i+1 + (j+1) * (n+1) // n+1
);
index.push(
i + j * (n+1), // 0
i+1 + (j+1) * (n+1) // n+1
i + (j+1) * (n+1) // n
);
}
} gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
gl.drawElements(gl.TRIANGLES, index.length, gl.UNSIGNED_SHORT, 0);

最后就能在 canvas 画布上画出球面了,n 越大,球面越精细,画出的球越圆滑。

ThreeJS 绘制球形

由于有导入模型的需求,开始接触 ThreeJS,用这个框架只需要调用 SphereGeometry 的 API 生成一个球,最后把球添加到场景中并进行渲染即可。

sphere = new THREE.Mesh(
new THREE.SphereGeometry(4, 36, 36),
new THREE.MeshPhongMaterial( {
opacity: 0.65,
transparent: true,
color: 0xeeeeee
} )
);
scene.add(sphere);

总结

尽管 ThreeJS 对底层的 WebGL 封装的很好,但是我只需要导入 OBJ 格式的模型就行了,ThreeJS 很强大,用起来也很方便。

而要从 WebGL 写的话,还需要去了解 GLSL 着色器语言,自己编写着色器代码,繁琐很多。

WebGL 踩坑系列-3的更多相关文章

  1. WebGL 踩坑系列-1

    WebGL 中的一些选项WebGL 中开启颜色混合(透明效果) gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALP ...

  2. WebGL 踩坑系列-2

    需求:绘制斑点在球面上走过的路径 思路:要绘制斑点在球面上走过的路径,首先要记录上一时刻和当前时刻该斑点所在球面的位置,并且实时更新当前时刻的斑点位置和上一时刻的斑点位置. 为了方便,上一时刻斑点所在 ...

  3. jmeter踩坑系列

    1.踩坑系列一: 抓包出来有host的字段,放到jmeter里面一起请求就报错了,去掉就请求正常了 1.踩坑系列二: 从花瓶复制过去 的values 前面有空格,肉眼看起来没有

  4. python踩坑系列之导入包时下划红线及报错“No module named”问题

    python踩坑系列之导入包时下划红线及报错“No module named”问题 使用pycharm编写Python时,自己写了一个包(commontool),在同级另一个路径下(fileshand ...

  5. 踩坑系列の Oracle dbms_job简单使用

    二话不说先上代码 --创建存储过程 create or replace procedure job_truncateState is begin --此处就是要定时执行的sql execute imm ...

  6. Vue踩坑系列

    前言 前端开发对于vue的使用已经越来越多,它的优点就不做介绍了, 本篇是我对vue使用过程中遇到的问题中做的一些总结,帮助大家踩坑.如果喜欢的话可以点波赞,或者关注一下,希望本文可以帮到大家!!! ...

  7. 踩坑系列:MySql only_full_group_by配置,竟导致所有应用报错?

    1. 踩坑经历 一个很平常的下午,大家都在埋头认真写bug呢,突然企业微信群里炸锅了,好多应用都出现大量的Error日志,而且都报同一个错误,就是下面这个: Caused by: com.mysql. ...

  8. 【踩坑系列】使用long类型处理金额,科学计数法导致金额转大写异常

    1. 踩坑经历 上周,一个用户反馈他创建的某个销售单无法打开,但其余销售单都可以正常打开,当时查看了生产环境的ERROR日志,发现抛了这样的异常:java.lang.NumberFormatExcep ...

  9. electron踩坑系列之一

    前言 以electron作为基础框架,已经开发两个项目了.第一个项目,我主要负责用react写页面,第二项目既负责electron部分+UI部分. 做项目,就是踩坑, 一路做项目,一路踩坑,坑多不可怕 ...

随机推荐

  1. w2008 R2 401 - 未授权: 由于凭据无效,访问被拒绝。

    1.打开服务器的"IIS信息服务管理器"-->选择你发布的网站-->选择功能视图中的"身份验证"-->右键匿名身份验证,选择"编辑& ...

  2. EIP-uni-app框架-建立项目

    uni-app介绍 uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架,开发者编写一套代码,可编译到iOS.Android.H5.小程序等多个平台.uni-app在跨端数量,扩展能力, ...

  3. [CentOS7] 设置语言环境

    博主想要将英文环境(en_US.UTF-8)改为中文环境(zh_CN.UTF-8),有两种解决方法 一.临时解决方法 使用LANG=“zh_CN.UTF-8”,这个命令来实现,不过在重新登录的时候又会 ...

  4. [SinGuLaRiTy] (树形)数据结构题目复习

    [SinGuLaRiTy-1023] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 普通平衡树 题目描述 你需要写一种数据结构(可参考题目标 ...

  5. python web框架之Tornado的简单使用

    python web框架有很多,比如常用的有django,flask等.今天主要介绍Tornado ,Tornado是一个用Python写的相对简单的.不设障碍的Web服务器架构,用以处理上万的同时的 ...

  6. SP1811 LCS - Longest Common Substring

    \(\color{#0066ff}{ 题目描述 }\) 输入2 个长度不大于250000的字符串,输出这2 个字符串的最长公共子串.如果没有公共子串则输出0 . \(\color{#0066ff}{输 ...

  7. C语言变量:名称、地址和值

    变量的名称.地址和变量的值之间关系密切. 我们可以认为变量有两个属性:名称和值(其他属性暂不讨论): 计算机编译和加载后也认为变量有两个属性:地址和值.地址就是变量在计算机内部的名称. 许多语言中地址 ...

  8. Python的主要应用领域及应用场景

    参考链接:https://www.cnblogs.com/kaid/p/9016673.html 正文: Python简介 Python(英国发音:/ˈpaɪθən/美国发音:/ˈpaɪθɑːn/), ...

  9. Applese 的毒气炸弹(最小生成树)

    链接:https://ac.nowcoder.com/acm/contest/330/G 来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言5242 ...

  10. FCN用卷积层代替FC层原因(转)

    分类任务 CNN对于常见的分类任务,基本是一个鲁棒且有效的方法.例如,做物体分类的话,入门级别的做法就是利用caffe提供的alexnet的模型,然后把输出的全连接层稍稍修改称为自己想要的类别数,然后 ...