校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > 淺談three.js中的needsUpdate的應用

淺談three.js中的needsUpdate的應用

熱門標簽:地圖標注自己去過的地方 江蘇高頻外呼系統線路 平頂山電子地圖標注怎么修改 高德地圖標注錯誤怎么修改 搜狗星級酒店地圖標注 標準智能外呼系統 洛陽市伊川縣地圖標注中心官網 會聲會影怎樣做地圖標注效果 電銷機器人視頻
three.js里的很多對象都有一個needsUpdate屬性,文檔中很少有寫(不過three.js的文檔本來就沒多少,很多問題還得靠github上的issues),網上各式各樣的教程中也不太會寫這個,因為對于簡單的入門程序而言,是用不到這個屬性的。
那么這個屬性到底是用來干嘛的,一言以敝之就是告訴renderer這一幀我該更新緩存了,盡管作為一個標志位用途很簡單,但是因為要知道為什么要更新緩存,要更新哪些緩存,所以還是有必要好好了解下的。
為什么需要needsUpdate
首先還是來看下為什么需要緩存,緩存的存在一般都是為了減少數據傳輸的次數,從而減少程序在數據傳輸上消耗的時間,這里也是,一般一個物體(Mesh)要最后能夠成功顯示到屏幕前是很不容易的,需要轉三次戰場
首先是通過程序將所有的頂點數據和紋理數據從本地磁盤讀取到內存當中。
然后程序在內存中做了適當的處理之后就要將那些需要繪制到屏幕前的物體的頂點數據和紋理數據傳輸到顯存當中。
最后在每一幀渲染的時候將顯存中的頂點數據和紋理數據flush到GPU中進行裝配,繪制。
根據那個金字塔式的數據傳輸模型,第一步顯然是最慢的,如果是在WebGL這樣的環境中通過網絡來傳輸,那就更加慢了,其次是從內存傳輸到顯存的時間,這個后面會做一個簡單的數據測試。
然后是這三步操作的使用頻率,對于小場景來說,第一步是一次性的,就是每次初始化程序的時候就會將一個場景的所有數據都加載到內存中了,對于大場景來說,可能會做一些異步加載,但是目前暫時不在我們考慮的問題當中。 對于第二步的頻率,應該是這次要講的最主要的,首先寫個簡單的程序測試一下做這一步傳輸所帶來的消耗

復制代碼
代碼如下:

var canvas = document.createElement('canvas');
var _gl = canvas.getContext('experimental-webgl');
var vertices = [];
for(var i = 0; i < 1000*3; i++){
vertices.push(i * Math.random() );
}
var buffer = _gl.createBuffer();
console.profile('buffer_test');
bindBuffer();
console.profileEnd('buffer_test');
function bindBuffer(){
for(var i = 0; i < 1000; i++){
_gl.bindBuffer(_gl.ARRAY_BUFFER, buffer);
_gl.bufferData(_gl.ARRAY_BUFFER, new Float32Array(vertices), _gl.STATIC_DRAW);
}
}

先簡單解釋下這個程序,vertices是一個保存頂點的數組,這里是隨機生成了1000個頂點,因為每個頂點都有x,y,z三個坐標,所以需要一個3000大小的數組, _gl.createBuffer命令在顯存中開辟了一塊用來存放頂點數據的緩存,然后使用_gl.bufferData將生成的頂點數據從內存傳輸一份copy到顯存中。 這里假設了一個場景中有1000個1000個頂點的物體,每個頂點是3個32位4個字節的float數據,計算一下就是差不多1000 x 1000 x 12 = 11M的數據,profile一下差不多消耗了15ms的時間,這里可能看看15ms才這么點時間,但是對于一個實時的程序來說,如果要保證30fps的幀率,每一幀所需要的時間要控制在30ms左右,僅僅是做一次數據的傳輸就花去了一半的時間怎么成,要知道大頭應該是GPU中的繪制操作和在CPU中的各種各樣的處理啊,應該吝嗇整個渲染過程中的每一步操作。
所以應該盡量減少這一步的傳輸次數,其實可以做到剛加載的時候就把所有的頂點數據和紋理數據從內存一并傳輸到顯存當中,這就是現在three.js做的,第一次就把需要繪制的物體(Geometry)的頂點數據傳輸到顯存中,并且緩存這個buffer到geometry.__webglVertexBuffer,之后每次繪制的時候都會判斷Geometry的verticesNeedUpdate屬性,如果不需要更新就直接使用現在的緩存,如果看到verticesNeedUpate為true, 就會重新將Geometry中的頂點數據傳輸到geometry.__webglVertexBuffer中,一般對于靜態物體我們是不需要這一步操作的,但是如果遇到頂點會頻繁改變的物體,例如用頂點來做粒子的粒子系統,還有使用了骨骼動畫的Mesh, 這些物體每一幀都會改變自己的頂點,所以需要每一幀都需要將其verticesNeedUpdate屬性設為true來告訴renderer我需要重新傳輸數據了!
其實在WebGL程序中,更多的會在vertex shader中去改變頂點的位置來完成粒子效果和骨骼動畫,盡管如果放在cpu端計算更容易擴展,但是因為javascript的計算能力的限制,更多的還是會把這些計算量大的操作放到gpu端操作。 這種情況下并不需要重新傳輸一次頂點數據,所以上面那種case在實際程序中其實用到的不多,更多的還是會去更新紋理和材質的緩存。
上面那個case主要描述的是一個傳輸頂點數據的場景,除了頂點數據,還有一個大頭就是紋理,一張1024*1024大小的R8G8B8A8格式的紋理所要占用的內存大小也要高達4M,于是看下面這個例子

