auto culling

auto culling
自动剪裁,也就是把超出屏幕的quad自动移出渲染队列。我们的渲染关键是两个,一个是quad队列,一个是cmd队列。
void Renderer::renderBatch()
	{
		
		_drawnBatches = _drawnVertices = 0;
		if(_numQuads <= 0 || _batchedQuadCommands.empty())
		{
			return;
		}

		glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
		glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * _numQuads , _quads, GL_DYNAMIC_DRAW);
		
		
		
		glEnableVertexAttribArray(_vertexPosition); 	
		glVertexAttribPointer(
			_vertexPosition,			// attribute 0. No particular reason for 0, but must match the layout in the shader.
			3,			// size
			GL_FLOAT,	// type
			GL_FALSE,	// normalized?
			kQuadSize,			// stride
			(void*)(offsetof( Vertex, _position))	// array buffer offset
			);
		
		glEnableVertexAttribArray(_vertexUV); 	
		glVertexAttribPointer(
			_vertexUV,			// attribute 0. No particular reason for 0, but must match the layout in the shader.
			2,			// size
			GL_FLOAT,	// type
			GL_FALSE,	// normalized?
			kQuadSize,			// stride
			(void*)(offsetof( Vertex, _texCoord))	// array buffer offset
			);


			
		glEnableVertexAttribArray(_vertexColor); 				
		glVertexAttribPointer(
			_vertexColor,			// attribute 0. No particular reason for 0, but must match the layout in the shader.
			4,			// size
			GL_FLOAT,	// type
			GL_FALSE,	// normalized?
			kQuadSize,			// stride
			(void*)(offsetof( Vertex, _color))	// array buffer offset
			);

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
		glActiveTexture(GL_TEXTURE0);
		int quadsToDraw = 0;
		int startQuad = 0;

		GLuint _lastTextureID = 0;

		//Start drawing verties in batch
		for(const auto& cmd : _batchedQuadCommands)
		{
			auto newTextureID = cmd->getTextureID();
			if(_lastTextureID != newTextureID )
			{
				//Draw quads
				if(quadsToDraw > 0)
				{
					glDrawElements(GL_TRIANGLES, (GLsizei) quadsToDraw*6, GL_UNSIGNED_SHORT, (GLvoid*) (startQuad*6*sizeof(_indices[0])) );			
					_drawnBatches++;
					_drawnVertices += quadsToDraw*6;


					startQuad += quadsToDraw;
					quadsToDraw = 0;
				}

				//Use new Texture
				cmd->useTexture();
				//优化后直接给单位矩阵
				//caculateMVP(cmd->getModel());
				caculateMVP(Mat4(1.0));
				_lastTextureID = newTextureID;
			}

			quadsToDraw += cmd->getQuadCount();
		}





		if(quadsToDraw > 0)
		{			
			
			glDrawElements(GL_TRIANGLES, (GLsizei) quadsToDraw*6, GL_UNSIGNED_SHORT, (GLvoid*) (startQuad*6*sizeof(_indices[0])) );

			_drawnBatches++;
			_drawnVertices += quadsToDraw*6;
		}		
		for(auto& cmd : _batchedQuadCommands)
		{
			delete cmd;
		}
		_batchedQuadCommands.clear();
		_numQuads = 0;
	}

void Renderer::visit()
	{
 		int queueSize = _renderQueue.size();
		float perZorder = (zFar - zNear)/(float)(queueSize+1) ;

		//优化排序
		for (int i = 0; i < queueSize; ++i)
		{
			QuadCommand* cmd = _renderQueue[i];			
			Quad* quad = cmd->getQuads();
			int quadCount = cmd->getQuadCount();
			float zOrder = perZorder * (queueSize - i);
			for (int j = 0; j < quadCount; ++j)
			{				
				quad[j].tl._position.z = zOrder;
				quad[j].bl._position.z = zOrder;
				quad[j].tr._position.z = zOrder;
				quad[j].br._position.z = zOrder;
			}

			
		}		


		std::sort( std::begin(_renderQueue), std::end(_renderQueue),quadComparisonLess);

		//复制到批渲染队列
		copyToBatchRender(queueSize);

		//剪裁超出屏幕的quad
		cullQuadForBatchRender();
	}

void Renderer::copyToBatchRender( int queueSize )
	{
		for (int i = 0; i < queueSize; ++i)
		{
			QuadCommand* cmd = _renderQueue[i];
			memcpy(_preCullQuads + _preNumQuads, cmd->getQuads(), sizeof(Quad) * cmd->getQuadCount());
			convertToWorldCoordinates(_preCullQuads + _preNumQuads, cmd->getQuadCount(), cmd->getModel());
			BatchCommand* batchCommand = new BatchCommand();			
			memcpy(batchCommand,(BatchCommand*)cmd,sizeof(BatchCommand));			
			_batchedQuadCommands.push_back(batchCommand);
			_preNumQuads += cmd->getQuadCount();
		}		
		_renderQueue.clear();
	}
我们把渲染quad复制到一个临时块中,然后检测后复制到渲染队列中。
void Renderer::cullQuadForBatchRender()
	{
		if(_preNumQuads <= 0 || _batchedQuadCommands.empty())
		{
			return;
		}
		
		int quadIndex = 0;
		int startQuadNumber = 0;
		int cullQuadNumber = 0;
		Size winSize = Engine::getInstance()->getDesignSize();
		Rect rectWindow(-winSize.width/2 ,-winSize.height/2 ,winSize.width,winSize.height);

		std::vector<BatchCommand*>::iterator cmd = _batchedQuadCommands.begin();
		while (quadIndex < _preNumQuads)
		{
			Quad *q = &_preCullQuads[quadIndex];		
			

			Rect rectQuad(q->bl._position.x,q->bl._position.y,q->br._position.x - q->bl._position.x, q->tl._position.y - q->bl._position.y);
			if(rectWindow.intersectsRect(rectQuad))
			{
				memcpy(_quads+_numQuads,q,sizeof(Quad));
			}
			else
			{
				++cullQuadNumber;
			}

			++startQuadNumber;
			if(startQuadNumber == (*cmd)->getQuadCount())
			{
				int quadCount = startQuadNumber - cullQuadNumber;
				if (quadCount < 1)
				{
					cmd = _batchedQuadCommands.erase(cmd);
				}
				else
				{
					(*cmd)->setQuadCount(quadCount);
					++cmd; 
				}
				
				_numQuads -= cullQuadNumber;
				startQuadNumber = 0;
				cullQuadNumber = 0;
			}
			
			++quadIndex;
			++_numQuads;
			
		}
		

		_preNumQuads = 0;
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值