今天繼續來Draw繪制的osg子產品的學習,昨天我們學習的是StateBin渲染狀态樹節點類,今天我們來繼續學習下一個Draw的基礎類DrawableEntity渲染對象實體類。這個類和Drawable和繪制對象關系是并列的,DrawableEntity同樣有自己的DrawEntityActor。但是要注意的是,DrawableEntity和Drawable的功能是完全不同的,Drawable是繪制對象,包含geometry,transform,stateBin等幾何屬性空間屬性和狀态樹屬性;DrawableEntity則是管理render渲染實體的,和将要繪制的對象有着天壤之别。我們今天研究的是渲染管理子產品,先理清概念。
接下來老辦法,鲫魚繼續帶大家看看DrawableEntity的構造函數,看看DrawableEntity的私有屬性有哪些。先貼出DrawableEntity構造函數的代碼,由于采用的是require(module)方式引入依賴子產品,是以鲫魚将DrawableEntity依賴的類也一起截出來,但在本文不加讨論,以後會逐一介紹。
1 /*
2 渲染實體的可繪制對象
3 */
4 let Drawable = require(\'./Drawable\');
5 let StateBin = require(\'./StateBin\');
6
7 let DrawableEntity = function (actor) {
8 Drawable.call(this, actor);
9
10 this._renderEntity = undefined;//關聯的渲染實體
11 this._material = undefined;//原本的顔色狀态
12 };
我們看到,DrawableEntity依賴Drawable可繪制對象類,依賴StateBin狀态樹節點類。前文已經讨論過這兩個類,這裡不再叙述。我們還是來看DrawableEntity的屬性,this._renderEntity渲染實體屬性;this._material初始顔色屬性。我們接下來繼續看看DrawableEntity的成員函數。
1 reset: function () {
2 Drawable.prototype.reset.call(this);
3
4 this._renderEntity = undefined;
5 //this._radius = 0;
6 },
重置函數,重構原型對象中的reset函數,将私有成員this._renderEntity置空。
1 setRenderEntity: function (entity) {
2 this._renderEntity = entity;
3 },
設定渲染對象,設定私有成員this._renderEntity渲染實體。
1 getRenderEntity: function () {
2 return this._renderEntity;
3 },
擷取渲染對象。
1 setMaterial: function (s) {
2 this._material = s;
3 },
設定材質。
1 getMaterial: function () {
2 return this._material;
3 },
擷取材質屬性。
1 valid: function () {
2 // if(this._frameNumber === Drawable.FrameNumber){//已經繪制過,不再處理
3 // return false;
4 // }
5 //是否後面的不需再判斷了
6
7 if (!this._renderEntity.isShown()) {//隐藏的直接跳過
8 return false;
9 }
10
11 if (this._drawActor.getBaseCamera().isBoundingBoxCulled(this.getBoundingBox())) {
12 return false;
13 }
14
15 return true;
16 },
這個就類似Drawable了,valid成員函數用來判斷render渲染對象是否需要被繪制,這裡排除了2種不需要繪制的情況,第一種是标記為隐藏的渲染對象;第二種被剔除的則是包圍盒不在相機可視棱台範圍内的可渲染對象,簡單來說就是不在目前視口範圍内的渲染對象。剩下的都是符合渲染條件的renderEntity,通過valid校驗。我們繼續看下一個函數。
1 isTransparent: function () {
2 let result = false;
3 let hasmaterial = false;
4 //this._stateBin不能變
5 this._statebin.removeChildren();
6 this._curStatebin = this._statebin;
7 if (this._renderEntity !== undefined) {//有關聯的渲染實體,渲染實體的狀态優先級最高
8 let statesets = this._renderEntity.getStateSets();
9 let size = statesets.size;
10 if (size !== 0) {
11 statesets.forEach((stateset) => {
12 if (stateset) {
13 let mat = stateset.getMaterialAttribute();//一般不存在多個Material的情況,邏輯上避免,如果存在使用最後一個
14 if (mat) {//如果有Material,目前this._material就不再考慮
15 hasmaterial = true;
16 result = mat.isTransparent();
17 }
18 this._curStatebin = this._curStatebin.addStateSetChild(stateset);
19 }
20 });
21 }
22 }
23
24 //目前材質狀态
25 if (this._material) {
26 if (!hasmaterial) {
27 this._curStatebin = this._curStatebin.addStateSetChild(this._material);
28 let mat = this._material.getMaterialAttribute();
29 if (mat) {
30 result = mat.isTransparent();
31 }
32 }
33 }
34
35 return result;
36 },
該函數是用來判斷目前渲染對象是否為透明的材質對象。由于webgl和opengl中對透明材質的處理很特殊,要按照深度排序由遠到近依次繪制而且我們都是在非透明材質繪制完成後才繪制透明材質,否則材質混合會出問題,是以我們在管理renderEntity時一定要判斷渲染對象是否透明。這當中還要對目前渲染對象的StateSet狀态優先級進行排序,其中判斷材質是否透明的函數是Material的成員函數,這個api是this._material.getMaterialAttribute().isTransparent()。我們再來看最後一個函數。
1 draw: function (glstate, preDrawable) {//重載
2 //先接受狀态,再渲染幾何
3 let curStatebin = this._curStatebin;
4 let curStateset = curStatebin.getStateSet();//目前的狀态
5 let curStatebinParent = curStatebin.getParent();//父節點
6 //let curStatesetParent = undefined;//父節點的狀态
7 //if(curStatebinParent){//自從加了總根節點後,這個情況不存在了吧!
8 //let curStatesetParent = curStatebinParent.getStateSet();//父節點的狀态
9 //}
10
11 if (preDrawable !== undefined) {
12 let preStatebin = preDrawable.getCurrentStateBin();
13 let preStateset = preStatebin.getStateSet();
14 let preStatebinParent = preStatebin.getParent();
15 //let preStatesetParent = undefined;
16 //if(preStatebinParent){//自從加了總根節點後,這個情況不存在了吧!
17 //let preStatesetParent = preStatebinParent.getStateSet();//父節點的狀态
18 //}
19
20 //RenderEntity下的狀态随時會變,在isTransparent中會實時更新StateBin
21 //是以每次StateBin的結果可能都是臨時建立的沒有可比性,還是比較stateset靠譜點
22 if (preStatebinParent !== curStatebinParent) {//A
23 StateBin.moveStateBin(glstate, preStatebinParent, curStatebinParent);
24 glstate.applyStateSet(curStateset);
25 } else if (preStateset !== curStateset) {//B
26 glstate.applyStateSet(curStateset);
27 } else {
28 // we call apply but actually we dont need
29 // except if the stateSetStack changed.
30 // for example if insert/remove StateSet has been used
31 // if (glstate._stateSetStackChanged(idLastDraw, lastStateSetStackSize )) {
32 // glstate.applyStateSet(curStateset);
33 // }
34 }
35 }
36 else {//如果preLeaf為空,第一個繪制的幾何,狀态周遊到根節點全部push到GLState中
37 StateBin.moveStateBin(glstate, undefined, curStatebinParent);
38 glstate.applyStateSet(curStateset);
39 }
40 //state._setStateSetsDrawID( ++idLastDraw );
41 //lastStateSetStackSize = state.getStateSetStackSize();
42
43 //this.drawGeometry(glstate);
44 let camera = this._drawActor.getBaseCamera();
45 glstate.applyModelMatrix(this._transform, camera.getModelViewMatrix(), camera.getProjectionMatrix());
46 this._geometry.draw(glstate);
47 //return true;
48
49 //_stateBin新添加的兒子要删除,不影響下一幀的繪制
50 //this._statebin.removeChildren();
51 //this._curStatebin = undefined;//千萬不要重置。。每幀繪制時的Drawable會取前一個的狀态
52 //this._frameNumber = Drawable.FrameNumber;//已經繪制過,不再繪制
53 },
繪制函數draw。這個繪制draw就是用glstate來繪制目前渲染對象。
好了,以上就是DrawableEntity渲染對象的管理操作類的所有成員屬性和成員函數的介紹。我們又了解了osg的DrawableEntity的構造,再接再厲,下一篇鲫魚帶領大家繼續學習DrawEntityActor類。今天先到這裡,下周再見。本文系原創,如需引用,請注明出處:https://www.cnblogs.com/ccentry/p/10227152.html