天天看点

[cocos2d-x]对CCSprite进行高斯模糊

摘要 cocos2d-x 2.2.1 中没有直接用于模糊精灵的类,但是在TestCpp里面的ShaderTest实现了高斯模糊。于是直接搬过来用就行了。

你可以从下面的目录找到示例的源代码:

cocos2d-x-2.2.1\samples\Cpp\TestCpp\Classes\ShaderTest

SpriteBlur类用于实现高斯模糊,但并没有定义在ShaderTest.h中,打开ShaderTest.cpp,大概在488行有这个类的定义和实现:

<code>01</code>

<code>// ShaderBlur</code>

<code>02</code>

<code>03</code>

<code>class</code> <code>SpriteBlur : </code><code>public</code> <code>CCSprite</code>

<code>04</code>

<code>{</code>

<code>05</code>

<code>public</code><code>:</code>

<code>06</code>

<code>    </code><code>~SpriteBlur();</code>

<code>07</code>

<code>    </code><code>void</code> <code>setBlurSize(</code><code>float</code> <code>f);</code>

<code>08</code>

<code>    </code><code>bool</code> <code>initWithTexture(CCTexture2D* texture, </code><code>const</code> <code>CCRect&amp;  rect);</code>

<code>09</code>

<code>    </code><code>void</code> <code>draw();</code>

<code>10</code>

<code>    </code><code>void</code> <code>initProgram();</code>

<code>11</code>

<code>    </code><code>void</code> <code>listenBackToForeground(CCObject *obj);</code>

<code>12</code>

<code>13</code>

<code>    </code><code>static</code> <code>SpriteBlur* create(</code><code>const</code> <code>char</code> <code>*pszFileName);</code>

<code>14</code>

<code>15</code>

<code>    </code><code>CCPoint blur_;</code>

<code>16</code>

<code>    </code><code>GLfloat    sub_[4];</code>

<code>17</code>

<code>18</code>

<code>    </code><code>GLuint    blurLocation;</code>

<code>19</code>

<code>    </code><code>GLuint    subLocation;</code>

<code>20</code>

<code>};</code>

实现:

<code>001</code>

<code>SpriteBlur::~SpriteBlur()</code>

<code>002</code>

<code>003</code>

<code>    </code><code>CCNotificationCenter::sharedNotificationCenter()-&gt;removeObserver(</code><code>this</code><code>, EVENT_COME_TO_FOREGROUND);</code>

<code>004</code>

<code>}</code>

<code>005</code>

<code>006</code>

<code>SpriteBlur* SpriteBlur::create(</code><code>const</code> <code>char</code> <code>*pszFileName)</code>

<code>007</code>

<code>008</code>

<code>    </code><code>SpriteBlur* pRet = </code><code>new</code> <code>SpriteBlur();</code>

<code>009</code>

<code>    </code><code>if</code> <code>(pRet &amp;&amp; pRet-&gt;initWithFile(pszFileName))</code>

<code>010</code>

<code>    </code><code>{</code>

<code>011</code>

<code>        </code><code>pRet-&gt;autorelease();</code>

<code>012</code>

<code>    </code><code>}</code>

<code>013</code>

<code>    </code><code>else</code>

<code>014</code>

<code>015</code>

<code>        </code><code>CC_SAFE_DELETE(pRet);</code>

<code>016</code>

<code>017</code>

<code>    </code> 

<code>018</code>

<code>    </code><code>return</code> <code>pRet;</code>

<code>019</code>

<code>020</code>

<code>021</code>

<code>void</code> <code>SpriteBlur::listenBackToForeground(CCObject *obj)</code>

<code>022</code>

<code>023</code>

<code>    </code><code>setShaderProgram(NULL);</code>

<code>024</code>

<code>    </code><code>initProgram();</code>

<code>025</code>

<code>026</code>

<code>027</code>

<code>bool</code> <code>SpriteBlur::initWithTexture(CCTexture2D* texture, </code><code>const</code> <code>CCRect&amp; rect)</code>

<code>028</code>

<code>029</code>

<code>    </code><code>if</code><code>( CCSprite::initWithTexture(texture, rect) ) </code>

<code>030</code>

<code>031</code>