復制代碼
代碼如下:

var canvas = document.createElement('canvas');
var _gl = canvas.getContext('experimental-webgl');
var texture = _gl.createTexture();
var img = new Image;
img.onload = function(){
console.profile('texture test');
bindTexture();
console.profileEnd('texture test');
}
img.src = 'test_tex.jpg';
function bindTexture(){
_gl.bindTexture(_gl.TEXTURE_2D, texture);
_gl.texImage2D(_gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, img);
}

這里就不需要變態的重復1000次了,一次傳輸10241024的紋理就已經花了30ms,一張256256的差不多是2ms,所以three.js中對于紋理也是盡量只在最開始的時候傳輸一次,之后如果texture.needsUpdate屬性不手動設為true的話就會一直直接使用已經傳輸到顯存中的紋理。
需要更新哪些緩存
上面通過兩個case描述了為什么three.js要加這么一個needsUpdate屬性,接下來列舉一下幾個場景來知道在什么情況下需要手動的更新這些緩存。
紋理的異步加載
這算是一個小坑吧,因為前端的圖片是異步加載的,如果在創建好img后直接寫texture.needsUpdate=true的話,three.js的renderer中會這一幀中就使用_gl.texImage2D將空的紋理數據傳輸到顯存中,然后就將這個標志位設成false, 之后真正等到圖片加載完成的時候確不再更新顯存數據了,所以必須要在onload事件中等整張圖片加載完成后再寫texture.needsUpdate = true
視頻紋理
大部分紋理都是像上面那個case直接加載和傳輸一次圖片就行了,但是對于視頻紋理來說并不是,因為視頻是一個圖片流,每一幀要顯示的畫面都不一樣,所以每一幀都需要將needsUpdate設為true來更新顯卡中的紋理數據。
使用render buffer
render buffer是比較特殊的對象,一般的程序在整個場景繪制出來后都是直接flush到屏幕了,但是如果多了post processing或這screen based xxx(例如screen based ambient occlusion)的話,就需要將場景先繪制到一個render buffer上,這個buffer其實就是一張紋理,只不過是上一步繪制生成的,而不是從磁盤加載的。three.js中有一個專門的texture對象WebGLRenderTarget來初始化和保存renderbuffer, 這種紋理也需要在每一幀設置一下needsUpdate為true
Material的needsUpdate
材質在three.js中是通過THREE.Material來描述的,其實材質并沒有什么數據要傳輸,但是為什么還要搞一個needsUpdate呢,這里還要說一下shader這個東西,shader直譯過來是著色器,提供了在gpu中編程處理頂點和像素的可能性,在繪畫中有個shading的術語來表示繪畫的明暗法,GPU中的shading也類似,通過程序計算光照的明暗來表現物體的材質,ok, 既然shader是一段跑在GPU上的程序,那么像所有程序一樣都需要進行一次編譯鏈接的操作, WebGL中是在運行時對shader程序進行編譯的,這當然需要消耗時間,因此也是最好能夠一次編譯就運行到程序結束。所以three.js中就在material初始化的時候就編譯鏈接了shader程序并且緩存了編譯鏈接后得到的program對象。一般一個material是不需要再去重新編譯整個shader了,材質的調整只需要修改shader的uniform參數就行了。但是如果是替換了整個材質,比如將原來phong的shader替換成了一個lambert的shader,就需要將material.needsUpdate設置成true去重新做一次編譯。不過這種情況不多見,更常見的是下面提到的一種情況。
添加和刪除燈光
這個應該還是在場景中比較常見了的吧,可能很多剛開始用three.js的人都會掉進這個坑里,在給場景動態添加了一個燈光后發現這個燈光怎么不起作用,不過這是在用three.js內置的shader的情況下,例如phong, lambert,看renderer里的源代碼就會發現three.js在內置的shader代碼中使用#define來設置場景中燈光的個數,而這個#define的值是在每次更新材質的時候通過字符串拼接shader得到,代碼如下

