文字渲染及渲染节点

文字渲染及渲染节点

我们先来最简单的文字渲染。即把文字画在一张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;
		}
	}	
	

}



### Blender 渲染节点使用教程及常见问题解决方案 #### 一、理解渲染节点的概念 在Blender中,渲染节点是用于处理图像合成的强大工具。通过创建复杂的节点网络,用户能够控制和调整渲染效果中的各个部分,从而获得更精细的视觉成果[^1]。 #### 二、基本操作指南 要开始构建自己的渲染节点树,在Compositor工作区打开Node Editor窗口。点击“Use Nodes”,激活默认的Render Layers与Composite两个基础节点。前者负责接收来自场景的数据流;后者则执行最后一步——将所有经过加工后的图层合成为一张完整的图片或视频帧[^2]。 对于初学者来说,建议先熟悉一些常用的节点类型: - **Math Node (数学运算)**:可用于调节亮度对比度等参数; - **Color Ramp (颜色渐变)**:有助于创造平滑过渡的效果; - **Blur Node (模糊滤镜)**:模拟景深虚化现象; - **Vector Blur (矢量模糊)**:适用于运动物体产生的拖影仿真; - **Glare Node (眩光特效)**:增添光源周围闪耀光芒的真实感。 ```python import bpy # 创建一个新的材质并启用节点编辑器 material = bpy.data.materials.new(name="NewMaterial") material.use_nodes = True nodes = material.node_tree.nodes links = material.node_tree.links # 添加纹理坐标输入节点 texture_coord_node = nodes.new(type='ShaderNodeTexCoord') # 添加映射节点 mapping_node = nodes.new(type='ShaderNodeMapping') links.new(texture_coord_node.outputs['UV'], mapping_node.inputs['Vector']) # 连接至原理着色器的颜色输入端口 principled_bsdf = nodes.get('Principled BSDF') links.new(mapping_node.outputs['Vector'], principled_bsdf.inputs['Base Color']) ``` 这段Python脚本展示了如何利用API自动化地建立简单的节点连接关系,这对于批量修改多个对象属性非常有用。 #### 三、优化性能的小贴士 当面对复杂场景时,合理的节点设计不仅影响最终画质的好坏,还会显著改变计算效率。因此,在搭建过程中应当注意以下几点以提高工作效率[^3]: - 尽可能减少不必要的转换环节,比如过多的颜色空间变换可能会引入额外开销; - 对于重复使用的子流程考虑封装成组(Group),既便于管理又利于重用; - 利用Cache功能保存中间结果,避免每次重新计算相同片段浪费时间; - 如果只关心特定区域内的变化,则可以通过Crop/Border选项限定实际参与合成范围来加快预览速度。 #### 四、解决常见的错误情况 有时即使按照正确的方式设置了节点链路仍然得不到预期的结果,这时可以从以下几个方面排查原因: - 检查各节点间是否存在未连接好的接口,特别是那些看似无关紧要却至关重要的辅助线; - 确认所选模式是否匹配当前需求(例如某些特殊效果仅限GPU加速有效); - 查看是否有第三方插件干扰了正常逻辑运作; - 参考官方文档或是社区论坛获取更多针对性的帮助和支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值