Posted on 2010-01-17 17:32
剑孤寒 阅读(3654)
评论(10) 编辑 收藏 引用 所属分类:
Galaxy2D 游戏引擎教程
在现在的3D游戏中有很多非常漂亮的Shader特效,比如爆炸产生的气浪,水流过玻璃使后面的景物变得扭曲等。这些特效并不是3D游戏的专利,有很多特效其实也是可以用在2D游戏里的,今天这一节我们就来学习一下如何在Galaxy2D游戏引擎中使用PixelShader制作爆炸气浪效果。
首先要判断显卡是否支持PixelShader,在OnInitiate()函数中添加:
if (System_GetState(GGE_PSVERSION) < PS_2_0) return false;![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
然后创建Shader和RenderTarget:
m_shaderFx = Shader_Load("shader.fx", "ShaderFx", PS_2_0);![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
m_fxTarget = Texture_Create(640, 480, true);
m_targetTex = Texture_Create(640, 480, true);
Shader_Load()函数用于载入Shader文件,第一个参数是Shader文件名,第二个参数指定Shader入口函数,第三个参数指定使用的Shader 版本,这里使用的是PS2.0。
RenderTarget就像一个临时的画布,我们可以将贴图画在某个RenderTarget上而不影响后台缓存或其它的RenderTarget,常常用来做一些特殊效果,在这里m_fxTarget用于绘制NormalMap贴图,m_targetTex用于绘制正常图像,以便最后进行Shader合成。为了使用Shader还必须将m_shaderFx绑定到一个ggeSprite上:m_targetSpr->SetShader(m_shaderFx);
接下来在OnUpdate(float dt)里添加如下代码:
if (Input_IsKeyDown(GGEK_SPACE))
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
m_alpha.a = 1; //气浪强度
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
m_posX = Random_Int(256, 384);//气浪中心点位置
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
m_posY = Random_Int(176, 304); //气浪中心点位置
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
m_scale = 1.0f;//气浪大小
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
}
Input_IsKeyDown()函数用于判断是否有键按下,后面的GGEK_SPACE是空格键的虚拟键值,其他的键值可在文档里找到。在Galaxy2D引擎里提供了一系列Input_*函数,用于键盘鼠标输入判断。
最后在OnRender()添加如下代码:
//如果alpha值大于0才进行Shader合成
if (m_alpha.a > 0)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
//开始在m_fxTarget上画东西
Graph_BeginScene(m_fxTarget);
Graph_Clear();
m_fxSpr->SetColor(m_alpha.GetColor());
m_fxSpr->SetPositionEx(m_posX, m_posY, 0, m_scale);
m_fxSpr->Render();
Graph_EndScene();
}
![](/Images/OutliningIndicators/None.gif)
//开始画正常图像
Graph_BeginScene(m_targetTex);
Graph_Clear(0);
m_bgSpr->Render();
Graph_EndScene();
![](/Images/OutliningIndicators/None.gif)
Graph_BeginScene();
if (m_alpha.a > 0)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
//绑定Shader要使用的纹理
Graph_SetCurrentShader(m_shaderFx);
m_shaderFx->SetTexture("FxTex", m_targetTex, true, TEXADDRESS_BORDER, 0);
m_shaderFx->SetTexture("NormalMapTex", m_fxTarget);
}
else
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
Graph_SetCurrentShader(0);
}
![](/Images/OutliningIndicators/None.gif)
m_targetSpr->Render();
Graph_SetCurrentShader(0);
Graph_EndScene();
好了,现在将下面的Shader代码复制到shader.fx文件中就大功告成了:
sampler2D FxTex:register(s0);
sampler2D NormalMapTex:register(s1);
![](/Images/OutliningIndicators/None.gif)
float4 ShaderFx(float2 texCoord:TEXCOORD0):COLOR0
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
float3 normal = tex2D(NormalMapTex, texCoord);
texCoord += dot(normal, float3(0, 0, 0.1));
float4 tex = tex2D(FxTex, texCoord);
![](/Images/OutliningIndicators/InBlock.gif)
return tex;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
最后上一张最终效果图,由于gif只有256色所以不大清楚,不过大致的效果还是可以看出来的,自己觉得还是比较华丽的^_^,当然Shader能做的不仅如此,只要大家发挥想象力一定能作出更Cool更华丽的特效。![](/images/cppblog_com/jianguhan/tutorial2.gif)