//! ---|> Evaluator
void OccOverheadEvaluator::measure(FrameContext & context,Node & node,const Geometry::Rect & /*r*/) {

	//float currentRenderingTime=0;
	//int numTests=0;
	//int numVBO=0;
	int numPoly=0;
	Util::Color4f clearColor(0.5f, 0.5f, 0.9f, 1.0f);
	{ // 1. normal render pass
//        rc.clearScreen(0.5,0.5,0.9);
//        context.getRenderingContext().finish();
//        node.display(rc,renderingFlags);
		context.getRenderingContext().clearScreen(clearColor);
		node.display(context,renderingFlags|USE_WORLD_MATRIX);

		context.getRenderingContext().clearScreen(clearColor);
		context.getRenderingContext().finish();
		context.getStatistics().beginFrame();
		node.display(context,renderingFlags|USE_WORLD_MATRIX);
		context.getRenderingContext().finish();
		context.getStatistics().endFrame();
		numPoly=static_cast<int>(context.getStatistics().getValueAsDouble(context.getStatistics().getTrianglesCounter()));
	}

	// 2. test all group nodes if their bb is visible and collect them
	std::deque<GroupNode *> visibleGroupNodes;

	{
		// collect geometry nodes in frustum
		const auto groupNodesInVFList = collectNodesInFrustum<GroupNode>(&node,context.getCamera()->getFrustum());

		// setup occlusion queries
		int numQueries=groupNodesInVFList.size();
		if (numQueries==0) {
			values->push_back(nullptr); // TODO!!!
			return; // TODO??
		}

		auto queries = new Rendering::OcclusionQuery[numQueries];

		//  test bounding boxes
		context.getRenderingContext().pushAndSetDepthBuffer(Rendering::DepthBufferParameters(true, true, Rendering::Comparison::LEQUAL));
		int i=0;
		// start queries
		Rendering::OcclusionQuery::enableTestMode(context.getRenderingContext());
		for(const auto & groupNode : groupNodesInVFList) {
			queries[i].begin();
//            queries[i].fastBoxTest((*it)->getWorldBB());
			Rendering::drawAbsBox(context.getRenderingContext(), groupNode->getWorldBB() );
			queries[i].end();
			++i;
		}
		Rendering::OcclusionQuery::disableTestMode(context.getRenderingContext());
		i=0;
		// get results
		for(const auto & groupNode : groupNodesInVFList) {
			Geometry::Box extendedBox=groupNode->getWorldBB();
			extendedBox.resizeAbs(context.getCamera()->getNearPlane());

			if (queries[i].getResult() > 0 || extendedBox.contains(context.getCamera()->getWorldOrigin()) ) {
				visibleGroupNodes.push_back(groupNode);
			}
			++i;
		}
		context.getRenderingContext().popDepthBuffer();

		delete [] queries;
	}
	std::deque<GeometryNode *> geoNodesInVisibleGroupNodes;

	// 3. collect all direct geometry-node children
	{
		struct GeoChildrenCollector:public NodeVisitor {
			GeoChildrenCollector(std::deque<GeometryNode*> & _geoNodes,FrameContext & _context):
				geoNodes(_geoNodes),firstNode(true),frameContext(_context) {}
			virtual ~GeoChildrenCollector() {}

			std::deque<GeometryNode*> & geoNodes;
			bool firstNode;
			FrameContext & frameContext;

			// ---|> NodeVisitor
			NodeVisitor::status enter(Node * _node) override {
				// if this is the first call, continue...
				if(firstNode) {
					firstNode=false;
					return CONTINUE_TRAVERSAL;
				}
				// else collect the geometry children and break the traversal.
				GeometryNode * gn=dynamic_cast<GeometryNode *>(_node);
				if(gn){
					if(frameContext.getCamera()->testBoxFrustumIntersection( _node->getWorldBB()) != Geometry::Frustum::intersection_t::OUTSIDE)
						geoNodes.push_back(gn);
				}
				return BREAK_TRAVERSAL;
			}
		};
		for (auto & visibleGroupNode : visibleGroupNodes) {
			GeoChildrenCollector vis(geoNodesInVisibleGroupNodes,context);
			(visibleGroupNode)->traverse(vis);
		}

	}

	// 4. clear screen and measure time drawing children
	float perfectRenderingTime=0;
	{
		context.getRenderingContext().clearScreen(clearColor);

		context.getRenderingContext().finish();
		Util::Timer timer;
		timer.reset();

		for (auto & geoNodesInVisibleGroupNode : geoNodesInVisibleGroupNodes) {
			context.displayNode((geoNodesInVisibleGroupNode),renderingFlags|USE_WORLD_MATRIX);
		}

		context.getRenderingContext().finish();
		timer.stop();
		perfectRenderingTime=timer.getMilliseconds();
	}

//    // Test-costs:
//    float result=numTests!=0?(currentRenderingTime-perfectRenderingTime)/numTests:0;

	// currentRenderingTime-perfRendering:
//    float result=currentRenderingTime-perfectRenderingTime;

	float result=numPoly>0?perfectRenderingTime*1000/numPoly:0;

//    std::cout <<currentRenderingTime<<"-"<<perfectRenderingTime<<"="<<result<<"\t"<<numTests<<"\n";
//    std::cout <<numVBO<<":"<<geoNodesInVisibleGroupNodes.size()<<"\n";

//   float result=perfectRenderingTime;
//    values.push_back(currentRenderingTime);
//    values.push_back(perfectRenderingTime);
	values->push_back(new Util::_NumberAttribute<float>(result));

//    if(mode==SINGLE_VALUE){
//        if(result>renderingTime || renderingTime==0)
//            renderingTime=result;
//    }else{
//        values.push_back(result);
//    }

//    renderingTime=0;
}
Exemple #2
0
//! (internal) Main culling method
State::stateResult_t OccRenderer::performCulling(FrameContext & context,Node * rootNode, const RenderParam & rp){
	if(mode==MODE_UNCONDITIONED){ // destroy temporal coherence
		frameNumber++;
	}
	frameNumber++;

	updateNodeInformation(context,rootNode); // ???

	// used for statistics
	unsigned int tests=0;
	int testsVisible=0;
	int testsInvisible=0;
	int occludedGeometryNodes=0;


	Statistics & statistics = context.getStatistics();

	RenderParam childParam = rp + USE_WORLD_MATRIX;

	const Geometry::Vec3 camPos=context.getCamera()->getWorldOrigin();


//	NodeDistancePriorityQueue_F2B distanceQueue(camPos);
	NodeDistancePriorityQueue_F2B distanceQueue(camPos);

	{	// add root node's children
		const auto children = getChildNodes(rootNode);
		for(auto & child : children) {
			distanceQueue.push(child);
		}
	}

	std::queue<std::pair<Rendering::OcclusionQuery, Node *>> queryQueue;

//    bool wasIdle=true;
	int idleCount=0;
	while ( (!distanceQueue.empty()) || (!queryQueue.empty() ) ) {
		bool idle=true;

		while ( !queryQueue.empty() && queryQueue.front().first.isResultAvailable() ) {
			idle=false;

			const OcclusionQuery & currentQuery = queryQueue.front().first;
			unsigned int result = currentQuery.getResult();
			Node * node = queryQueue.front().second;

			queryQueue.pop();
			NodeInfo * nodeInfo = getNodeInfo(node);

			// Node is visible?
			if (result>0 ) {

				statistics.pushEvent(Statistics::EVENT_TYPE_END_TEST_VISIBLE,nodeInfo->getActualSubtreeComplexity());

				testsVisible++;
				if (node->isClosed()) {
					// mark parents as visible
					Node * n=node;
					NodeInfo * ni=nodeInfo;
					while( ni->getVisibleFrameNumber()!=frameNumber){
						ni->setVisibleFrameNumber(frameNumber);
						n=n->getParent();
						if(n==nullptr || n==rootNode) break;
						ni=getNodeInfo(n);
					}
				}
				nodeInfo->setVisibleFrameNumber(frameNumber);

				// haben wir schon bearbeitet? -> Weiter...
				if (nodeInfo->getProcessedFrameNumber()==frameNumber)
					continue;

////                if(node->visibleFrameNumber != (frameNumber-1)){ ????
				// Process node
				processNode(context,node,nodeInfo,distanceQueue,childParam);

////                }
			}// Node is fully occluded?
			else {
				testsInvisible++;


				statistics.pushEvent(Statistics::EVENT_TYPE_END_TEST_INVISIBLE, nodeInfo->getActualSubtreeComplexity());

				// not processed yet?
				if (nodeInfo->getProcessedFrameNumber()!=frameNumber) {
					// TODO: Store and propagate in tree.
					occludedGeometryNodes+=collectNodesInFrustum<GeometryNode>(node,context.getCamera()->getFrustum()).size();

					// mark the node as processed
					nodeInfo->setProcessedFrameNumber(frameNumber);
				}
				// In diesem Frame verdeckt worden? (dann haben wir nicht mit der Bearbeitung gewartet und
				// die Kinder liegen bereits in der distanceQueue; die sollten jetzt �bersprungen werden)
				if ( nodeInfo->getVisibleFrameNumber() == (frameNumber-1) ) {
					if (!node->isClosed()) {
						const auto children = getChildNodes(node);
						for(auto & child : children) {
							getNodeInfo(child)->setProcessedFrameNumber(frameNumber);
							// TODO: Check if ancestors have to be removed too.
						}
					}
				}
			}
		}
		// ...
		if ( ! distanceQueue.empty()) {

			idle=false;

			Node * node=distanceQueue.top();
			NodeInfo * nodeInfo=getNodeInfo(node);
			distanceQueue.pop();

			// If the current node has already been processed, then continue.
			if (nodeInfo->getProcessedFrameNumber()==frameNumber ) continue; // ||node->isEmpty()

//			// skip empty subtrees // does never happen (checked in processNode)
//			if( nodeInfo->getActualSubtreeComplexity() == 0){
//                nullBoxes++;
//                continue;
//			}

			// Kamera innerhalb der (um die nearplane vergroesserte) Box? -> immer sichtbar
			// [2008-01-04_CJ] Bugfix: added nearplane addition; could result in dissapearing scene-parts.
			Geometry::Box extendedBox=node->getWorldBB(); //node->getGeometryBB();
			extendedBox.resizeAbs(context.getCamera()->getNearPlane());
			if (extendedBox.contains(camPos)) {

				nodeInfo->setVisibleFrameNumber(frameNumber);

				// Process node
				processNode(context,node,nodeInfo,distanceQueue,childParam);
				continue;
			}

			// !IS_INSIDE_FRUSTUM(node)
			if ( nodeInfo->getActualFrustumStatus()== Geometry::Frustum::OUTSIDE)
				continue;

			// [MODE_OPT_CULLING] For optimal culling, skip all unnecessary tests
			if(mode==MODE_OPT_CULLING && nodeInfo->getVisibleFrameNumber() == (frameNumber-1)){
				nodeInfo->setVisibleFrameNumber(frameNumber);
				// Process node
				processNode(context,node,nodeInfo,distanceQueue,childParam);
				continue;
			}

			// if query reasonable
			// TODO: Something missing here?

			{ // start occlusion test for the current node
				Rendering::OcclusionQuery query;

				Rendering::OcclusionQuery::enableTestMode(context.getRenderingContext());
				query.begin();
				Rendering::drawFastAbsBox(context.getRenderingContext(), node->getWorldBB());
				query.end();
				Rendering::OcclusionQuery::disableTestMode(context.getRenderingContext());
				tests++;
				queryQueue.emplace(std::move(query), node);

				statistics.pushEvent(Statistics::EVENT_TYPE_START_TEST, nodeInfo->getActualSubtreeComplexity());
			}

			// if the current node was visible in the last frame,
			//  then assume that it is also visible in this frame and process it.
			if (nodeInfo->getVisibleFrameNumber() == (frameNumber-1) ) {
				// Process node
				processNode(context,node,nodeInfo,distanceQueue,childParam);
			}

		}
//		else{
			// waiting

//		}
		if (idle) {
			statistics.pushEvent(Statistics::EVENT_TYPE_IDLE, idleCount++);
		} else {
			idleCount = 0;
		}

	}

	statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestCounter(), tests);
	statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestVisibleCounter(), testsVisible);
	statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestInvisibleCounter(), testsInvisible);
	statistics.addValue(OcclusionCullingStatistics::instance(statistics).getCulledGeometryNodeCounter(), occludedGeometryNodes);
	statistics.pushEvent(Statistics::EVENT_TYPE_FRAME_END,0.3);

	return State::STATE_SKIP_RENDERING;
}
Exemple #3
0
State::stateResult_t PhotonRenderer::doEnableState(FrameContext & context, Node * node, const RenderParam & rp){
#ifdef MINSG_THESISSTANISLAW_GATHER_STATISTICS
  Rendering::RenderingContext::finish();
  _timer.reset();
#endif // MINSG_THESISSTANISLAW_GATHER_STATISTICS

  if(!_photonSampler){
    WARN("No PhotonSampler present in PhotonRenderer!");
    return State::stateResult_t::STATE_SKIPPED;
  }
  
  if(!_approxScene){
    WARN("No approximated Scene present in PhotonRenderer!");
    return State::stateResult_t::STATE_SKIPPED;
  }
  
  
  auto& rc = context.getRenderingContext();
  rc.setImmediateMode(true);
  rc.applyChanges();
  
  if(_fboChanged){
    if(!initializeFBO(rc)){
      WARN("Could not initialize FBO for PhotonRenderer!");
      return State::stateResult_t::STATE_SKIPPED;
    }
    _fboChanged = false;
  }
  
  RenderParam newRp;
  
  rc.pushAndSetFBO(_fbo.get());
  rc.clearDepth(1.0f);
  
  rc.applyChanges();
  
  for(int32_t i = 0; i < _photonSampler->getPhotonNumber(); i++){
    _fbo->setDrawBuffers(2);
    rc.pushAndSetShader(_indirectLightShader.get());
    _lightPatchRenderer->bindTBO(rc, true, false);
    _photonSampler->bindPhotonBuffer(1);
    context.pushAndSetCamera(_photonCamera.get());
    _indirectLightShader->setUniform(rc, Rendering::Uniform("photonID", i));
    
    rc.clearDepth(1.0f);
    rc.clearColor(Util::Color4f(0.f, 0.f, 0.f, 0.f));
    _approxScene->display(context, newRp);
    
    context.popCamera();
    _photonSampler->unbindPhotonBuffer(1);
    _lightPatchRenderer->unbindTBO(rc);
    rc.popShader();
    
    
    // Accumulate all pixel values in one photon 
    _fbo->setDrawBuffers(0);
    rc.pushAndSetShader(_accumulationShader.get());
    _accumulationShader->setUniform(rc, Rendering::Uniform("photonID", i));
    _accumulationShader->setUniform(rc, Rendering::Uniform("samplingWidth", static_cast<int>(_samplingWidth)));
    _accumulationShader->setUniform(rc, Rendering::Uniform("samplingHeight", static_cast<int>(_samplingHeight)));
    _photonSampler->bindPhotonBuffer(1);
    rc.clearDepth(1.0f);
    Rendering::TextureUtils::drawTextureToScreen(rc, Geometry::Rect_i(0, 0, _samplingWidth, _samplingHeight), *_indirectLightTexture.get(), Geometry::Rect_f(0.0f, 0.0f, 1.0f, 1.0f));
    _photonSampler->unbindPhotonBuffer(1);
    rc.popShader();
  }
  
  rc.popFBO();
  
  rc.setImmediateMode(false);
  
//  rc.pushAndSetShader(nullptr);
//  Rendering::TextureUtils::drawTextureToScreen(rc, Geometry::Rect_i(0, 0, _samplingWidth, _samplingHeight), *(_indirectLightTexture.get()), Geometry::Rect_f(0.0f, 0.0f, 1.0f, 1.0f));
//  rc.popShader();
//  return State::stateResult_t::STATE_SKIP_RENDERING;

#ifdef MINSG_THESISSTANISLAW_GATHER_STATISTICS
  Rendering::RenderingContext::finish();
  _timer.stop();
  auto& stats = context.getStatistics();
  Statistics::instance(stats).addPhotonRendererTime(stats, _timer.getMilliseconds());
#endif // MINSG_THESISSTANISLAW_GATHER_STATISTICS

  return State::stateResult_t::STATE_OK;
}
Exemple #4
0
//! ---|> [State]
State::stateResult_t CHCRenderer::doEnableState(FrameContext & context,Node * rootNode, const RenderParam & rp){
	if(rp.getFlag(SKIP_RENDERER))
		return State::STATE_SKIPPED;
	if(debugShowVisible){
		std::deque<Node *> nodes;
		{
			const auto children = getChildNodes(rootNode);
			nodes.insert(nodes.end(), children.begin(), children.end());
		}
		while(!nodes.empty()){
			Node& node = *nodes.front();
			nodes.pop_front();
			auto& nodeInfo = getNodeInfo(node);
			if(nodeInfo.frameNr == frameNr && nodeInfo.visible){
				if(node.isClosed())
					context.displayNode(&node,rp);
				else {
					const auto children = getChildNodes(&node);
					nodes.insert(nodes.end(), children.begin(), children.end());
				}
			}
		}
	}else{
		++frameNr;
		
		// used for statistics
		unsigned int stat_numTests = 0;
		unsigned int stat_numTestsInvisible = 0;
		unsigned int stat_numTestsVisible = 0;
		Statistics & statistics = context.getStatistics();

		RenderParam childParam = rp + USE_WORLD_MATRIX;

		const auto& camera = *context.getCamera();
		const Geometry::Vec3 camPos = camera.getWorldOrigin();
		const float bbEnlargement = camera.getNearPlane();
		NodeDistancePriorityQueue_F2B distanceQueue(camPos);
		std::queue<std::pair<Rendering::OcclusionQuery, Node*>> queryQueue;

		const auto traverseNode = [&](Node& node){
			if( node.isClosed() ){ // leaf node
				context.displayNode(&node, childParam );
			}else{
				for(auto & child : getChildNodes(&node))
					distanceQueue.push(child);
			}
		};
		const auto pullUpVisibility = [&](Node& node){
			for(Node* n=&node; n&&n!=rootNode; n = n->getParent()){
				auto& nodeInfo = getNodeInfo(*n);
				if(nodeInfo.frameNr == frameNr && nodeInfo.visible)
					break;
				nodeInfo.visible = true;
				nodeInfo.frameNr = frameNr;
				
			};
		};
		const auto startQuery = [&](Node& node,const Geometry::Box& worldBoundingBox){
			Rendering::OcclusionQuery query;
			Rendering::OcclusionQuery::enableTestMode(context.getRenderingContext());
			query.begin();
			Rendering::drawAbsBox(context.getRenderingContext(), worldBoundingBox );
			query.end();
			Rendering::OcclusionQuery::disableTestMode(context.getRenderingContext());
			return std::make_pair(std::move(query),&node);
		};
		
		traverseNode(*rootNode);
		while(!distanceQueue.empty() || !queryQueue.empty()){
				
			// ---- PART 1: process finished occlusion queries
			while( !queryQueue.empty() && (distanceQueue.empty() || queryQueue.front().first.isResultAvailable()) ){
				if( queryQueue.front().first.getResult()>0 ){
					++stat_numTestsVisible;
					statistics.pushEvent( Statistics::EVENT_TYPE_END_TEST_VISIBLE, 1);

					Node& node = *queryQueue.front().second;
					pullUpVisibility(node);
					auto& nodeInfo = getNodeInfo( node );
					if( !nodeInfo.wasVisible )
						traverseNode(node);
				}else{
					++stat_numTestsInvisible;
					statistics.pushEvent( Statistics::EVENT_TYPE_END_TEST_INVISIBLE, 1);
				}
				queryQueue.pop();
			}
			
			// ---- PART 2: tree traversal
			if( !distanceQueue.empty() ){
				Node& node = *distanceQueue.top();
				distanceQueue.pop();
				const Geometry::Box worldBoundingBox = node.getWorldBB();
				if (camera.testBoxFrustumIntersection( node.getWorldBB()) == Geometry::Frustum::intersection_t::OUTSIDE) {
					continue;
				}
				Geometry::Box enlargedBox = worldBoundingBox;
				enlargedBox.resizeAbs( bbEnlargement );
				if( enlargedBox.contains(camPos) ){
					pullUpVisibility(node);
					traverseNode(node);
					continue;
				}
				auto& nodeInfo = getNodeInfo( node );
				// identify previously visible nodes
				const bool wasVisible = nodeInfo.frameNr == frameNr-1 && nodeInfo.visible;
				nodeInfo.wasVisible = wasVisible;
				
				// reset node's visibility flag
				nodeInfo.visible = false;
				// update node's visited flag
				nodeInfo.frameNr = frameNr;
				
				// test leafs and previously invisible nodes
				if( node.isClosed() || !wasVisible){ // on testing front
					// start test
					++stat_numTests;
					statistics.pushEvent(Statistics::EVENT_TYPE_START_TEST, 1);
					queryQueue.push( std::move(startQuery(node,worldBoundingBox)) );
				}
				// traverse a node unless it was invisible
				if( wasVisible )
					traverseNode( node );
			}
		}

		statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestVisibleCounter(), stat_numTestsVisible);
		statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestInvisibleCounter(), stat_numTestsInvisible);
		statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestCounter(), stat_numTests);
	}
//			std::cout << std::endl;

	return State::STATE_SKIP_RENDERING;
}