从今天开始,我们开始正式的学习osg框架,今天我们学习的是osg的渲染模块,我们来看一下代码结构。

所有DrawXXX的js模块都是渲染的模块,我们逐一来简单介绍一下,第一个Drawable.js,这个模块是描述可绘制对象的类,也是我们今天要讨论的类。在osg框架中,渲染管道在准备时期首先要统计管理可绘制对象,我们来看看Drawable模块到底做了什么操作,进行了哪些管理。先贴出代码。

/*
可绘制对象
*/
let StateBin = require('./StateBin');
let BoundingBox = require('../util/BoundingBox');
let BoundingSphere = require('../util/BoundingSphere');
let Vec3 = require('../util/Vec3'); let Drawable = function (actor) {
this._drawActor = actor;//关联的DrawActor this._geometry = undefined;//渲染的几何Geometry
this._transform = undefined;//世界变换 FloatArray(16) this._statebin = undefined;//状态结点,原始的状态,没有额外功能时的状态
this._curStatebin = undefined;//如果状态会动态变化,这里存储每一帧绘制时的状态结点 this._depth = 0.0;//场景深度值,透明需要按深度排序绘制 this._boundingBox = undefined;//包围盒
this._boundingSphere = undefined;//包围球
};
Drawable.prototype = {
setGeometry: function (g, transform) {
this._geometry = g;
this._transform = transform;
},
getGeometry: function () {
return this._geometry;
},
getTransform: function () {
return this._transform;
},
setStateBin: function (sb) {
this._statebin = sb;
},
getStateBin: function () {
return this._statebin;
},
getCurrentStateBin: function () {
return this._curStatebin;
},
// setDepth: function (d) {
// this._depth = d;
// },
getDepth: function () {
return this._depth;
}, reset: function () {
this._geometry = undefined;
this._transform = undefined; this._statebin = undefined;
this._curStatebin = undefined;
this._depth = 0.0; this._boundingBox = undefined;
this._boundingSphere = undefined;
},
valid: function () {
if (this._drawActor.getBaseCamera().isBoundingBoxCulled(this.getBoundingBox())) {
return false;
}
return true;
},
isTransparent: function () {
return false;
},
//计算深度值
computeDepth: function () {
//根据包围盒和相机变换矩阵,确认中心点的Z值
let mvmatrix = this._drawActor.getBaseCamera().getModelViewMatrix(); let temp = Vec3.MemoryPool.alloc();
this._depth = this.distanceZ(this.getBoundingBox().getCenter(temp), mvmatrix);
Vec3.MemoryPool.free(temp);
//drawable.setDepth(depth);
},
//相机的矩阵要取反
distanceZ: function (coord, matrix) {
return -(coord[0] * matrix[2] + coord[1] * matrix[6] + coord[2] * matrix[10] + matrix[14]);
},
getBoundingBox: function () {
if(this._boundingBox === undefined){
this._boundingBox = new BoundingBox(); this._boundingBox.copy(this._geometry.getBoundingBox(true));
if(this._transform){
this._boundingBox.transformMat4(this._transform);
}
}
return this._boundingBox;
},
getBoundingSphere: function () {
if(this._boundingSphere === undefined) {
this._boundingSphere = new BoundingSphere();
let bb = this.getBoundingBox();
this._boundingSphere.expandByBoundingBox(bb);
}
return this._boundingSphere;
},
getRadius: function () {
return this.getBoundingSphere().getRadius();
},
// There are 3 cases when there is a prev / current render leaf
// pSG: previousStateGraph
// cSG: currentStateGraph
// pRL: previousRenderLeaf
// cRL: currentRenderLeaf
//
// A B C
// +-----+ +-----+ +-----+ +-----+
// | pSG | | cSG | +--+ SG +--+ | SG |
// +--+--+ +--+--+ | +-----+ | +--+--+
// | | | | |
// +--v--+ +--v--+ +--v--+ +--v--+ +--v--+
// | pSG | | cSG | | pSG | | cSG | +--+ SG +--+
// +--+--+ +--+--+ +--+--+ +--+--+ | +-----+ |
// | | | | | |
// +--v--+ +--v--+ +--v--+ +--v--+ +--v--+ +--v--+
// | pRL | | cRL | | pRL | | cRL | | pRL | | cRL |
// +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
//
//
// Case A
// no common parent StateGraphNode we need to
// popStateSet until we find the common parent and then
// pushStateSet from the common parent to the current RenderLeaf
//
// Case B
// common parent StateGraphNode so we apply the current stateSet
//
// Case C
// the StateGraphNode is common to the previous RenderLeaf so we dont need
// to do anything except if we used an insertStateSet
draw: function (glstate, preDrawable) {
//先接受状态,再渲染几何
let curStateGraph = this._statebin;
let curStateGraphStateSet = curStateGraph.getStateSet();
let curStateGraphParent = curStateGraph.getParent(); let preStateGraph;
let preStateGraphParent;
if(preDrawable !== undefined){
preStateGraph = preDrawable._statebin;
preStateGraphParent = preStateGraph.getParent(); if(preStateGraphParent !== curStateGraphParent){//A
StateBin.moveStateBin(glstate, preStateGraphParent, curStateGraphParent);
glstate.applyStateSet(curStateGraphStateSet);
}else if(preStateGraph !== curStateGraph){//B
glstate.applyStateSet(curStateGraphStateSet);
}else{
// in osg we call apply but actually we dont need
// except if the stateSetStack changed.
// for example if insert/remove StateSet has been used
// if (glstate._stateSetStackChanged(idLastDraw, lastStateSetStackSize )) {
// glstate.applyStateSet(curStateGraphStateSet);
// }
}
}
else{//如果preLeaf为空,第一个绘制的几何,状态遍历到根节点全部push到GLState中
StateBin.moveStateBin(glstate, undefined, curStateGraphParent);
glstate.applyStateSet(curStateGraphStateSet);
} let camera = this._drawActor.getBaseCamera();
glstate.applyModelMatrix(this._transform, camera.getModelViewMatrix(), camera.getProjectionMatrix());
this._geometry.draw(glstate);
return true;
},
};
module.exports = Drawable; // set: function (stateGraph, geometry, , depth) {
// this._statebin = stateGraph;
// this._geometry = geometry;
//
// this._depth = depth;
// },
// drawGeometry: function (glstate) {
// //let program = glstate.getLastProgramApplied();
// //let programID = program.getID();
// //let programCaches = glstate.getProgramCaches();
// //let obj = programCaches[programID];
// // if(!obj){//程序不存在,创建一个新的
// // obj = new CacheUniformApply(glstate, program);
// // programCaches[programID] = obj;
// // }
//
// //从相机获取modelview和projection
// //着色器暂时不需要透视矩阵
// //let modelview = this._camera.get
//
//
//
// //glstate.applyModelViewMatrix(this._modelview);
// //glstate.applyProjectionMatrix(this._projection);
// glstate.applyTransformMatrix(this._transform);
// //this._modelview = this._camera.getModelViewMatrix();
// //Mat4.mul(this._modelview, this._modelview, this._transform);
// //this._projection = this._camera.getProjectionMatrix();
// glstate.applyModelMatrix(this._transform, this._camera.getModelViewMatrix(), this._camera.getProjectionMatrix());
//
//
// //let gluniforms = program.getGLUniformsCache();
// //let modelviewloc = gluniforms[glstate._modelViewMatrixUniform.getName()];
// //let viewloc = gluniforms[glstate._viewMatrixUniform.getName()];
//
// //obj.apply(glstate, this._modelview, this._modelworld, this._view, this._projection, this._normal);
// this._geometry.draw(glstate);
// },

