QT里的qopenglwidget提供了對多線程的知識,根據文檔所說,想要在另一個線程中執行渲染操作,需要將該widget的context通過movetothread到該線程,手動makecurrent和donecurrent,然后執行渲染操作。總而言之QT中想讓opengl在另一個線程渲染,需要的東西只有一個:屬於該線程的context。知道這個,就可以以很多方法實現該功能了。
方法1
qt的example里面有一個threadedopengl例子,里面就是通過aboutToCompose和frameSwapped兩個信號來控制渲染的,重寫paintevent為空函數。當aboutTocompose時,停止渲染,可以以獲取該線程互斥量的形式完成,交換完成后,釋放互斥量,並發送信號,指示渲染線程開始渲染。渲染線程首先請求context,通過發送信號給gui線程,並用條件變量等待,gui將context所有權交給渲染線程,喚醒條件變量,渲染線程執行渲染操作,再重新轉移context所有權,並用qmetaobject向其發送一個update操作。update操作又會觸發abouttocompose,這樣就不停渲染了。
方法2
雖然上面的方法很好,但是在同一級父窗口中有多個widget的時候就會出問題,原因是update會導致兩個widget的abouttocompose,QT在發送這個信號之前會makecurrent,但如果有一個widget正在渲染,context的所有權並不屬於gui時就會報錯。所以需要用另一種方法,這里用渲染到紋理的方法解決了。QT中有QOpenGLContext和QOffscreenSurface,這兩個的組合可以將渲染結果渲染到紋理上,這樣gui顯示該紋理,就能達到同樣的效果。使用方法查看QT文檔,這里就不說明了。