復制代碼
代碼如下:

"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,

確實這種寫法能夠有效的減少了gpu寄存器的使用,如果只有一盞燈光就可以只聲明一個一盞燈光所需要的uniform變量,但是在每次燈光數量改變,特別是添加的時候就需要重新拼接編譯鏈接一次shader,這時候也需要將所有材質的material.needsUpdate設為true;
改變紋理
這里的改變紋理指的并不是更新紋理數據,而是原來材質使用了紋理,后來不使用了,或者原來材質不使用紋理后來又加上去了,如果不手動強制更新材質都會導致最后出來的效果跟自己想的不一樣,產生這種問題的原因跟上面添加燈光差不多,也是因為shader中加了一個宏來判斷是否使用了紋理,

復制代碼
代碼如下:

parameters.map ? "#define USE_MAP" : "",
parameters.envMap ? "#define USE_ENVMAP" : "",
parameters.lightMap ? "#define USE_LIGHTMAP" : "",
parameters.bumpMap ? "#define USE_BUMPMAP" : "",
parameters.normalMap ? "#define USE_NORMALMAP" : "",
parameters.specularMap ? "#define USE_SPECULARMAP" : "",

所以每次map, 或者envMap或者lightMap等改變真值的時候都需要更新材質
其它頂點數據的改變
其實上面紋理的改變還會產生一個問題,主要是在初始化的時候沒有紋理,但是后來動態添加上去這種環境下,光是將material.needsUpdate設為true還不夠,還需要將geometry.uvsNeedsUpdate設成true, 為什么會有這種問題呢,還是因為three.js對程序的優化,在renderer中第一次初始化geometry, material的時候,如果判斷為沒有紋理,盡管內存中的數據中有每個頂點uv數據,但 three.js 還是不會將這些數據copy到顯存中,初衷應該還是為了節省點寶貴的顯存空間,但是在添加紋理后geometry并不會很智能的重新去傳輸這些uv數據以供紋理使用,必須要我們手動的將設置uvsNeedsUpdate來告知它該更新uv了, 這個問題真是開始的時候坑了我很長時間。
關于幾種頂點數據的needUpdate屬性可以看這條issue
https://github.com/mrdoob/three.js/wiki/Updates
最后
three.js的優化做的是不錯,但是在各種優化下帶來的是各種可能踩到的坑,這種情況最好的辦法也只能是看源代碼了,或者去github上提issues

標簽:常德 廣西 松原 蚌埠 鄂爾多斯 阿克蘇 廣東 果洛