我们先来看看Drawable的构造函数,截取构造函数代码

let Drawable = function (actor) {
this._drawActor = actor;//关联的DrawActor this._geometry = undefined;//渲染的几何Geometry
this._transform = undefined;//世界变换 FloatArray(16) this._statebin = undefined;//状态结点,原始的状态,没有额外功能时的状态
this._curStatebin = undefined;//如果状态会动态变化,这里存储每一帧绘制时的状态结点 this._depth = 0.0;//场景深度值,透明需要按深度排序绘制 this._boundingBox = undefined;//包围盒
this._boundingSphere = undefined;//包围球
};

首先我们看到第一个私有属性是DrawActor,我们看看DrawActor是个什么模块,先贴出DrawActor类代码。

/*
绘制对象角色 每个DrawActor管理自己的渲染数据,自己的状态树,自己的相机树
如果该功能销毁直接销毁对应的DrawActor资源
但是他引用的状态,相机并不是他管理
不想把各个DrawActor搅和在一起,逻辑混乱 绘制分几种情况,全自动,全手动,半自动
全自动-所有的绘制流程从一开始数据构造好后就不会再变更,只需在初始化时确认好 后续直接渲染即可
半自动-部分绘制流程是固定的,部分绘制流程是动态的,比如构件场景下,需要点选高亮等功能变化
全手动-所有的绘制流程都是动态的,每一帧都需要重新构造每个drawable,部分功能数据
*/
let Drawable = require('./Drawable');
let StateBin = require('./StateBin');
let NodeVisitor = require('../util/NodeVisitor');
let CullStack = require('./CullStack');
let Mat4 = require('../util/Mat4');
let Group = require('../core/Group');
let Geode = require('../core/Geode');
let MatrixTrasform = require('../core/MatrixTransform');
let SceneRoot = require('../scene/SceneRoot');
let Geometry = require('../core/Geometry'); let DrawActor = function (renderer) {
NodeVisitor.call(this, NodeVisitor.TRAVERSE_CHILDREN);
CullStack.call(this); //为正确渲染准备的数据
this._renderer = renderer;//所属的渲染器,固有资产,不会变更
this._baseCamera = this._renderer.getMainCamera();//相机,默认为主相机
this._baseState = new StateBin();//状态
this._sceneRoot = undefined;//所属的场景根节点 //渲染的对象
this._drawables = []; //
this._drawIndex = 0;//当前绘制的索引数,需要固定帧率渲染的地方使用 //
this._currentStateBin = undefined;//当前处理的状态树结点,临时数据 //
//this._fixed = false;//是否启用固定帧率
this._valid = true;//直接屏蔽渲染的标记
}; DrawActor.prototype = Object.create(NodeVisitor.prototype);
Object.assign(DrawActor.prototype, CullStack.prototype);
DrawActor.prototype.constructor = DrawActor;
Object.assign(DrawActor.prototype, {
setBaseCamera: function (camera) {//设置当前相机,可以自由设置自己独特的相机
this._baseCamera = camera;
},
getBaseCamera: function () {
return this._baseCamera;
},
getBaseStateBin: function () {
return this._baseState;
},
getBaseStateSet: function () {
return this._baseState.getStateSet();
},
//复原场景根节点的状态
revertBaseState: function () {
if (this._sceneRoot) {
this._baseState.setStateSet(this._sceneRoot.getStateSet());
}
},
//与场景的唯一联系,一定要先定义好场景的几何和状态再调用setSceneRoot
setSceneRoot: function (root) {
this._sceneRoot = root;
//一定要先定义好场景根节点的状态,否则会出错!!!
//this._baseState.setStateSet(root.getStateSet());
},
createDrawable: function () {//base override
return new Drawable(this);//创建对应类型的Drawable
},
addDrawable: function (drawable) {
this._drawables.push(drawable);
},
getDrawables: function () {
return this._drawables;
}, valid: function (valid) {
if (valid !== undefined) {
this._valid = valid;
}
return this._valid;
},
//遍历
apply: function (node) {
this[node.typeID](node);
},
//重载,压入一个状态
pushStateSet: function (stateset) {
if (stateset) {
//添加StateGraph子节点,更新当前活动的StateGraph为新的状态
this._currentStateBin = this._currentStateBin.addStateSetChild(stateset);
}
},
//重载,弹出一个状态
popStateSet: function (stateset) {
if (stateset) {
this._currentStateBin = this._currentStateBin.getParent();
}
},
//重载
pushDrawable: function (geometry) {
let drawable = this.createDrawable();
drawable.setStateBin(this._currentStateBin);
drawable.setGeometry(geometry, this.getCurrentTransformMatrix());
this.addDrawable(drawable);
}, //根重载,绘制当前Actor下的drawables,绘制不需要固定帧率,永远在第一帧里绘制完毕
draw: function (glstate, preCamera) {
if (!this._valid) {//不再绘制
return preCamera;
} this.drawCamera(preCamera); //循环遍历一遍drawables,绘制实体
let preDrawable = undefined;
let l = this._drawables.length;
for (let i = this._drawIndex; i < l; i++) {
let drawable = this._drawables[i];
if (drawable.valid()) {
drawable.draw(glstate, preDrawable);//成功绘制的
preDrawable = drawable;
}
this._drawIndex++;
}
return this._baseCamera;
},
//每个新帧绘制之前的重置工作
drawReset: function () {
this._baseCamera.setClearFlag(false);
this._drawIndex = 0;
},
//当前Actor的对象是否全部绘制完毕
drawFinished: function () {
return this._drawables.length === this._drawIndex;
},
//绘制相机状态(视口,清空)
drawCamera: function (preCamera) {
if (preCamera === this._baseCamera) {//重复的不再处理
return;
} //视口何时都需要设置
let glstate = this._renderer.getGLState();
glstate.applyAttribute(this._baseCamera.getViewport()); //以下是每个相机只需要处理一次的事情
if (!this._baseCamera.getClearFlag()) {
//更新视锥体,确保剔除正确,每帧相机的投影矩阵和视图矩阵可能都会变化
this._baseCamera.updateCullFrustum(); //清空颜色和深度,但如果是主相机不再需要,在最开始就已经清空
let clearmask = this._baseCamera.getClearMask();
if (clearmask !== 0x0) {
let gl = glstate.getWebGLContext();
if (clearmask & gl.COLOR_BUFFER_BIT) {
let color = this._baseCamera.getClearColor();//清空颜色
gl.clearColor(color[0], color[1], color[2], color[3]);
}
if (clearmask & gl.DEPTH_BUFFER_BIT) {
let depth = this._baseCamera.getClearDepth();//清空深度
gl.depthMask(true);
gl.clearDepth(depth);
}
gl.clear(clearmask);
}
this._baseCamera.setClearFlag(true);
}
}, //根重载,线段求交,返回相交的drawable对象
linesegmentIntersect: function (start, end, threshold) {
let LineSegmentIntersector = require('../util/LineSegmentIntersector');
let intersector = new LineSegmentIntersector();
intersector.initialize(start, end, threshold);
let length = this._drawables.length;
for (let i = 0; i < length; i++) {
let drawable = this._drawables[i];
if (drawable.valid()) {//没有隐藏,没有被剔除的drawable进行相交运算
intersector.intersect(drawable);
}
}
//线段求交结果需要根据ratio排序
return intersector.getIntersections();
},
}); DrawActor.prototype[SceneRoot.typeID] = function (root) {
this._baseState.removeChildren();
this._baseState.setStateSet(root.getStateSet()); this._currentStateBin = this._baseState;
this.pushTransformMatrix(root.getRootTransform());//变换矩阵中先推入一个单位矩阵作为根节点,非常重要
this.traverse(root);
this.popTransformMatrix();
this._currentStateBin = undefined;
};
DrawActor.prototype[MatrixTrasform.typeID] = function (node) {
//模型矩阵变换
let lastModelMatrix = this.getCurrentTransformMatrix();
let mmatrix = undefined;
if (lastModelMatrix) {
mmatrix = Mat4.clone(lastModelMatrix);
} else {
mmatrix = Mat4.new();
}
node.computeLocalToWorldMatrix(mmatrix);
this.pushTransformMatrix(mmatrix); //状态
let stateset = node.getStateSet();
this.pushStateSet(stateset);
this.traverse(node);
this.popStateSet(stateset);
this.popTransformMatrix();
};
DrawActor.prototype[Geode.typeID] = function (geode) {
this[Group.typeID](geode);
};
DrawActor.prototype[Group.typeID] = function (group) {
let stateset = group.getStateSet();
this.pushStateSet(stateset);
this.traverse(group);
this.popStateSet(stateset);
};
DrawActor.prototype[Geometry.typeID] = function (geometry) {//Geometry已经是叶子,不需要继续递归了
let stateset = geometry.getStateSet();
this.pushStateSet(stateset);
this.pushDrawable(geometry);
this.popStateSet(stateset);
};
module.exports = DrawActor;
// reset: function () {
// this._drawables.length = 0;//置空
// this._sceneRoot = undefined;
// },
// polytopeIntersect: function () {
//
// },
// sphereIntersect: function () {
//
// },

  我们可以看到,DrawActor是将要被绘制的对象,分成全自动(初始化模型数据就构造Drawable,准备渲染)、半自动(事件触发后构造Drawable,等待渲染)、全手动(用户自己构造Drawable,用户自己将Drawable排入渲染队列)。我们看到,DrawActor的构造函数包含的私有属性有this._renderer渲染器、this._baseCamera待渲染模块所属相机、this._baseState状态(对应shader里的uniform参数)、this._sceneRoot所属场景根节点、this._drawables包含的渲染对象、this._drawIndex当前绘制的索引数(代表本次绘制是第几次绘制,如果一此不能全部绘制完,就分多次绘制,例如模型增长)、this._currentStateBin当前处理的状态树节点、this._valid屏蔽渲染的标记(true:加入渲染队列,false:不加入渲染队列)。

  我们再来看看DrawActor的成员函数都做了什么,我们依次来看。

