WebGL入门与进阶3

前文已经大概讲解了一些基础知识,涵盖了WebGL创建,着色器,着色器编程以及缓存区等知识,一些简单的点面效果即可以基于此来完成,接下来让我们绘制一下如下的效果: 让我们先准备一下前期的WebGL内容,首先让我们来创建一个可以接受参数的着色器,(如果不清楚具体要怎么创建可以参考上一章教程内容) 接下来,我们需要创建多个点的坐标,所有点在同一行时,只有X坐标是变化的,y是相同的。 但因为WebGL的坐标系与实际页面中的坐标系是不同的,如下图,普通canvas坐标系与正常的浏览器像素值相同,但WebGL中的坐标系是以整个WebGL中心点为(0.0,0.0),而且坐标的精确度为小数点后一位。坐标系对比如下图所示: 然后你知道了这个依旧会绘制出超级模糊的图像,那是因为整个WebGL的尺寸是与canvas宽度与高度相关连的,并且canvas的宽度与高度如果用css来设置的话,会被默认成100×100,也就意味着,你绘制出来的图形是把100×100的图形拉伸到当前canvas的尺寸中。所以正确的设置canvas的方式应该如下:

首先我们需要先将对应的真实坐标转换成WebGL坐标,因为canvas宽度的一半对应为WebGL的1.0尺寸。所以将真实像素除以宽度的一半就可以得到对应的WebGL尺寸,高度与宽度的处理方式一致。

有了点,那么我们就可以使用先前讲过的缓存区开始批量绘制点了。(如果不清楚具体如何使用缓存区绘制,也可以点击上一章)。 接下来我们要让他动起来,怎么动起来呢?思路是我们可以在不停的重绘,并且将点进行轻微位移即可达到效果,定时执行函数可以使用setInterval或setTimeout。但此2个函数性能上有很大问题,并且也无法完美的匹配浏览器的刷新频率。 在这里我跟大家介绍一个新函数requestAnimationFrame。 requestAnimationFrame是为了提高js动画性能而诞生的神器。下面我们简单来介绍一下这个函数为何被誉为神器。 requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,也就是没s刷新60次。因与浏览器刷新频率一样所以不会出现看似卡顿的情况出现。 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量 requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销 具体的内容以后有机会可以单独详细来介绍此函数功能。 接下来让我们来绘制一个变化的函数,变化值从0开始,requestAnimationFrame内容入参为循环执行的函数名。

接下来我们需要将之前绘制点的部分功能函数提取到单独的一个函数中,方便动画循环调用时使用。

接下来也就是最重要的,我们需要每次都变更对应点的坐标位置,因我们要使用波浪效果,所以采用正弦函数来实现,首先让所有的点都按照每次变更10度的浮动,并且因为是上下移动,我们只需要变更y轴的坐标即可。

正弦函数Math.sin传入的值不是角度,而是弧度,我们需要通过下面的函数把角度转化为弧度,函数如下:(如果您不知道弧度与角度的关系,建议自行查询)

我们为此函数中x与y的值进行一下操作。 为保证所有的点肯定全部覆盖屏幕,我们将每个点的间距调整按照整个canvas宽度超过500的尺寸来平均分,整个坐标系向做便宜200,也就是右边还存在300的富于空间,这样即使有错开位移也不会让屏幕露出空白。接下来,为了让上面的点波动比下面的点大,让我们来设置了一个最大倍数,并且将行数与此倍数关联,这样就会使动画上下浮动不一样了。

我们达到了横向。 接下来我们在角度便宜中添加上x轴的影响力。

让我们看看效果,波动开始有偏差了。 效果按照我们预期的方向前进了,接下来我们扩大x轴的影响,这个个人可以一点一点尝试,我们直接扩大到5倍。

看样子动画效果已经基本达到了效果,接下来让我们把上面的点变小,下面的点变大。产生前后的视觉差。 如何让渲染的点尺寸不同呢?没错我们也可以使用缓存区来操作。 对创建点的函数进行改造:

我们把点与对应的坐标匹配一下,并且把点的数量动态化,让我们在使用缓存区来把size动态批量化。

记得着色器上要声明一个接收的参数哦。

然后我们在render函数中可以直接使用其函数进行重绘。 我们已经绘制出来了最终效果,本着开源的原则,完整代码链接如下: https://github.com/jdf2e/webgl-demo 有兴趣欢迎关注我们的公众号:全栈探索。欢迎交流。

