WebGL中使用window.requestAnimationFrame建立主迴圈
今天總結記錄一下WebGL中主迴圈的建立和作用。我先說明什麼是主迴圈,其實單純的webgl不存在主迴圈這個概念,這個概念是由渲染引擎引入的,主迴圈就是利用一個死迴圈或無截止條件的遞迴達到定時重新整理canvas場景的函式,也就是人們常說的canvas重新整理率(fps)。在討論主迴圈的用處之前,我們先明確一下一個簡單的完整webgl的渲染過程是怎樣的,請看下圖。
好了我們通過上圖看到一個mesh完整的渲染流程,大致再講解一下,首先如果是持續繪製模型的話,就不要gl.clear(gl.color_buffer_bit),否則會將之前繪製進canvas場景的模型擦除,這也是我們所不希望看到的。還是老樣子,向vertex-shader中傳入attribute和uniform引數,然後呼叫gl.drawElement進行一次繪製。這個流程已經很清楚了,如果還有問題,請看之前的部落格,連結地址https://www.cnblogs.com/ccentry/p/9864847.html。到這裡我們把一次繪製渲染的流程重新理了一遍,接下來我們再把場景樹的流程理清楚,請看下圖。
我們可以看到,每次我們遍歷到一個樹節點,我們就會檢查這個節點使用的shader是哪一對vertex-shader和fragment-shader,然後呼叫之前圖示的渲染流程,繫結shader;接下來檢查該節點相對於其父節點的空間變換矩陣matrixTransform,經過運算傳給shader的uniform;隨後檢查mesh,傳給shader的attribute;最後檢查材質和UV這類引數,傳給shader。最後所有傳值都結束以後,drawElement將該節點模型繪製到canvas場景中去。直到遍歷玩整棵樹,將所有模型都繪製進canvas場景,才是完整的一幀渲染流程。
以上是複習之前2篇文章討論的內容,也理了一遍整個渲染流程。接下來我們進入今天要討論的主題,即webGL製作的渲染引擎的主迴圈。文章開頭說過了,主迴圈就是一個無限迴圈的函式,在這個函式中我們要做的就是重複剛才我們渲染整個scene場景的過程。具體的迴圈間隔可以人為的去設定,例如通過setTimeout來設施迴圈時間間隔,即設定每次重新渲染的時間間隔。這麼做有什麼好處嗎,當然有。我之前做的demo就沒有主迴圈的概念,純粹是滑鼠事件觸發的重新繪製,即clear(擦除)->traverseNodeTree(遍歷樹)->buffer(傳參)->draw(繪製)->traverseNodeTree->buffer->draw ......->traverseEnd(遍歷結束)。每次這個過程都是計算滑鼠的clientXY來重繪,由mouseUp事件觸發。其實就是一個靜態模仿動態的過程。這麼做當然也能做出動態互動的效果,沒有問題,但主迴圈給了我們一個更好的互動事件管理模式,即每一幀繪製時間間隔到了的時候,就會檢查互動後的模型引數,然後進行重繪。同樣也是計算clientXY,就不需要一次次去監聽mouseUp事件了。這是我理解的主迴圈在事件互動裡的作用。當然更復雜的互動管理,模型預篩選(超過視稜臺的discard或選擇不繪製),都可以在主迴圈裡操作。主迴圈還有製作animation動畫的用處,這裡不是討論的重點,所以就暫時不展開講。
說了半天,怎麼構造WebGL主迴圈還沒說,我們就以Threejs的render渲染流程為依託,來看看render在主迴圈裡是怎麼玩的,以及今天要說的window.requestAnimationFrame是怎麼用的,請看下面程式碼。
/** * 進行渲染 * */ function rend(){ renderer.render(scene, camera); } //動效 function animate(){ requestAnimationFrame( animate ); controls.update(); rend(); } animate();
我們看到這就是一個簡單的遞迴,目的就是利用html5的requestAnimationFrame進行定時重繪。從而達到上面說的滑鼠互動效果。
今天僅僅是初步瞭解了一下主迴圈是什麼,幹什麼用的,其應用場景討論也侷限在渲染和滑鼠互動上,本人水平有限,希望各位大佬指教,在此貽笑大方。謝謝@山椒@上校已死兩位大佬的解釋指點,今天就寫這些見解,再次感謝。
引用本文請註明出處https://www.cnblogs.com/ccentry/p/9938725.html