WebGL——osg框架学习一

  从今天开始,我们开始正式的学习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

 

原文地址:https://www.cnblogs.com/ccentry/p/10199157.html

时间: 2024-11-02 06:50:54

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

WebGL——osg框架学习四

这篇我们接着来看一下DrawEntityActor类,我们来看看这个继承DrawActor的类到底做了什么事.我们之前学习了Drawable对应的DrawActor,那么我们类比的来看DrawableEntity对应DrawEntityActor,这样就好理解一些.首先我们还是先来看DrawEntityActor的构造函数,看看他除了继承DrawActor以外还有哪些私有成员.下面是DrawEntityActor的构造函数. 1 /* 2 绘制对象角色 3 */ 4 let DrawActor

windows下scrapy框架学习笔记—&#39;scrapy&#39; 不是内部或外部命令

最近几天在深入的学习scrapy框架,但是装完各种需要的基础包之后却发现scrapy命令在别的路径下都用不了,我一开始是把python安装在F:\Python路径下的,安装了scrapy后它默认都会安装在这个路径下,scrapy在路径F:\Python\Scripts路径下,我的scrapy命令只能在此路径下用,因此创建什么工程也都只能在此文件下. 想了一下它的工作原理:它在F:\Python\Scripts路径下,就会在Scripts文件下存在一个scrapy批处理文件,那么在DOS下想要命令

Swagger框架学习分享

Swagger框架学习分享 转至元数据结尾 Created and last modified by 刘新宇 大约1分钟以前 转至元数据起始 一.背景介绍 1.1.项目简介 1.2.code repository 1.3.演示项目 二.开发准备 2.1.环境准备 2.2.项目搭建 2.2.1.jar仓库 2.2.2.相关依赖 2.2.3.编写配置文件 2.2.4.与swagger-ui集成 2.6.5.Controller配置 2.2.6.启动中间件 2.2.7.需求定制 三.学习感想 一.背景

某智能家居项目框架学习总结

这个月来第一篇博客,各种其他事情.. 之前负责过一个智能家居项目的二次开发,苏州一家公司做的,项目还是分了好几个系统,对业务流程的不同部分进行了划分,我是此项目的主要负责人,通过老师的指导,对这个项目也有了一些了解.此项目运用了一些框架,有些也是我第一次接触到的,下面将对项目用到的一些框架进行总结. 下面可能会出现几个有关智能家居的名词,介绍一下 1.机顶盒:每一个家庭都应该至少有一个机顶盒,控制电器开关都是由机顶盒向各电器的接收器发送命令 2.客户端:也就是用户的移动设备,手机.平板都可以,我

Spring框架学习之IOC(一)

Spring框架学习之IOC 先前粗浅地学过Spring框架,但当时忙于考试及后期实习未将其记录,于是趁着最近还有几天的空闲时间,将其稍微整理一下,以备后期查看. Spring相关知识 spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器.可单独使用,通常也与其他框架整合使用,例如SSH.SSM. IOC:控制反转 控制权由对象本身转向容器:由容器根据配置文件去创建实例并创建各个实例之间的依赖关系.等同于DI依赖注入 A

Android Afinal框架学习(一) FinalDb 数据库操作

框架地址:https://github.com/yangfuhai/afinal 对应源码: net.tsz.afinal.annotation.sqlite.* net.tsz.afinal.db.sqlite.* net.tsz.afinal.db.table.* net.tsz.afinal.utils.ClassUtils.net.tsz.afinal.utils.FieldUtils FinalDb 建库 FinalDb db = FinalDb.create(context, "my

spring框架学习(二)依赖注入

转自:http://blog.csdn.net/lishuangzhe7047/article/details/20740835 ———————————————————————————————————————————— spring框架为我们提供了三种注入方式,分别是set注入,构造方法注入,接口注入.接口注入不作要求,下面介绍前两种方式. 1,set注入 采用属性的set方法进行初始化,就成为set注入. 1)给普通字符类型赋值. [java] view plaincopyprint? pub

spring框架学习(一)

转自:http://blog.csdn.net/lishuangzhe7047/article/details/20740209 —————————————————————————————————————————————————— 1,什么是spring框架 spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,ibatis框架等组合使用. 2,架构概述 1)IoC(Inversi

从零开始编写自己的C#框架——框架学习补充说明

非常感谢轩辕公子提出了对本框架的看法与意见,所以这里也将回复贴出来,让大家都了解一下 本系列的快速开发指的是,框架构建完毕后,在这个基础上开发新功能非常快捷方便,基本不用写太多代码就可以在短时间内完成大量的基本功能.当然如果直接将全部代码贴出来,直接上例子的话可能更容易理解,但这样的话对于很多想了解整个框架实现过程的朋友来说,一下子太多代码就很难理解最初的思路了,同时大家也看到每一章都会附上独立的解决方案也是这么一回事,通过循序渐进的方式来进行学习.原本想要写得更细更多章节的,但由于个人空闲时间