[WebGL入门]十七,递归处理和移动?旋转?缩放

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正。


本次的demo的运行结果

模型坐标变换矩阵的好处

上次,通过操作模型坐标变换矩阵,绘制了多个模型。这次,继续在此基础上,给多个模型再添加上旋转和放大缩小等处理。
看过上一篇文章的人应该知道,在3D渲染的世界里,利用VBO和一部分坐标变换矩阵,只需要少量修改,就可以绘制出大量的模型。当然,计算量也会变少,效率也自然得到了提升。
换句话说,能够熟练使用模型坐标变换矩阵的话,就可以实现高效的渲染,这就是模型坐标变换的好处。
这次,试着绘制三个多边形,一个多边形沿着一个圆进行移动,一个多边形沿Y轴进行旋转,第三个多边形进行放大缩小。

添加一个持续循环的处理

上次的demo,只是在canvas上更新了一次,这次的demo会让模型持续变化,做成一个简单的动画效果。
为了进行动画处理,需要添加一个持续的循环,在javascript中持续循环有很多种方法,本网站基本上就是使用setTimeout函数。
这里说的setTimeout函数是javascript中window对象内置的函数,在指定的时间过后,可以进行指定的处理。
经过的时间的单位是毫秒,1秒是1000毫秒,所以需要指定描述的1千倍。

使用setTimeout实现递归处理

按照刚才说的,使用setTimeout函数可以实现反复的循环处理,那么具体的做法是怎样的呢?
setTimeout函数的第一个参数是调用的函数,第二个参数是需要经过多长时间(毫秒)后调用这个函数。如果第一个参数指定为当前所运行的函数的话,那么就可以实现持续循环了。
?函数A被调用
?在函数A中,使用setTimeout,并传入函数A作为参数
?经过指定的时间后,函数A被调用
按照上面的步骤,把WebGL中绘图部分写成递归函数,就可以持续循环了。

arguments和callee属性

函数的内部调用函数本身的话,可以直接写函数的名字来实现,但是如果是匿名函数的话,这样的做法就行不通了。
解决的办法是有的,使用arguments和callee属性的话就可以调用函数本身了。arguments对象是函数被调用的时候自动生成的,而callee属性就是这个函数本身的引用,使用这种方法的话,即使是匿名函数也可以实现递归。
这次的递归处理,就是使用这里所说的setTimeout+arguments.callee组合来实现。

递归函数中的处理

向递归函数中,添加最少限度的处理。因为在反复循环的处理中,如果添加了多余的没用的处理的话,会导致程序效率降低。
比如,WebGL的context的获取,VBO和着色器的生成等,是不用每次都调用的。一旦对象被生成的话,就可以反复利用了,同样,视图坐标变换矩阵和投影坐标变换矩阵的生成也没有必要放在递归函数中,因为每次都是使用相同的东西。
这样的话,递归函数中所包含处理就基本上限定了,具体的就是下面列出的处理。
?清空画面
?模型坐标变换矩阵的生成
?向uniform中传入坐标变换矩阵
?绘图命令
?画面刷新
?setTimeout+arguments.callee
那么,看一下递归函数部分的代码吧。
>递归函数的代码

// minMatrix.js中的矩阵相关的处理
// matIV对象的生成
var m = new matIV();

// 各种矩阵的生成和初始化
var mMatrix = m.identity(m.create());
var vMatrix = m.identity(m.create());
var pMatrix = m.identity(m.create());
var tmpMatrix = m.identity(m.create());
var mvpMatrix = m.identity(m.create());

// 视图x投影坐标变换矩阵
m.lookAt([0.0, 0.0, 5.0], [0, 0, 0], [0, 1, 0], vMatrix);
m.perspective(45, c.width / c.height, 0.1, 100, pMatrix);
m.multiply(pMatrix, vMatrix, tmpMatrix);

// 声明计数器
var count = 0;