1.setBaseCamera设置参考相机,这就是设置当前绘制对象的观察相机。2.getBaseCamera获取参考相机。3.getbaseStateBin获取状态信息,包括当前渲染对象绑定的shader,uniform参数以及frameBuffer材质。4.getBaseStateSet同样是获取当前渲染对象的状态信息,shader,uniform,材质信息,depth深度缓冲等。5.revertBaseState恢复场景根节点状态,包括shader,uniform参数,材质信息,depth深度缓存。6.setSceneRoot设置场景根节点。7.createDrawable创建渲染对象。8.addDrawable追加渲染对象进入绘制对象数组。9.getDrawable返回渲染对象数组。10.valid标记当前渲染对象是否被屏蔽。11.apply取出每个渲染节点。12.pushStateSet向stateBin中加入stateSet,这里说明一点,stateSet是stateBin的属性。13.popStateSet从stateBin中取出stateSet属性参数。14.pushDrawable创建渲染对象drawable然后加入drawActor的drawable渲染对象数组。15.draw这才是drawActor的核心功能函数,同学们,鲫鱼为大家隆重介绍绘制函数,或者叫渲染函数,这就是将所有的drawable渲染对象进行遍历渲染的功能函数。16.drawReset每一帧绘制之前的整理重置。17.drawFinished判断当前drawActor绘制对象是否全部将drawable数组中的渲染对象绘制完毕。18.drawCamera绘制相机状态(视口,深度缓冲),如果没有渲染对象私有独立的相机,就操作主相机。19.linesegmentIntersection射线碰撞,重载父类方法。

  依次看一下上面的函数,我们大致了解了DrawActor类处理的是渲染流程管理的工作。我们接下来继续看Drawable类的其他属性。我们再贴出一次drawable的构造函数。

let Drawable = function (actor) {
this._drawActor = actor;//关联的DrawActor this._geometry = undefined;//渲染的几何Geometry
this._transform = undefined;//世界变换 FloatArray(16) this._statebin = undefined;//状态结点,原始的状态,没有额外功能时的状态
this._curStatebin = undefined;//如果状态会动态变化,这里存储每一帧绘制时的状态结点 this._depth = 0.0;//场景深度值,透明需要按深度排序绘制 this._boundingBox = undefined;//包围盒
this._boundingSphere = undefined;//包围球
};

我们已经看过了this._drawActor,也知道了drawActor是管理渲染的类。接下来我们看this._geometry渲染的几何体成员对象。this._transform空间变换矩阵。this._statebin状态节点,用来添加stateSet状态参数对象。this._currStatebin,保存每一帧的临时状态stateSet。this._depth场景深度值,作用于主相机或渲染对象私有相机(如果有私有相机的话)。this._boundingBox包围盒。this._boundingSphere包围球。这些就是Drawable类的成员。我们马上来看一下Drawable的成员函数。
  Drawable成员函数。贴出代码。

setGeometry: function (g, transform) {
this._geometry = g;
this._transform = transform;
},
getGeometry: function () {
return this._geometry;
},
getTransform: function () {
return this._transform;
},
setStateBin: function (sb) {
this._statebin = sb;
},
getStateBin: function () {
return this._statebin;
},
getCurrentStateBin: function () {
return this._curStatebin;
},
// setDepth: function (d) {
// this._depth = d;
// },
getDepth: function () {
return this._depth;
}, reset: function () {
this._geometry = undefined;
this._transform = undefined; this._statebin = undefined;
this._curStatebin = undefined;
this._depth = 0.0; this._boundingBox = undefined;
this._boundingSphere = undefined;
},
valid: function () {
if (this._drawActor.getBaseCamera().isBoundingBoxCulled(this.getBoundingBox())) {
return false;
}
return true;
},
isTransparent: function () {
return false;
},
//计算深度值
computeDepth: function () {
//根据包围盒和相机变换矩阵,确认中心点的Z值
let mvmatrix = this._drawActor.getBaseCamera().getModelViewMatrix(); let temp = Vec3.MemoryPool.alloc();
this._depth = this.distanceZ(this.getBoundingBox().getCenter(temp), mvmatrix);
Vec3.MemoryPool.free(temp);
//drawable.setDepth(depth);
},
//相机的矩阵要取反
distanceZ: function (coord, matrix) {
return -(coord[0] * matrix[2] + coord[1] * matrix[6] + coord[2] * matrix[10] + matrix[14]);
},
getBoundingBox: function () {
if(this._boundingBox === undefined){
this._boundingBox = new BoundingBox(); this._boundingBox.copy(this._geometry.getBoundingBox(true));
if(this._transform){
this._boundingBox.transformMat4(this._transform);
}
}
return this._boundingBox;
},
getBoundingSphere: function () {
if(this._boundingSphere === undefined) {
this._boundingSphere = new BoundingSphere();
let bb = this.getBoundingBox();
this._boundingSphere.expandByBoundingBox(bb);
}
return this._boundingSphere;
},
getRadius: function () {
return this.getBoundingSphere().getRadius();
},

