为了可以直接利用数据,提高程序效率,我们不使用噪声函数来计算,而是利用预先生成好的一组噪声数据:
unsigned char perm[256] = {151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,
129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,
49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180};
这个数组就是一个二维的柏林噪声数据,可以直接拿这个数据来生成一张glowmap的灰度图~可以先渲染出这个噪声灰度图:
CCTexture2D *noise = new CCTexture2D();
noise->initWithData(perm, kCCTexture2DPixelFormat_A8, 16, 16, CCSizeMake(16, 16));
test->setTexture(noise);
rect.setRect(0, 0, noise->getContentSize().width, noise->getContentSize().height);
test->setTextureRect(rect);
我们既然做的是动态的流光效果,那么静止的发亮显然是不够的~为了能让这些亮斑动起来,我们使用UV动画。shader中在读取texture数据的时候,使用的是texture的UV坐标,即图片左上角为(0, 0),右下角为(1, 1)。所以只需要在读取texture数据的时候,把对应的坐标做变化即可~为了控制贴图按时间移动,用cocos添加的一个uniform变量CC_Time进行控制,简单修改fragment shader代码即可实现:
uniform sampler2D CC_Texture0;
uniform sampler2D u_Texture1;
uniform vec2 u_BlurDis;
varying vec4 v_Color;
varying vec2 v_TexCoord;
void main()
{
vec4 originColor = texture2D(CC_Texture0, v_TexCoord);
float per = fract(CC_Time.y * 0.3);
float x = v_TexCoord.x + per;
if (x > 1 ) { x = x - 1; }
float y = v_TexCoord.y + per;
if (y > 1 ) { y = y - 1; }
vec4 glowColor = texture2D(u_Texture1, vec2(x, y));
originColor.r = (originColor.r + glowColor.a) * originColor.a;
originColor.g = (originColor.g + glowColor.a) * originColor.a;
originColor.b = (originColor.b + glowColor.a) * originColor.a;
gl_FragColor = originColor;
}
为了可以在shader中读取噪声贴图,在C++代码中传入该贴图数据:
。。。
_uniforms[kUniformSampler1] = glGetUniformLocation(program->getProgram(), UniformSampler1);
。。。
glUniform1i(_uniforms[kUniformSampler1], 1);
。。。
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _texture1->getName());
代码中,fract函数是shader内置的函数,用于取小数点后面的部分。因为UV坐标区间为0~1,所以恰好利用时间的小数点后来做UV移动的动画效果~因为UV坐标的从水平和竖直方向上都有等量的增加,所以流光的移动也以45度方向进行。最终效如下: