文字渲染及渲染节点
我们先来最简单的文字渲染。即把文字画在一张png上,然后把png根据字符串画到屏幕上。
/********************************************************************
Copyright(C), 2012-2013,
FileName:Label.h
Description:
Author:cloud
Created:2014/11/19
history:
19:11:2014 11:46 by
*********************************************************************/
#pragma once
#include "export/RenderNode.h"
namespace cloud
{
class LabelBMFont:public RenderNode
{
public:
//png 字体
LabelBMFont(const std::string& string, const char* pngFile, int itemWidth, int itemHeight, int startCharMap);
LabelBMFont();
void render(const Mat4& parentMat4);
void setString(const std::string& string);
void reallocQuads(int count);
protected:
int _caculateStringLength(const std::string& string);
std::string _strLabel;
int _itemWidth;
int _itemHeight;
int _mapStartChar;
int _itemsPerColumn;
int _itemsPerRow;
};
}
/********************************************************************
Copyright(C), 2012-2013,
FileName:Label.cpp
Description:
Author:cloud
Created:2014/11/19
history:
19:11:2014 11:46 by
*********************************************************************/
#include "Label.h"
#include "base/TextureManager.h"
#include "base/render/Renderer.h"
namespace cloud
{
LabelBMFont::LabelBMFont()
{
}
LabelBMFont::LabelBMFont(const std::string& string, const char* pngFile, int itemWidth, int itemHeight, int startCharMap):RenderNode(pngFile)
{
_strLabel = string;
_itemWidth = itemWidth;
_itemHeight = itemHeight;
_mapStartChar = startCharMap;
_itemsPerColumn = (int)(_textureSize.height / _itemHeight);
_itemsPerRow = (int)(_textureSize.width / _itemWidth);
_quadsCount = _strLabel.size();
initQuads();
setString(string);
}
int LabelBMFont::_caculateStringLength(const std::string& string)
{
int length = 0;
int n = _strLabel.length();
const unsigned char *s = (unsigned char*)_strLabel.c_str();
for(int i = 0; i < n; i++) {
int a = s[i] - _mapStartChar;
if(a >= 0)
{
++length;
}
}
return length;
}
void LabelBMFont::setString(const std::string& string)
{
_strLabel = string;
int length = _caculateStringLength(string);
reallocQuads(length);
int n = _strLabel.length();
const unsigned char *s = (unsigned char*)_strLabel.c_str();
int index = 0;
for(int i = 0; i < n; i++) {
int a = s[i] - _mapStartChar;
if (a < 0)
{
continue;
}
float row = (float) (a % _itemsPerRow);
float col = (float) (a / _itemsPerRow);
float left = row * _itemWidth / _textureSize.width;
float right = left + _itemWidth / _textureSize.width;
float top = col * _itemHeight /_textureSize.height;
float bottom = top + _itemHeight /_textureSize.height;
ASSERT_MSG(index < length,"out of quads");
_quads[index].tl._texCoord.x = left;
_quads[index].tl._texCoord.y = top;
_quads[index].tr._texCoord.x = right;
_quads[index].tr._texCoord.y = top;
_quads[index].bl._texCoord.x = left;
_quads[index].bl._texCoord.y = bottom;
_quads[index].br._texCoord.x = right;
_quads[index].br._texCoord.y = bottom;
_quads[index].bl._position.x = (float) (i * _itemWidth);
_quads[index].bl._position.y = 0;
_quads[index].br._position.x = (float)(i * _itemWidth + _itemWidth);
_quads[index].br._position.y = 0;
_quads[index].tl._position.x = (float)(i * _itemWidth);
_quads[index].tl._position.y = (float)(_itemHeight);
_quads[index].tr._position.x = (float)(i * _itemWidth + _itemWidth);
_quads[index].tr._position.y = (float)(_itemHeight);
_quads[index].tl._color = Color(1,1,1,1);
_quads[index].tr._color = Color(1,1,1,1);
_quads[index].bl._color = Color(1,1,1,1);
_quads[index].br._color = Color(1,1,1,1);
++index;
}
}
void LabelBMFont::reallocQuads(int count)
{
if(count != _quadsCount)
{
_quads = (Quad*) realloc(_quads,count * sizeof(Quad));
_quadsCount = count;
memset(_quads,0,_quadsCount * sizeof(Quad));
}
}
void LabelBMFont::render(const Mat4& parentMat4)
{
_quadCommand.init(_quads,_textureID,_quadsCount,_blendFunc,this->transform(parentMat4));
Renderer::getInstance()->addQuadCommand(&_quadCommand);
}
}
完成文字之后,我们发现sprite,labelBMFont,particleQuad,skeletonAnimation都有相同的结构。我们把它抽出来成一个新的类RenderNode
/********************************************************************
Copyright(C), 2012-2013,
FileName:RenderNode.h
Description:
Author:cloud
Created:2014/11/19
history:
19:11:2014 11:46 by
*********************************************************************/
#pragma once
#include "export/Node.h"
#include "base/GLFix.h"
#include "base/render/Quad.h"
#include "base/TextureManager.h"
namespace cloud
{
class RenderNode:public Node
{
public:
RenderNode();
RenderNode(const char* texturePath);
void createTexture(const char* texturePath);
~RenderNode();
void initQuads();
void dellocQuads();
void cacheTexture(bool isCache);
protected:
GLuint _textureID;
Size _textureSize;
std::string _texturePath;
PictureType _picType;
QuadCommand _quadCommand;
Quad* _quads;
int _quadsCount;
BlendFunc _blendFunc;
Color _color;
bool _isCacheTexture;
};
}
/********************************************************************
Copyright(C), 2012-2013,
FileName:RenderNode.cpp
Description:
Author:cloud
Created:2014/11/19
history:
19:11:2014 11:46 by
*********************************************************************/
#include "RenderNode.h"
namespace cloud
{
RenderNode::RenderNode()
{
_textureID = 0;
_textureSize = Size(0,0);
_blendFunc = BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
RenderNode::RenderNode(const char* texturePath)
{
createTexture(texturePath);
}
void RenderNode::createTexture(const char* texturePath)
{
int textureWidth;
int textureHeight;
_color = Color::WHITE;
_isCacheTexture = false;
_textureID = TextureManager::getInstance()->createTexture(texturePath,textureWidth,textureHeight);
if(_textureID > 0)
{
_textureSize = Size(textureWidth,textureHeight);
_contentSize = _textureSize;
_texturePath = texturePath;
_picType = TextureManager::getInstance()->getTextureType(_texturePath.c_str());
}
else
{
_textureSize = Size(0,0);
}
_blendFunc = BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
RenderNode::~RenderNode()
{
dellocQuads();
if (!_isCacheTexture)
{
TextureManager::getInstance()->removeTexture(_texturePath.c_str());
}
}
void RenderNode::cacheTexture(bool isCache)
{
_isCacheTexture = isCache;
}
void RenderNode::initQuads()
{
_quads = (Quad*)malloc( _quadsCount * sizeof(Quad));
memset(_quads, 0, _quadsCount * sizeof(Quad));
}
void RenderNode::dellocQuads()
{
if(_quads)
{
free(_quads);
_quads = NULL;
}
}
}