都是设置和获取属性的函数,包括包围盒和包围球。接下来我们来看看最核心的部分,隆重介绍draw绘制函数,请看代码。

// There are 3 cases when there is a prev / current render leaf
// pSG: previousStateGraph
// cSG: currentStateGraph
// pRL: previousRenderLeaf
// cRL: currentRenderLeaf
//
// A B C
// +-----+ +-----+ +-----+ +-----+
// | pSG | | cSG | +--+ SG +--+ | SG |
// +--+--+ +--+--+ | +-----+ | +--+--+
// | | | | |
// +--v--+ +--v--+ +--v--+ +--v--+ +--v--+
// | pSG | | cSG | | pSG | | cSG | +--+ SG +--+
// +--+--+ +--+--+ +--+--+ +--+--+ | +-----+ |
// | | | | | |
// +--v--+ +--v--+ +--v--+ +--v--+ +--v--+ +--v--+
// | pRL | | cRL | | pRL | | cRL | | pRL | | cRL |
// +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
//
//
// Case A
// no common parent StateGraphNode we need to
// popStateSet until we find the common parent and then
// pushStateSet from the common parent to the current RenderLeaf
//
// Case B
// common parent StateGraphNode so we apply the current stateSet
//
// Case C
// the StateGraphNode is common to the previous RenderLeaf so we dont need
// to do anything except if we used an insertStateSet
draw: function (glstate, preDrawable) {
//先接受状态,再渲染几何
let curStateGraph = this._statebin;
let curStateGraphStateSet = curStateGraph.getStateSet();
let curStateGraphParent = curStateGraph.getParent(); let preStateGraph;
let preStateGraphParent;
if(preDrawable !== undefined){
preStateGraph = preDrawable._statebin;
preStateGraphParent = preStateGraph.getParent(); if(preStateGraphParent !== curStateGraphParent){//A
StateBin.moveStateBin(glstate, preStateGraphParent, curStateGraphParent);
glstate.applyStateSet(curStateGraphStateSet);
}else if(preStateGraph !== curStateGraph){//B
glstate.applyStateSet(curStateGraphStateSet);
}else{
// in osg we call apply but actually we dont need
// except if the stateSetStack changed.
// for example if insert/remove StateSet has been used
// if (glstate._stateSetStackChanged(idLastDraw, lastStateSetStackSize )) {
// glstate.applyStateSet(curStateGraphStateSet);
// }
}
}
else{//如果preLeaf为空,第一个绘制的几何,状态遍历到根节点全部push到GLState中
StateBin.moveStateBin(glstate, undefined, curStateGraphParent);
glstate.applyStateSet(curStateGraphStateSet);
} let camera = this._drawActor.getBaseCamera();
glstate.applyModelMatrix(this._transform, camera.getModelViewMatrix(), camera.getProjectionMatrix());
this._geometry.draw(glstate);
return true;
},