<code>        </code><code>CCNotificationCenter::sharedNotificationCenter()-&gt;addObserver(</code><code>this</code><code>,</code>

<code>032</code>

<code>                                                                      </code><code>callfuncO_selector(SpriteBlur::listenBackToForeground),</code>

<code>033</code>

<code>                                                                      </code><code>EVENT_COME_TO_FOREGROUND,</code>

<code>034</code>

<code>                                                                      </code><code>NULL);</code>

<code>035</code>

<code>        </code> 

<code>036</code>

<code>        </code><code>CCSize s = getTexture()-&gt;getContentSizeInPixels();</code>

<code>037</code>

<code>038</code>

<code>        </code><code>blur_ = ccp(1/s.width, 1/s.height);</code>

<code>039</code>

<code>        </code><code>sub_[0] = sub_[1] = sub_[2] = sub_[3] = 0;</code>

<code>040</code>

<code>041</code>

<code>        </code><code>this</code><code>-&gt;initProgram();</code>

<code>042</code>

<code>043</code>

<code>        </code><code>return</code> <code>true</code><code>;</code>

<code>044</code>

<code>045</code>

<code>046</code>

<code>    </code><code>return</code> <code>false</code><code>;</code>

<code>047</code>

<code>048</code>

<code>049</code>

<code>void</code> <code>SpriteBlur::initProgram()</code>

<code>050</code>

<code>051</code>

<code>    </code><code>GLchar * fragSource = (GLchar*) CCString::createWithContentsOfFile(</code>

<code>052</code>

<code>                                </code><code>CCFileUtils::sharedFileUtils()-&gt;fullPathForFilename(</code><code>"Shaders/example_Blur.fsh"</code><code>).c_str())-&gt;getCString();</code>

<code>053</code>

<code>    </code><code>CCGLProgram* pProgram = </code><code>new</code> <code>CCGLProgram();</code>

<code>054</code>

<code>    </code><code>pProgram-&gt;initWithVertexShaderByteArray(ccPositionTextureColor_vert, fragSource);</code>

<code>055</code>

<code>    </code><code>setShaderProgram(pProgram);</code>

<code>056</code>

<code>    </code><code>pProgram-&gt;release();</code>

<code>057</code>

<code>058</code>

<code>    </code><code>CHECK_GL_ERROR_DEBUG();</code>

<code>059</code>

<code>060</code>

<code>    </code><code>getShaderProgram()-&gt;addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);</code>

<code>061</code>

<code>    </code><code>getShaderProgram()-&gt;addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);</code>

<code>062</code>

<code>    </code><code>getShaderProgram()-&gt;addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);</code>

<code>063</code>

<code>064</code>

<code>065</code>

<code>066</code>

<code>    </code><code>getShaderProgram()-&gt;link();</code>

<code>067</code>

<code>068</code>

<code>069</code>

<code>070</code>

<code>    </code><code>getShaderProgram()-&gt;updateUniforms();</code>

<code>071</code>

<code>072</code>

<code>073</code>

<code>074</code>

<code>    </code><code>subLocation = glGetUniformLocation( getShaderProgram()-&gt;getProgram(), </code><code>"substract"</code><code>);</code>

<code>075</code>

<code>    </code><code>blurLocation = glGetUniformLocation( getShaderProgram()-&gt;getProgram(), </code><code>"blurSize"</code><code>);</code>

<code>076</code>

<code>077</code>

<code>078</code>

<code>079</code>

<code>080</code>

<code>void</code> <code>SpriteBlur::draw()</code>

<code>081</code>

<code>082</code>

<code>    </code><code>ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex );</code>

<code>083</code>

<code>    </code><code>ccBlendFunc blend = getBlendFunc();</code>

<code>084</code>

<code>    </code><code>ccGLBlendFunc(blend.src, blend.dst);</code>

<code>085</code>

<code>086</code>

<code>    </code><code>getShaderProgram()-&gt;use();</code>

<code>087</code>

<code>    </code><code>getShaderProgram()-&gt;setUniformsForBuiltins();</code>

<code>088</code>

<code>    </code><code>getShaderProgram()-&gt;setUniformLocationWith2f(blurLocation, blur_.x, blur_.y);</code>

