渲染原理

图片渲染的核心思路是:在一个矩形上使用 2D 纹理贴图,通过纹理坐标映射把图片内容投射到矩形表面,从而显示一张图片。

OpenGL 只认识 bitmap(位图)格式,所以 jpeg、png 等压缩格式必须先解码成 bitmap,才能上传为纹理并参与渲染。

Lite2D Text 示例

下面是 Lite2D 中 Text 组件的 draw 实现,它负责把 freetype 生成的字体 bitmap 作为纹理逐字渲染到屏幕上。

void Text::draw()
                {
                
                	if (this->_is_need_update)
                	{//need sync string
                		this->clear();
                		this->updateString();
                		this->_is_need_update = false;
                	}
                	if (this->_is_need_update_color)
                	{//need sync color
                		this->updateColor();
                		this->_is_need_update_color = false;
                	}
                
                
                	float width = 0;
                	float height = 0;
                //deal with each font with string
                	for (int i = 0; i < _queue.size(); i++)
                	{
                		CharBitMap*bitmap = _queue[i];
                
                
                		glLoadIdentity();// vetex can work once
                
                		glBindTexture(GL_TEXTURE_2D, bitmap->texture_id);
                
                		// able alpha blend for the texture who has alpha
                		glEnable(GL_BLEND);
                		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                		//able opacity
                		glEnable(GL_ALPHA_TEST);
                		glAlphaFunc(GL_GREATER, 0.0f);
                		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
                
                
                		//start to render
                
                		glBegin(GL_QUADS);
                
                		//fix bug of transform of difference window size
                
                		Vec2 windowsize = Director::getInstance()->getWindowSize();
                
                		float xx = -1.0f; //position
                		float yy = -1.0f;
                
                		float scaleX = this->getGlobalScale().x; //scale
                		float scaleY = this->getGlobalScale().y;
                
                		float imageWidth = bitmap->width / windowsize.x;
                		float imageHeight = bitmap->height / windowsize.y;
                
                		float x, y;
                		if (i >= 1)
                		{
                			width += (_queue[i - 1]->width + _queue[i]->width) / 2.0f;
                			width += _fontsize*0.05f;
                		}
                		else
                		{
                
                			width += _queue[i]->width / 2.0f;
                		}
                		if (_queue[i]->_char <= 0xff)
                		{
                			height = _queue[i]->height / 2.0f + _fontsize*0.08F;
                		}
                		else
                		{
                			height = _fontsize / 2.0f;
                
                		}
                		height -= _fontsize *0.08;
                
                
                
                
                		// transform position with inner anchor point
                		x = (this->getGlobalPosition().x + width - _rect.x*_anchor.x) / windowsize.x * 2.0f
                			+ imageWidth - (0.5)*imageWidth * 2.0f;
                
                		y = (this->getGlobalPosition().y + height-_fontsize*_anchor.y*0.71// - (_anchor.y)*height * 2.0f)
                			)/windowsize.y * 2.0f + imageHeight - (0.5)*imageHeight * 2.0f;
                
                		xx += x;
                		yy += y;
                
                		//for different image has different Texcoord
                		float _coord2f[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
                
                
                		//	glPushMatrix();
                
                
                		// transform the vertexs
                		glTexCoord2f(_coord2f[0], _coord2f[1]); glVertex2f(-imageWidth*scaleX + xx, -imageHeight*scaleY + yy);
                		glTexCoord2f(_coord2f[2], _coord2f[3]); glVertex2f(imageWidth*scaleX + xx, -imageHeight *scaleY + yy);
                		glTexCoord2f(_coord2f[4], _coord2f[5]); glVertex2f(imageWidth*scaleX + xx, imageHeight*scaleY + yy);
                		glTexCoord2f(_coord2f[6], _coord2f[7]); glVertex2f(-imageWidth*scaleX + xx, imageHeight*scaleY + yy);
                
                
                
                		//glPopMatrix();
                
                		glDisable(GL_BLEND);
                		glDisable(GL_ALPHA_TEST);
                
                
                		glEnd();
                	}
                	Node::draw();
                
                }