我将注释也贴了出来,我们可以看到,渲染绘制是分三种情况的,首先我们要了解一下StateGraph渲染属性这个来源于osg的概念。stateGraph是渲染的状态属性,包括本次渲染绑定的shader,uniform参数,frameBuffer材质属性,depth深度属性。好了,大致了解了StateGraph后我们再来了解一下RenderLeaf渲染叶这个同样来自osg的概念。RenderLeaf是渲染叶,需要注意的是渲染叶保存的是sceneTree的节点状态,而不是场景树的几何和transform信息。好了,了解了这两个概念我们来看看这三种情况。A.前一帧stateGraph和后一帧stateGraph没有同一个父节点;B.前后两帧stateGraph有同一个父节点;C.前后两帧renderLeaf有共同父节点。针对这三种情况,处理的方式不同,需要注意。鲫鱼也才开始逐步研究osg框架,理解不到位之处请各位方家海涵。
  好了,今天讲述的是osg的渲染模块中的一部分DrawActor和Drawable两个模块。下一篇会进一步讲述渲染模块。欢迎大家讨论,祝大家元旦快乐。本文系原创,如需引用,请注明出处:https://www.cnblogs.com/ccentry/p/10199157.html

 

WebGL——osg框架学习一的更多相关文章

  1. WebGL——osg框架学习三

    今天继续来Draw绘制的osg模块的学习,昨天我们学习的是StateBin渲染状态树节点类,今天我们来继续学习下一个Draw的基础类DrawableEntity渲染对象实体类.这个类和Drawable ...

  2. WebGL——osg框架学习四

    这篇我们接着来看一下DrawEntityActor类,我们来看看这个继承DrawActor的类到底做了什么事.我们之前学习了Drawable对应的DrawActor,那么我们类比的来看Drawable ...

  3. IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API

    IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习之保护API. 使用IdentityServer4 来实现使用客户端凭据保护ASP.N ...

  4. Hadoop学习笔记—18.Sqoop框架学习

    一.Sqoop基础:连接关系型数据库与Hadoop的桥梁 1.1 Sqoop的基本概念 Hadoop正成为企业用于大数据分析的最热门选择,但想将你的数据移植过去并不容易.Apache Sqoop正在加 ...

  5. Spring框架学习一

    Spring框架学习,转自http://blog.csdn.net/lishuangzhe7047/article/details/20740209 Spring框架学习(一) 1.什么是Spring ...

  6. EF框架学习手记

    转载: [ASP.NET MVC]: - EF框架学习手记 1.EF(Entity Framework)实体框架EF是ADO.NET中的一组支持开发面向数据的软件应用程序的技术,是微软的一个ORM框架 ...

  7. web框架学习列表

    转载自鲁塔弗的博客,原文网址:http://lutaf.com/148.htm web framework层出不穷,特别是ruby/python,各有10+个,php/java也是一大堆 根据我自己的 ...

  8. OSG动画学习

    OSG动画学习 转自:http://bbs.osgchina.org/forum.php?mod=viewthread&tid=3899&_dsign=2587a6a9 学习动画,看了 ...

  9. 2013 最新的 play web framework 版本 1.2.3 框架学习文档整理

    Play framework框架学习文档 Play framework框架学习文档 1 一.什么是Playframework 3 二.playframework框架的优点 4 三.Play Frame ...