WebGL入门与进阶2

程序创建完之后,我们需要需要对着色器进行动态控制才能达到我们所需要的功能。(如不知道怎么创建WebGL,可参考上篇文章)。 首先让我来介绍2个变量,我们需要借助这2个变量搭建的桥梁才能使JavaScript与GLSL ES之间进行沟通。 attribute: 用于顶点点着色器(Vertex Shader)传值时使用。 uniform:可用于顶点着色器(Vertex Shader)与片元着色器(Fragment Shader)使用。 将顶点动态化 先在顶点着色器代码中,将对应的vec4的固定值变成变量。

位置参数使用了attribute变量来承载。这样WebGL对象就可以获取到对应的存储位置,就可以去动态改变GLSL变量了。 使用WebGL来获取对应参数的存储地址。

然后给变量赋值。

注意:vertexAttrib3fv这个函数是典型的GLSL语法命名规范,vertexAttrib函数功能: 3:对应需要传3个参数,或者是几维向量。 f:表示参数是float类型。 v:表示传如的为一个vector变量。 也就是说对应设置顶点着色器的函数有一下几种功能:

同样操作可以如下修改PointSize:

片元着色器编程 对片元着色器变成需要使用uniform变量来承载。

获取片元着色器变量地址。

给变量赋值。

注意:uniform3fv这个函数是典型的GLSL语法命名规范,uniform3fv函数功能: 3:对应需要传3个参数,或者是几维向量。 f:表示参数是float类型。 u:表示参数是Uint32Array类型。 i:表示参数是integer类型。 ui:表示参数是unsigned integer类型。 v:表示传如的为一个vector变量。 uniform对应函数同attribute的函数构成相似,这里就不详细列举,具体请参考 [1]。 着色器中的代码precision mediump float;表示的意思是着色器中配置的float对象会占用中等尺寸内存。 具体包含的尺寸: highp for vertex positions, mediump for texture coordinates, lowp […]

WebGL入门与进阶1

改革开发40年以来,世界日新月异,无论从生活到精神上都有了颠覆性的变化,曾经教授还是教书的,砖家还叫专家,太阳还不叫日,菊花还是一种花,老王还没那么多,Web还只需要做IE,XHR还没出生的时候,怎么能想到现在浏览器会提供如此丰富多彩的多媒体生活,无论是音频、视频、以及各种漂亮的页面都在让用户更好的拥抱着互联网,当二维页面无法满足用户之后,会出现什么样的内容来继续推进Web进展呢,没错,就是3D,浏览器中看到的内容从平面变成3D的时候,oH,My God,提起来都让人兴奋。 网站的未来是这样子的: 的确,3D技术会让平淡的网页变的更酷,更让人眼花撩眼,这本后隐藏着什么呢?来来,咱们做下来泡一壶茶,边喝边聊,这个神奇的家伙叫做WebGL。 谈起WebGL可能有一些人比较陌生,实际上WebGL是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。显然,WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏等等。 此链接可以查看你的游览器是否支持WebGL以及支持的版本[1]。 看WebGL的背景实际上是JavaScript操作一些OpenGL接口,也就意味着,可能会编写一部分GLSL ES 2.0的代码,没错,你猜对了,WebGL只是绑定了一层,内部的一些核心内容,如着色器,材质,灯光等都是需要借助GLSL ES语法来操作的. 基于WebGL周边也衍生了众多的第三方库,如开发应用类的Three.js,开发游戏类的Egert.js等,都大大的降低了学习WebGL的成本,但是本着有问题解决问题,没问题制造问题在解决问题的程序猿态度,还是觉得应该稍微了解一下WebGL一些基本的概念,以便能更好的去理解不同框架带来的便捷以及优势。 接下来先简单介绍一下使用到的知识要点。 创建webGL对象 不同浏览器生命WebGL对象方式有所区别,虽然大部分浏览器都支持experimental-webgl,而且以后会变成webgl,所以创建时做一下兼容处理

