void SceneView::updateUniforms()
{
if (!_localStateSet)
{
_localStateSet = new osg::StateSet;
}
if (!_localStateSet) return;
if ((_activeUniforms & FRAME_NUMBER_UNIFORM) && _frameStamp.valid())
{
osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_FrameNumber",osg::Uniform::INT);
uniform->set(_frameStamp->getFrameNumber());
}
if ((_activeUniforms & FRAME_TIME_UNIFORM) && _frameStamp.valid())
{
osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_FrameTime",osg::Uniform::FLOAT);
uniform->set(static_cast<float>(_frameStamp->getReferenceTime()));
}
if ((_activeUniforms & DELTA_FRAME_TIME_UNIFORM) && _frameStamp.valid())
{
float delta_frame_time = (_previousFrameTime != 0.0) ? static_cast<float>(_frameStamp->getReferenceTime()-_previousFrameTime) : 0.0f;
_previousFrameTime = _frameStamp->getReferenceTime();
osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_DeltaFrameTime",osg::Uniform::FLOAT);
uniform->set(delta_frame_time);
}
if ((_activeUniforms & SIMULATION_TIME_UNIFORM) && _frameStamp.valid())
{
osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_SimulationTime",osg::Uniform::FLOAT);
uniform->set(static_cast<float>(_frameStamp->getSimulationTime()));
}
if ((_activeUniforms & DELTA_SIMULATION_TIME_UNIFORM) && _frameStamp.valid())
{
float delta_simulation_time = (_previousSimulationTime != 0.0) ? static_cast<float>(_frameStamp->getSimulationTime()-_previousSimulationTime) : 0.0f;
_previousSimulationTime = _frameStamp->getSimulationTime();
osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_DeltaSimulationTime",osg::Uniform::FLOAT);
uniform->set(delta_simulation_time);
}
if (_activeUniforms & VIEW_MATRIX_UNIFORM) //通过Uniform把漫游器矩阵传给着色器
{
osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_ViewMatrix",osg::Uniform::FLOAT_MAT4);
uniform->set(getViewMatrix());
}
if (_activeUniforms & VIEW_MATRIX_INVERSE_UNIFORM)
{
osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_ViewMatrixInverse",osg::Uniform::FLOAT_MAT4);
uniform->set(osg::Matrix::inverse(getViewMatrix()));
}
}
//------------------
void CullVisitor::apply(Transform& node)//
{
if (isCulled(node)) return;
// push the culling mode.
pushCurrentMask();
// push the node's state.
StateSet* node_state = node.getStateSet();
if (node_state) pushStateSet(node_state);
ref_ptr<RefMatrix> matrix = createOrReuseMatrix(*getModelViewMatrix());
node.computeLocalToWorldMatrix(*matrix,this);//matrix转到世界坐标,模型视图矩阵和局部矩阵
pushModelViewMatrix(matrix.get(), node.getReferenceFrame());
handle_cull_callbacks_and_traverse(node);
popModelViewMatrix();
// pop the node's state off the render graph stack.
if (node_state) popStateSet();
// pop the culling mode.
popCurrentMask();
}
void CullVisitor::apply(Geode& node)
{
if (isCulled(node)) return;
// push the node's state.
StateSet* node_state = node.getStateSet();
if (node_state) pushStateSet(node_state);
// traverse any call callbacks and traverse any children.
handle_cull_callbacks_and_traverse(node);
RefMatrix& matrix = *getModelViewMatrix(); //得到当前的局部坐标矩阵和视图矩阵
for(unsigned int i=0;i<node.getNumDrawables();++i)
{
Drawable* drawable = node.getDrawable(i);
const BoundingBox &bb =drawable->getBound();
if( drawable->getCullCallback() )
{
if( drawable->getCullCallback()->cull( this, drawable, &_renderInfo ) == true )
continue;
}
//else
{
if (node.isCullingActive() && isCulled(bb)) continue;
}
if (_computeNearFar && bb.valid())
{
if (!updateCalculatedNearFar(matrix,*drawable,false)) continue;
}
// need to track how push/pops there are, so we can unravel the stack correctly.
unsigned int numPopStateSetRequired = 0;
// push the geoset's state on the geostate stack.
StateSet* stateset = drawable->getStateSet();
if (stateset)
{
++numPopStateSetRequired;
pushStateSet(stateset);
}
CullingSet& cs = getCurrentCullingSet();
if (!cs.getStateFrustumList().empty())
{
osg::CullingSet::StateFrustumList& sfl = cs.getStateFrustumList();
for(osg::CullingSet::StateFrustumList::iterator itr = sfl.begin();
itr != sfl.end();
++itr)
{
if (itr->second.contains(bb))
{
++numPopStateSetRequired;
pushStateSet(itr->first.get());
}
}
}
float depth = bb.valid() ? distance(bb.center(),matrix) : 0.0f;
if (osg::isNaN(depth))
{
osg::notify(osg::NOTICE)<<"CullVisitor::apply(Geode&) detected NaN,"<<std::endl
<<" depth="<<depth<<", center=("<<bb.center()<<"),"<<std::endl
<<" matrix="<<matrix<<std::endl;
}
else
{
addDrawableAndDepth(drawable,&matrix,depth);//传进去矩阵
}
for(unsigned int i=0;i< numPopStateSetRequired; ++i)
{
popStateSet();
}
}
// pop the node's state off the geostate stack.
if (node_state) popStateSet();
}
inline void CullVisitor::addDrawableAndDepth(osg::Drawable* drawable,osg::RefMatrix* matrix,float depth)
{
if (_currentStateGraph->leaves_empty())
{
// this is first leaf to be added to StateGraph
// and therefore should not already know to current render bin,
// so need to add it.
_currentRenderBin->addStateGraph(_currentStateGraph);
}
//_currentStateGraph->addLeaf(new RenderLeaf(drawable,matrix,depth));
_currentStateGraph->addLeaf(createOrReuseRenderLeaf(drawable,_projectionStack.back().get(),matrix,depth));//生成渲染叶
}
inline RenderLeaf* CullVisitor::createOrReuseRenderLeaf(osg::Drawable* drawable,osg::RefMatrix* projection,osg::RefMatrix* matrix, float depth)
{
// Skips any already reused renderleaf.
while (_currentReuseRenderLeafIndex<_reuseRenderLeafList.size() &&
_reuseRenderLeafList[_currentReuseRenderLeafIndex]->referenceCount()>1)
{
osg::notify(osg::NOTICE)<<"Warning:createOrReuseRenderLeaf() skipping multiply refrenced entry."<< std::endl;
++_currentReuseRenderLeafIndex;
}
// If still within list, element must be singularly referenced then return it to be reused.
if (_currentReuseRenderLeafIndex<_reuseRenderLeafList.size())
{
RenderLeaf* renderleaf = _reuseRenderLeafList[_currentReuseRenderLeafIndex++].get();
renderleaf->set(drawable,projection,matrix,depth);
return renderleaf;
}
// Otherwise need to create new renderleaf.
RenderLeaf* renderleaf = new RenderLeaf(drawable,projection,matrix,depth);//matrix传入到渲染叶
_reuseRenderLeafList.push_back(renderleaf);
++_currentReuseRenderLeafIndex;
return renderleaf;
}
}
void RenderLeaf::render(osg::RenderInfo& renderInfo,RenderLeaf* previous)
{
osg::State& state = *renderInfo.getState();
// don't draw this leaf if the abort rendering flag has been set.
if (state.getAbortRendering())
{
//cout << "early abort"<<endl;
return;
}
if (previous)
{
// apply matrices if required.
state.applyProjectionMatrix(_projection.get());
state.applyModelViewMatrix(_modelview.get());
// apply state if required.
StateGraph* prev_rg = previous->_parent;
StateGraph* prev_rg_parent = prev_rg->_parent;
StateGraph* rg = _parent;
if (prev_rg_parent!=rg->_parent)
{
StateGraph::moveStateGraph(state,prev_rg_parent,rg->_parent);
// send state changes and matrix changes to OpenGL.
state.apply(rg->getStateSet());
}
else if (rg!=prev_rg)
{
// send state changes and matrix changes to OpenGL.
state.apply(rg->getStateSet());
}
// draw the drawable
_drawable->draw(renderInfo);
}
else
{
// apply matrices if required.
state.applyProjectionMatrix(_projection.get()); //应用模型视图矩阵
state.applyModelViewMatrix(_modelview.get());
// apply state if required.
StateGraph::moveStateGraph(state,NULL,_parent->_parent);
state.apply(_parent->getStateSet());
// draw the drawable
_drawable->draw(renderInfo);
}
if (_dynamic)
{
state.decrementDynamicObjectCount();
}
// osg::notify(osg::NOTICE)<<"RenderLeaf "<<_drawable->getName()<<" "<<_depth<<std::endl;
}