随机推荐

  1. 我的Java之旅——答答租车系统的改进

    之前的答答租车系统虽然可以实现项目的要求,但是没有用Java面向对象,今天用面向对象的三大特性封装.继承和多态来改进原来的代码.题目和之前的代码参考上篇博客,这里不再述说. 改进后的代码: Vehic ...

  2. [咸恩静][Good Bye]

    歌词来源:http://music.163.com/#/song?id=35437298 作曲 : 安英民 [作曲 : 安英民] 作词 : 安英民/로코 [作词 : 安英民/lo-Ko] 나를 떠나버 ...

  3. 盒子模型之margin相关技巧!

    废话不多说,直接进入主题,margin相关技巧. 1.设置元素水平居中:margin:x auto; 2.margin负值让元素位移及边框合并. 外边距合并 指当两个垂直外边距相遇时,它们将形成一个外 ...

  4. ORA-28001: the password has expired (DBD ERROR: OCISessionBegin)解决办法

    1.问题描述: 打开oracle在线管理页面发现这个错误:界面如下 2问题原因 造成这个问题的主要原因是因为DBSNMP .SYSMAN用户密码已经过期. 3解决办法 可以使用sys以管理员的身份登录 ...

  5. Uva1395 POJ3522 Slim Span (最小生成树)

    Description Given an undirected weighted graph G, you should find one of spanning trees specified as ...

  6. 20165318 2017-2018-2 《Java程序设计》第五周学习总结

    20165318 2017-2018-2 <Java程序设计>第五周学习总结 学习总结 在使用IDEA时,由于我之前编写的代码都是使用GBK编码,使用IDEA打开时,由于IDEA默认为UT ...

  7. Fluent Terminal

    特性: PowerShell,CMD,WSL或自定义shell的终端 支持选项卡和多个窗口 主题和外观配置 导入/导出主题 导入iTerm主题 全屏模式 可编辑的键绑定 搜索功能 配置shell配置文 ...

  8. XML External Entity attack/XXE攻击

    XML External Entity attack/XXE攻击   1.相关背景介绍 可扩展标记语言(eXtensible Markup Language,XML)是一种标记语言,被设计用来传输和存 ...

  9. virtualbox+vagrant学习-2(command cli)-18-vagrant ssh-config命令

    SSH Config 格式: vagrant ssh-config [options] [name|id] 这将从SSH直接将SSH配置文件的有效配置输出到正在运行的vagrant 计算机(而不是使用 ...

  10. Docker实战(四)之Docker数据管理

    在生产环境中使用Docker的过程中,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及到容器的数据管理操作. 容器中管理数据主要有两种形式: 数据卷:容器内数据直接映射到本地主 ...