着色器 WebGL依赖一种新的称为着色器(shader)的绘图机制。着色器提供了灵活且强大的绘制二维或三维图形的方法,所有WebGL必须使用它。着色器不仅强大,而且更复杂,仅仅通过一条简单的绘图指令是不能操作它的。 WebGL需要两种着色器 顶点着色器(Vertex shader):顶点着色器是用来描述顶点特性(如位置、颜色等)的程序。顶点(Vertex)是指二维或三维空间的一个点,比如二维或三维空间线与线之间的交叉点或者端点。 片元着色器(Fragment shader):进行逐片元处理过程(如光照等)的程序。片元(fragment)是一个WebGL的术语,你可以将其理解成像素。 着色器语言使用的是GLSL ES语言,所以在javascript需要将之存放在字符串中,等待调用编译 创建顶点着色器:

创建片元着色器:

浏览器的整个过程如下: 着色器中包含几个内置变量:gl_Position、gl_PointSize、gl_FragColor。 着色器语言中涉及到vec4的数据类型,此数据类型是一个思维浮点数组,所以其值不可以是整形如(1,1,1,1),正确应为:(1.0,1.0,1.0,1.0) gl_Position: 为一种vec4类型的变量,且必须被赋值。四维坐标矢量,我们称之为齐次坐标,即(x,y,z,w)等价于三维左边(x/w,y/w,z/w),w相当于深度,没有特殊要求设置为1.0即可。 gl_PointSize:表示顶点的尺寸,也是浮点数,为非必填项,如果不填则默认显示为1.0。 gl_FragColor:该变量为片元着色器唯一的内置变量,表示其颜色,也是一个vec4类型变量,分别代表(R,G,B,A),不过颜色范围是从0.0-1.0对应Javascript中的#00-#FF。 有了着色器我们就可以着手去绘制图像了,既然绘制3D图形,必然会有对应的三维坐标系,WebGL采用右手坐标系,如图所示: 使用着色器 让我们来看看如何把着色器代码编译并且使用起来 着色器代码需要载入到一个程序中,webgl使用此程序才能调用着色器。

让我们尝试绘制一个点

我们来看一看最终结果,果然出来了一个点。 Why? 咋这么模糊?没错不是你的眼镜度数又高了,的确是模糊的。 让我们来说说WebGL的坐标系。 因为WebGL的坐标系与实际页面中的坐标系是不同的,如下图,普通canvas坐标系与正常的浏览器像素值相同,但WebGL中的坐标系是以整个WebGL中心点为(0.0,0.0),而且坐标的精确度为小数点后一位。坐标系对比如下图所示: 图上的实例是在使用源生WebGL时,并且未对视角有设置的情况下的默认值。默认视角的位置为(0.0, 0.0, 0.0),并且lookAt(0.0, […]

CSS 3D Panorama – 淘宝造物节技术剖析

前言 3D 全景并不是什么新鲜事物了,但以前我们在 Web 上看到的 3D 全景一般是通过 Flash 实现的。若我们能将 CSS3 Transform 的相关知识运用得当,也是能实现类似的效果。换句话说,3D 全景其实就是 CSS3 3D 的应用场景之一。 准备 在实现 CSS3 3D 全景之前,我们先理清部分 CSS3 Transform 属性: transform-origin:元素变形的原点(默认值为 50% 50% 0,该数值和后续提及的百分比均默认基于元素自身的宽高算出具体数值); perspective:指定了观察者与z=0平面的距离,使具有三维位置变换的元素产生透视效果。(默认值:none,值只能是绝对长度,即负数是非法值); transform-style:用于指定其为子元素提供2D还是3D的场景。另外,该属性是非继承的; transform:该属性能让你修改CSS可视化模型的坐标空间,其中包括 平移(translate)、旋转(rotate)、缩放(scale) 和 扭曲(skew)。 下面对上述的一些点进行更深入的分析: 对于 perspective,该属性指定了“眼睛”与元素的 perspective-origin (默认值是 50% 50%)点的距离。那么问题来了:“当我们应用 px 作为衡量单位时,那它的实际距离该如何量化呢(即如何得到我们熟悉且易于表达的距离)?” 答:当我们的屏幕的分辨率是1080P(1920*1080px),且该元素或祖先元素的 perspective 值是 1920px 时,该应用了 CSS3 3D Transform 的元素的立体效果就相当于我们在距离一个屏幕宽度(1920px)的屏幕前观看该元素的真实效果。尽管如此,目前我也不清楚如何准确地为元素设置一个合适的 perspective 值,只能猜测个大概值,然后再动态修改值,以达到满意的呈现效果。 根据 相似三角形 的性质可计算出被前移的元素最终在屏幕上显示的实际大小 […]

© 2018 JDC. All Rights Reserved.