巨人網絡通訊聲明:本文標題《淺談three.js中的needsUpdate的應用》,本文關鍵詞  淺談,three.js,中的,needsUpdate,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《淺談three.js中的needsUpdate的應用》相關的同類信息!
  • 本頁收集關于淺談three.js中的needsUpdate的應用的相關信息資訊供網民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    成人v精品蜜桃久久一区| 久久一日本道色综合| 精品欧美乱码久久久久久1区2区| 国产亚洲女人久久久久毛片| 亚洲自拍偷拍综合| 成人综合婷婷国产精品久久蜜臀 | 在线视频你懂得一区| 国产欧美在线观看一区| 日韩高清不卡一区| 在线国产电影不卡| 亚洲国产精品精华液2区45| 人人狠狠综合久久亚洲| 在线观看视频一区二区欧美日韩| 国产欧美日韩三级| 狠狠狠色丁香婷婷综合激情| 欧美日韩一级黄| 一区二区成人在线| 色哟哟精品一区| 国产精品美女一区二区| 国产白丝网站精品污在线入口| 欧美tickling挠脚心丨vk| 亚洲一区二区三区四区在线观看| 一本大道久久a久久精二百| 国产精品青草久久| 成人动漫中文字幕| 国产精品日产欧美久久久久| 成人中文字幕合集| 国产欧美视频一区二区三区| 亚洲四区在线观看| 99国产一区二区三精品乱码| 国产精品女上位| 91色综合久久久久婷婷| 亚洲免费av观看| 欧美伊人久久大香线蕉综合69 | 热久久免费视频| 日韩一区二区三区免费看| 日本在线不卡一区| 日韩一区二区三区av| 美女视频第一区二区三区免费观看网站| 9191国产精品| 美国欧美日韩国产在线播放| 久久丝袜美腿综合| 成人国产精品视频| 一区二区三区在线免费播放| 91国在线观看| 青娱乐精品视频在线| 精品美女在线观看| 成人动漫一区二区| 亚洲乱码精品一二三四区日韩在线| 91香蕉视频污| 日韩精品一区第一页| 欧美成人aa大片| 不卡视频在线看| 亚洲国产精品久久久男人的天堂| 91精品免费观看| 国产成人精品网址| 亚洲精品成人少妇| 日韩小视频在线观看专区| 高清不卡一二三区| 亚洲一区二区av电影| 精品捆绑美女sm三区| 99精品国产99久久久久久白柏 | 欧美一区二区三区视频免费播放| 国产剧情一区二区| 亚洲精品videosex极品| 欧美一级视频精品观看| 成人一区二区三区中文字幕| 亚洲福利视频导航| 精品少妇一区二区三区免费观看| 成人app软件下载大全免费| 亚洲成a人v欧美综合天堂下载| 久久亚洲精华国产精华液 | 久久久久久黄色| 欧美亚洲自拍偷拍| 韩国午夜理伦三级不卡影院| 亚洲天堂2014| 久久久亚洲精华液精华液精华液| 91欧美一区二区| 韩国欧美一区二区| 亚洲国产中文字幕在线视频综合| 久久网这里都是精品| 欧美日韩精品二区第二页| 懂色av噜噜一区二区三区av| 日韩精品午夜视频| 亚洲理论在线观看| 欧美激情一区二区三区不卡| 日韩免费福利电影在线观看| 色呦呦国产精品| 99久久国产综合精品色伊| 国产一区二区精品久久| 亚洲18色成人| 樱花草国产18久久久久| 中文字幕一区av| 国产日韩欧美精品电影三级在线| 91精品在线免费| 在线观看91精品国产麻豆| 欧美性淫爽ww久久久久无| 成人三级伦理片| 国产毛片精品一区| 久久精品久久99精品久久| 无吗不卡中文字幕| 亚洲一级二级在线| 亚洲一区中文日韩| 一区二区三区日韩欧美精品| 亚洲欧洲精品成人久久奇米网| 久久婷婷成人综合色| 久久人人超碰精品| 国产亚洲成年网址在线观看| 欧美成人综合网站| 欧美一区二区三区免费| 欧美一区二区三区播放老司机| 欧美在线影院一区二区| 欧美性猛交xxxx乱大交退制版 | 亚洲妇女屁股眼交7| 亚洲影视资源网| 午夜欧美大尺度福利影院在线看| 亚洲一二三区不卡| 午夜欧美视频在线观看 | 成人免费观看视频| 成人激情动漫在线观看| 成人性生交大合| 91麻豆文化传媒在线观看| 欧美午夜不卡在线观看免费| 欧美三级电影网站| 777亚洲妇女| 精品国产免费人成在线观看| 久久久久久久久99精品| 国产欧美日韩精品a在线观看| 国产精品黄色在线观看| 亚洲美女免费视频| 性做久久久久久免费观看欧美| 日韩影视精彩在线| 国产精品一区专区| 日本道精品一区二区三区| 欧美日韩美少妇| 久久综合狠狠综合久久综合88| 国产色婷婷亚洲99精品小说| ●精品国产综合乱码久久久久 | 亚洲人成在线播放网站岛国| 亚洲国产日韩精品| 久久机这里只有精品| 国产91色综合久久免费分享| 91蝌蚪国产九色| 欧美精品三级在线观看| www亚洲一区| 亚洲黄色在线视频| 久久99精品久久久久久国产越南 | 国产午夜精品一区二区三区四区| 亚洲三级电影网站| 麻豆传媒一区二区三区| av资源网一区| 欧美一区二区三区白人| 自拍视频在线观看一区二区| 日韩av一区二| 91原创在线视频| 精品久久久久香蕉网| 亚洲精品久久7777| 国产成人三级在线观看| 337p亚洲精品色噜噜狠狠| 国产精品美女久久久久av爽李琼 | 中文字幕在线不卡一区| 天天爽夜夜爽夜夜爽精品视频 | 久久99久久精品欧美| 欧美伦理视频网站| 国产精品看片你懂得| 麻豆成人av在线| 欧美日韩精品三区| 亚洲欧美在线另类| 国产精品影视在线观看| 欧美一级生活片| 亚洲一区二区三区影院| 99麻豆久久久国产精品免费| 欧美大片在线观看| 日韩经典一区二区| 日韩情涩欧美日韩视频| 亚洲精品老司机| 99久久精品情趣| 国产农村妇女毛片精品久久麻豆| 毛片不卡一区二区| 欧美喷水一区二区| 亚洲一区av在线| 欧美性猛交一区二区三区精品| **欧美大码日韩| 波多野结衣中文字幕一区| 国产欧美日韩另类一区| 韩国女主播成人在线| 精品乱码亚洲一区二区不卡| 日本不卡一二三| 欧美理论片在线| 亚洲综合色丁香婷婷六月图片| 91美女在线观看| 亚洲欧美日韩人成在线播放| av一区二区三区| 亚洲欧洲性图库| 91美女蜜桃在线| 一二三四社区欧美黄| 在线观看91精品国产入口| 亚洲综合激情网| 欧美顶级少妇做爰| 免费成人在线视频观看|