<code>089</code>

<code>    </code><code>getShaderProgram()-&gt;setUniformLocationWith4fv(subLocation, sub_, 1);</code>

<code>090</code>

<code>091</code>

<code>    </code><code>ccGLBindTexture2D( getTexture()-&gt;getName());</code>

<code>092</code>

<code>093</code>

<code>    </code><code>//</code>

<code>094</code>

<code>    </code><code>// Attributes</code>

<code>095</code>

<code>096</code>

<code>#define kQuadSize sizeof(m_sQuad.bl)</code>

<code>097</code>

<code>    </code><code>long</code> <code>offset = (</code><code>long</code><code>)&amp;m_sQuad;</code>

<code>098</code>

<code>099</code>

<code>    </code><code>// vertex</code>

<code>100</code>

<code>    </code><code>int</code> <code>diff = offsetof( ccV3F_C4B_T2F, vertices);</code>

<code>101</code>

<code>    </code><code>glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (</code><code>void</code><code>*) (offset + diff));</code>

<code>102</code>

<code>103</code>

<code>    </code><code>// texCoods</code>

<code>104</code>

<code>    </code><code>diff = offsetof( ccV3F_C4B_T2F, texCoords);</code>

<code>105</code>

<code>    </code><code>glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (</code><code>void</code><code>*)(offset + diff));</code>

<code>106</code>

<code>107</code>

<code>    </code><code>// color</code>

<code>108</code>

<code>    </code><code>diff = offsetof( ccV3F_C4B_T2F, colors);</code>

<code>109</code>

<code>    </code><code>glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (</code><code>void</code><code>*)(offset + diff));</code>

<code>110</code>

<code>111</code>

<code>112</code>

<code>    </code><code>glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);</code>

<code>113</code>

<code>114</code>

<code>    </code><code>CC_INCREMENT_GL_DRAWS(1);</code>

<code>115</code>

<code>116</code>

<code>117</code>

<code>void</code> <code>SpriteBlur::setBlurSize(</code><code>float</code> <code>f)</code>

<code>118</code>

<code>119</code>

<code>    </code><code>CCSize s = getTexture()-&gt;getContentSizeInPixels();</code>

<code>120</code>

<code>121</code>

<code>    </code><code>blur_ = ccp(1/s.width, 1/s.height);</code>

<code>122</code>

<code>    </code><code>blur_ = ccpMult(blur_,f);</code>

<code>123</code>

好了,直接copy到你的program里面,不过有一点需要注意,就是他这个只能用一个文件(图片)create,如果需要用一个Texture初始化(因为有时候需要模糊即时的sprite),可以稍微改装一下,加一个函数:

<code>1</code>

<code>static</code> <code>SpriteBlur* createWithTexture(CCTexture2D *pTexture);</code>

<code>SpriteBlur* SpriteBlur::createWithTexture(CCTexture2D *pTexture)</code>

<code>    </code><code>CCAssert(pTexture != NULL, </code><code>"Invalid texture for sprite"</code><code>);</code>

<code>    </code><code>CCRect rect = CCRectZero;</code>

<code>    </code><code>rect.size = pTexture-&gt;getContentSize();</code>

<code>    </code><code>if</code> <code>(pRet &amp;&amp; pRet-&gt;initWithTexture(pTexture,rect))</code>

用法:

<code>SpriteBlur *bluredSpr = SpriteBlur::createWithTexture(tex);</code>

<code>2</code>

<code>bluredSpr-&gt;setPosition(ccp(sz.width/2,sz.height/2));</code>

<code>3</code>

<code>bluredSpr-&gt;setBlurSize(0.9f); </code><code>// 这里稍微设小一点</code>

<code>4</code>

<code>addChild(bluredSpr);</code>

效果:

[cocos2d-x]对CCSprite进行高斯模糊

注意:

他需要一个fsh文件(具体看它的实现),似乎是叠texture用的,找到example_Blur.fsh放到你的Resources\Shaders目录下

本文转蓬莱仙羽51CTO博客,原文链接:http://blog.51cto.com/dingxiaowei/1366154,如需转载请自行联系原作者

继续阅读