// 持续循环
(function(){
    // canvasを初期化
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clearDepth(1.0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    // 计数器递增
    count++;

    // 使用计数器算出角度
    var rad = (count % 360) * Math.PI / 180;

    // 模型1按照一个圆形轨道进行旋转
    var x = Math.cos(rad);
    var y = Math.sin(rad);
    m.identity(mMatrix);
    m.translate(mMatrix, [x, y + 1.0, 0.0], mMatrix);

    // 完成模型1的坐标变换矩阵,并进行绘图
    m.multiply(tmpMatrix, mMatrix, mvpMatrix);
    gl.uniformMatrix4fv(uniLocation, false, mvpMatrix);
    gl.drawArrays(gl.TRIANGLES, 0, 3);

    // 模型2沿Y轴进行旋转
    m.identity(mMatrix);
    m.translate(mMatrix, [1.0, -1.0, 0.0], mMatrix);
    m.rotate(mMatrix, rad, [0, 1, 0], mMatrix);

    // 完成模型2的坐标变换矩阵,并进行绘图
    m.multiply(tmpMatrix, mMatrix, mvpMatrix);
    gl.uniformMatrix4fv(uniLocation, false, mvpMatrix);
    gl.drawArrays(gl.TRIANGLES, 0, 3);

    // 模型3进行放大缩小
    var s = Math.sin(rad) + 1.0;
    m.identity(mMatrix);
    m.translate(mMatrix, [-1.0, -1.0, 0.0], mMatrix);
    m.scale(mMatrix, [s, s, 0.0], mMatrix)

    // 完成模型3的坐标变换矩阵,并进行绘图
    m.multiply(tmpMatrix, mMatrix, mvpMatrix);
    gl.uniformMatrix4fv(uniLocation, false, mvpMatrix);
    gl.drawArrays(gl.TRIANGLES, 0, 3);

    // context刷新
    gl.flush();

    // 为了循环,进行递归处理
    setTimeout(arguments.callee, 1000 / 30);
})();

文章的最后,会给出demo的链接,大家可以直接查看完整的代码,HTML代码依然没有做任何修改。

这次处理的重点是在匿名函数外面声明了count,匿名函数中让这个变量每次递增,然后使用这个变量的值来进行模型坐标变换。
变量count对360取余数,然后用这个余数来计算弧度。
>获取弧度的代码

var rad = (count % 360) * Math.PI / 180;

无论变量count有多大,余数始终是在0 ~ 359这个范围内,这样就能得到正确的角度了,从而得到弧度,然后使用这个弧度作为其中一个参数,来进行模型坐标变换。

第一个模型,使用弧度来计算sin和cos,得到X和Y就是移动的量。
第二个模型,为了沿着Y轴旋转,也使用了这个弧度作为旋转量。
第三个模型,使用弧度的sin值来计算了放大缩小的量。
注意这里频繁出现的multiply和rotate等函数,都是为了实现各种坐标变换而封装在minMatrix.js中函数。参数的指定可以看之前的文章(minMatrix.js和坐标变换矩阵),里面已经做了详细的解说。
另外,需要注意模型坐标变换的顺序,移动,旋转和放大缩小等各种变换,执行的顺序如果不对的话,结果就有变化了。这里之前的文章也都说过了,不清楚的人可以复习一下前面的内容。

总结

这次利用递归处理实现了持续循环,并介绍了模型坐标变换矩阵的处理。以后,动态的demo会越来越多,这次介绍的持续循环也会被更多的用到。
匿名函数或者普通的函数的递归可能是个稍微难理解的概念,也要着急,仔细考虑的话会理解的。如果处理比较多的话,这一部分处理可能应该单独分离出来。

下次,介绍一个缓存索引。

下面的链接是这次的demo,可以直接运行,所以一定参考一下。
模型的移动,旋转和放大缩小的动态demo

http://wgld.org/s/sample_005/

转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend

[WebGL入门]十七,递归处理和移动?旋转?缩放

时间: 2024-10-13 11:45:12

[WebGL入门]十七,递归处理和移动?旋转?缩放的相关文章

WebGL递归处理和移动?旋转?缩放

3D世界只有三种运动方式:移动.旋转.放大缩小. 使用setTimeout函数可以实现反复的循环处理,那么具体的做法是怎样的呢?setTimeout函数的第一个参数是调用的函数,第二个参数是需要经过多长时间(毫秒)后调用这个函数.如果第一个参数指定为当前所运行的函数的话,那么就可以实现持续循环了.    ?函数A被调用    ?在函数A中,使用setTimeout,并传入函数A作为参数    ?经过指定的时间后,函数A被调用    按照上面的步骤,把WebGL中绘图部分写成递归函数,就可以持续循

[WebGL入门]十八,利用索引缓存来绘图

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 本次的demo的运行结果 对应复杂的模型 上次,通过操作模型坐标变换矩阵,实现了多个模型的移动,旋转和放大缩小.但是,渲染的依然是简单的三角形,是个构造及其简单的模型.但是实际中,用WebGL来绘制一个简单的三角形的机会是很少见的.至少是个四角多边形吧,通常会是更复杂的模型.伴随着模型的复杂化

[WebGL入门]二十,绘制立体模型(圆环体)

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 本次的demo的运行结果 立体的模型 这次稍微喘口气,开始绘制立体模型.这里说的[喘口气]是指本次的文章中没有出现任何新的技术知识点.只是利用到现在为止所介绍过的内容,来绘制一个立体的圆环体.到现在为止,只绘制了三角形和四边形,当然,在三维空间中绘制简单的多边形也没什么不对,但是缺点儿说服力.

[WebGL入门]五,矩阵的基础知识

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 不是让你到店前面排队 lufy:你一定奇怪,为什么叫这个题目,因为日语中的矩阵叫做"行列",所以作者就给读者们开了个玩笑,我就这么直接翻译了,大家知道什么意思就行了. 在3D渲染的世界里,会很频繁的用到矩阵. 这里所说的矩阵,是数学里的矩阵.英语中叫做Matrix. 矩阵虽然听起来好

[WebGL入门]十九,遮挡剔除和深度测试

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 本次的demo的运行结果 多边形的外侧,内侧和遮挡剔除 上次介绍了索引缓存,以及使用IBO来绘图,使用索引缓存可以循环利用重复的顶点,能够提高绘图效率.这之后的文章,如果没有特殊的原因的话,基本上都会使用索引缓存,通过drawElements来绘图.这次来说一下遮挡剔除和深度测试,这是两个重要

[WebGL入门]十三,minMatrix.js和坐标变换矩阵

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 坐标变换矩阵的基本功能 进行基本的3D渲染的时候,需要准备3个坐标变换矩阵,这个在之前的文章中说过很多次了.第一个是模型变换矩阵,DirectX中叫做世界变换矩阵.模型变换矩阵影响的是所绘制的模型,模型的位置,模型的旋转,模型的放大和缩小等相关的情况.第二个是视图变换矩阵,简单来说,就是定义拍

WebGL入门教程第1篇——六色立方

WebGL入门教程第1篇——六色立方 WebGL,一项允许开发人员在浏览器里操纵GPU来显示图形的技术.让我们一起走进WebGL的世界. 读者对象 本系列适合具有基础JavaScript知识的开发人员. 准备工作 我们应该在本地搭建好web服务器,或者安装了具有预览功能的IDE.如果你安装了Visual Studio,Nivk童鞋为我们开发了WebGL代码提示功能,你可以通过以下步骤使Visual Studio支持WebGL代码提示:打开Visual Studio——点击工具——点击选项——展开

[WebGL入门]二,开始WebGL之前,先了解一下canvas

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. HTML5和canvas标签 现在(2012年2月)HTML5依然处于草案阶段. HTML5支持网页端的多媒体功能和画布功能,追加了很多全新的更合理的Tag标签,各个浏览器也都在逐渐的完善这些新的特性. Canvas对象表示一个 HTML画布元素,如它的名字一样,它定义了一个API支持脚本化客

WebGL入门教程(二)-webgl绘制三角形

前面已经介绍过了webgl,WebGL入门教程(一)-初识webgl(http://www.cnblogs.com/bsman/p/6128447.html),也知道了如何绘制一个点,接下来就用webgl画出一个三角形. 效果图: 在WebGL入门教程(一)-初识webgl中,知道如何绘制一个点 //绘制一个点 gl.drawArrays(gl.POINTS, 0, 1); 但是图形是有多个点组成,那么就应该考虑如何绘制多个点,WebGL提供了一种很方便的机制,缓冲区对象(buffer obje