帧率控制及批量渲染

帧率控制及批量渲染
帧率fps很简单,关键在于时间的获取。
void Engine::mainLoop()
	{		
		struct timeval tv;
		gettimeofday (&tv, NULL);
		unsigned int now = tv.tv_sec * 1000000 + tv.tv_usec;
		if ( (now - _lastTime) > _animationInterval)
		{
			stepFrame();
			_lastTime = now;
		}
		else
		{
			#if (TARGET_PLATFORM == PLATFORM_WIN32)
			Sleep(0);
			#else
			sleep(0);
			#endif
			
		}		
	}

时间的获取使用函数gettimeofday,win32下我们利用getlocalTime来写一个。
#if (TARGET_PLATFORM == PLATFORM_WIN32)
int gettimeofday(struct timeval *tp, void *tzp)
{
	time_t clock;
	struct tm tm;
	SYSTEMTIME wtm;
	GetLocalTime(&wtm);
	tm.tm_year     = wtm.wYear - 1900;
	tm.tm_mon     = wtm.wMonth - 1;
	tm.tm_mday     = wtm.wDay;
	tm.tm_hour     = wtm.wHour;
	tm.tm_min     = wtm.wMinute;
	tm.tm_sec     = wtm.wSecond;
	tm. tm_isdst    = -1;
	clock = mktime(&tm);
	tp->tv_sec = clock;
	tp->tv_usec = wtm.wMilliseconds * 1000;
	return (0);
}
#endif
要注意的是, gettimeofday本生是微秒级精度,现在只能达到毫秒级。不过这个对于帧率控制也够了。

批量渲染的本质是相同纹理的quad,我们一次性给它画出来。
std::vector<QuadCommand*> _batchedQuadCommands;
		int _numQuads;
		Quad _quads[VBO_SIZE];
		GLushort _indices[6 * VBO_SIZE];
		GLuint _buffersVBO[2];
static const int VBO_SIZE = 65536 / 6;

里面的相互关系是1个quad 对应6个索引 顶点,int 值0-0xffff也就是0-65535。

Renderer::Renderer(void):_isInit(false),_numQuads(0)
	{		
		glGenBuffers(2,&_buffersVBO[0]);
		for( int i=0; i < VBO_SIZE; i++)
		{
			_indices[i*6+0] = (GLushort) (i*4+0);
			_indices[i*6+1] = (GLushort) (i*4+1);
			_indices[i*6+2] = (GLushort) (i*4+2);
			_indices[i*6+3] = (GLushort) (i*4+3);
			_indices[i*6+4] = (GLushort) (i*4+2);
			_indices[i*6+5] = (GLushort) (i*4+1);
		}
	}

Renderer::~Renderer(void)
	{
		glDeleteBuffers(2,&_buffersVBO[0]);
	}

void Renderer::renderBatch()
	{
		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]);
		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])) );			

					startQuad += quadsToDraw;
					quadsToDraw = 0;
				}

				//Use new Texture
				cmd->useTexture();
				_lastTextureID = newTextureID;
			}

			quadsToDraw += cmd->getQuadCount();
		}


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

		_batchedQuadCommands.clear();
		_numQuads = 0;
	}
_numQuads表示批量渲染集合的总个数。_batchedQuadCommands里是经过处理后的渲染集合,它把同纹理的quad给放在了一起。当检测到纹理不同时,就一次性把之前的quad给画出来。为了能够最大限度用到批量渲染。需要我们进行一个预处理操作,即modle*view*projection的计算不放到shader执行,放到cpu来执行,batch里的quad顶点是已经变换好之后的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值