Web Worker之Milo Yip的光线追踪
来源:广州中睿信息技术有限公司官网
发布时间:2012/10/21 23:25:16 编辑:admin 阅读 981
//Vector3.jsVector3=function(x,y,z){this.x=xthis.y=ythis.z=z}Vector3.prototype={copy:function(){ret


run
以上是milo yip写的《用JavaScript玩转计算机图形学(一)光线追踪入门》中代码的Web Worker版本。我将代码略作修改使其能够在Web Worker中运行,并且添加的uv坐标使得Checker材质能更通用,和折射(最后3个示例)。当然,我这篇文章只说Web Worker部分。

Web Worker简介

一个Web Worker对象就对应着一个操作系统的线程。使用如下方式创建:
var worker = new Worker("foo.js");  
Worker构造函数的参数是个url,在新建的线程中就执行foo.js中的代码。但是在foo.js中的代码是有限制的,它不能直接访问在主线程也就是html页面中的任何对象,而只能使用消息来进行通信。
例如,html中的代码:
var worker = new Worker("foo.js");  worker.onmessage = function(e){  console.log(e.data);  }  worker.postMessage("world");  
foo.js中的代码
this.onmessage = function(e){  postMessage("hello,"+e.data);  }  
在上述代码中,html中新建一个Worker对象,并监听message事件(也可以使用AddEventListener),最后发送一个"world"字符串给Worker。
在foo.js中,监听message时间,当收到来自于主线程的消息时,在消息前面加上"hello,"并回复。
在大多数情况下,都是html页面中的代码发送一个消息给Worker,Worker进行复杂的计算,并且将结果用消息发送给html页面。
不过,postMessage能发送的消息并不能是任意的对象,这个对象不能包含函数,任何dom对象,等等。幸运的是,可以是canvas中的ImageData对象,上面的示例传递的就是ImageData对象。(具体哪些可以,哪些不可以请参考:https://developer.mozilla.org/en/DOM/The_structured_clone_algorithm)

Inline Web Worker

Worker对象构造函数参数一定要是一个url,那如何才能将Web Worker代码和html写在同一个文件中呢? 代码如下:
function createBlobUrl(text)  {  var bb;  if (window.BlobBuilder)  bb = new BlobBuilder();  else if (window.WebKitBlobBuilder)  bb = new WebKitBlobBuilder();  else if (window.MozBlobBuilder)  bb = new MozBlobBuilder();  else  return null;  bb.append(text);  if (window.URL && URL.createObjectURL)  {  return window.URL.createObjectURL(bb.getBlob());  }  else if (window.webkitURL && webkitURL.createObjectURL)  {  return window.webkitURL.createObjectURL(bb.getBlob());  }  else  return null;  }  function createInlineWebWorker(id)  {  var url = createBlobUrl(document.getElementById(id).textContent);  if (!url) return null;  return new Worker(url);  }  
CreateBlobUrl(text)会创建一个url,浏览器访问这个url就会返回text的内容(不过由于chrome一个该死的wontfix的bug,此函数对于保存的本地html不起作用)。 试试,复制下面的url,并在浏览器的新页面打开

是不是内容是abcdefg呢?
这样就可以这么写了:
<script id="worker1" type="webworker">  this.onmessage = function(e){  postMessage("hello,"+e.data);  }  </script>  <script>  var worker = createInlineWebWorker("worker1")  </script>  
注意哦,第一个script的type是worker,所以浏览器并不会执行其代码。而且由于使用script标签,所以中间的内容并不需要html escape也不会显示出来。

最后

我来说一下,上面光线追踪中Web Worker代码是怎么写的。 Web Worker代码如下:
self.onmessage = function(e)  {  var data = e.data;  if (data.type=="eval")  {  var ret;  var code = data.code;  try  {  ret = eval(code);  }  catch(err)  {  postMessage({type:"log",msg:err.message+"\nline:"+err.lineNumber});  postMessage({type:"error",msg:err.message+"\nline:"+err.lineNumber});  return;  }  postMessage({type:"result",result:ret});  }  }  
很简单吧,就是在Web Worker中运行一下html页面上发过来的代码(不是函数,是代码的文本哦)。如果成功,则将返回值返回给页面;出错则将出错信息返回给页面。例如,你想在Web worker中计算1到100的和,则代码如下:
function calc(n)  {  var ret = 0;  for (var i=1;i<=n;++i)  ret += i;  return ret;  }  worker.onmessage = function(e){  if (e.data.type == "result")  {  alert(e.data.result)  }  }  worker.postMessage({  type:"eval",  code:calc.toString()+";calc(100);"  });  
好啦,就写到这里啦。其实,我对Web Worker的了解就是参考了google "Web Worker"中第一页的几篇文章,尤其这篇比较通俗易懂:http://www.html5rocks.com/en/tutorials/workers/basics/希望大家能认真看一下。
最后的最后,希望下次我能写篇文章来说一下光线追踪的折射。
联系我们CONTACT 扫一扫
愿景:成为最专业的软件研发服务领航者
中睿信息技术有限公司 广州•深圳 Tel:020-38931912 务实 Pragmatic
广州:广州市天河区翰景路1号金星大厦18层中睿信息 Fax:020-38931912 专业 Professional
深圳:深圳市福田区车公庙有色金属大厦509~510 Tel:0755-25855012 诚信 Integrity
所有权声明:PMI, PMP, Project Management Professional, PMI-ACP, PMI-PBA和PMBOK是项目管理协会(Project Management Institute, Inc.)的注册标志。
版权所有:广州中睿信息技术有限公司 粤ICP备13082838号-2