一、封装工具类
Shader.h
Shader.cpp
ShaderNode.cpp
ShaderNode.h
使用方法如下:
auto sprite = ShaderSprite::create(......);
auto shader = Shader::createWithSrc(......);
shader->drawCallOnSprite = function; // 在Sprite的draw中执行的回调,一般就是gl call指令
shader->setUniformsAndAttribs = function; // 设置shader程序的uniform变量、attribute变量
// ******************* 方 法 一:设置Sprite的shader
// shader->setUniformsAndAttribs(); // 别忘了先设置好shader需要的数据
sprite->setMainShader(shader); // 设置sprite的Shader
// ******************* 方 法 二:给Sprite额外的shader,多个效果叠加
// 在Sprite的draw中,先执行zorder<0的shader,再执行sprite的shader,然后执行zorder>=0的shader
shader->setLocalZorder(...); // 设置zorder
sprite->addShader(shader); // 添加到队列中。
addChild(sprite);
二、多纹理(MultiTexture)
C++:
const auto textureFile1 = "Images/grossini_sister1.png";
const auto textureFile1 = "Images/grossini_sister2.png";
const auto vShaderFile = "shaders/multiTexture.vsh";
const auto fShaderFile = "shaders/multiTexture.fsh";
const auto winSize = Director::getInstance()->getWinSize();
auto texture1 = TextureCache::getInstance()->addImage(textureFile1);
auto texture2 = TextureCache::getInstance()->addImage(textureFile2);
auto sprite = Sprite::createWithTexture(texture1);
// autorelease对象。如果我们要直接访问program,要自己retain起来维护,
auto program = GLProgram::createWithFileNames(vShaderFile, fShaderFile);
// programState已经缓存,且缓存中通过cocos2d::Map retain住了program
// 因此program不会被销毁。programState也是autorelease对象,因此也要自己retain起来维护。
auto programState = GLProgramState::getOrCreateWithGLProgram(program);
float factor = 0.5f;
sprite->setPosition(Vec2(winSize.width>>1, winSize.height>>1));
addChild(sprite);
// 设置自定义的Shader
programState->retain(); // 我们自己retain起来,GLProgramStateCache可能会清掉它。
sprite->setProgramState(programState);
// 在程序中动态设置shader的uniform值
programState->setUniformFloat("factor", factor);
programState->setUniformTexture("texture1", texture2);
顶点着色器:
ccPositionTextureColor_noMVP_vert
// #include "renderer/ccShader_PositionTextureColor_noMVP.vert"
// Position Texture Color without MVP shader
//
// gl_Position = CC_PMatrix * a_position
// gl_FragColor = texutreColor * a_color
//
片段着色器:
uniform float factor;
uniform sampler2D texture1;
// 下面是GLProgram内部自动添加,对应Sprite::create(texture)里的texture
// uniform Sampler2D CC_Texture0;
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main(){
gl_FragColor = v_fragmentColor *
mix(texture2D(CC_Texture0, v_texCoord),
texture2D(texture1, v_texCoord),
factor);
}
三、Lens Flare:镜头光晕
C++:
const auto winSize = Director::getInstance()->getWinSize();
const auto frameSize = Director::getInstance()->getOpenGLView()->getFrameSize();
const auto visibleSize = Director::getInstance()->getVisibleSize();
const auto retinaFactor = Director::getInstance()->getOpenGLView()->getRetinaFactor();
const auto SizeX = 256;
const auto SizeY = 256;
const auto _resolution = Vec2( SizeX, SizeY );
auto shaderNode = NodeShader::createWithFile( "", "Shaders/shadertoy_LensFlare.fsh" );
auto position = Vec2( winSize.width / 2, winSize.height / 2 );
auto _center = Vec2( position.x * frameSize.width / visibleSize.width * retinaFactor,
position.y * frameSize.height / visibleSize.height * retinaFactor );
shaderNode->setAnchorPoint( Vec2( 0.5f, 0.5f ) );
shaderNode->setPosition( position );
shaderNode->setContentSize( winSize / 2 );
addChild( shaderNode );
shaderNode->setDrawCall(
[=]( GLProgramState * const programState, const Mat4 & transform, uint32_t flags ) {
GLfloat vertices[12] = { 0, 0,
SizeX, 0,
SizeX, SizeY,
0, 0,
0, SizeY,
SizeX, SizeY
};
programState->setUniformVec2( "resolution", _resolution );
programState->setUniformVec2( "center", _center );
programState->setVertexAttribPointer( "a_position", 2, GL_FLOAT, GL_FALSE, 0, ( GLvoid * ) vertices );
programState->apply( transform );
glDrawArrays( GL_TRIANGLES, 0, 6 );
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES( 1, 6 );
} );
顶点着色器:
ccPositionTextureColor_vert
// #include "renderer/ccShader_PositionTextureColor.vert"
// Position Texture Color shader
//
// gl_Position = CC_MVPMatrix * a_position(顶点数据传入的顶点坐标)
// gl_FragColor = texutreColor * a_color(顶点数据传入的color)
//
片段着色器:
uniform vec2 center;
uniform vec2 resolution;
//uniform float iChannelTime[4]; // channel playback time (in seconds)
//uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)
vec4 iMouse = vec4(0,0,0,0); // mouse pixel coords. xy: current (if MLB down), zw: click
//uniform sampler2D iChannel0; // input channel. XX = 2D/Cube
/*by musk License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
Trying to get some interesting looking lens flares.
13/08/13:
published
muuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuusk!*/
float noise(float t)
{
return 0.;
}
float noise(vec2 t)
{
return 0.;
}
vec3 lensflare(vec2 uv,vec2 pos)
{
vec2 main = uv-pos;
vec2 uvd = uv*(length(uv));
float ang = atan(main.x,main.y);
float dist=length(main); dist = pow(dist,.1);
float n = noise(vec2(ang*16.0,dist*32.0));
float f0 = 1.0/(length(uv-pos)*16.0+1.0);
f0 = f0+f0*(sin(noise((pos.x+pos.y)*2.2+ang*4.0+5.954)*16.0)*.1+dist*.1+.8);
float f1 = max(0.01-pow(length(uv+1.2*pos),1.9),.0)*7.0;
float f2 = max(1.0/(1.0+32.0*pow(length(uvd+0.8*pos),2.0)),.0)*00.25;
float f22 = max(1.0/(1.0+32.0*pow(length(uvd+0.85*pos),2.0)),.0)*00.23;
float f23 = max(1.0/(1.0+32.0*pow(length(uvd+0.9*pos),2.0)),.0)*00.21;
vec2 uvx = mix(uv,uvd,-0.5);
float f4 = max(0.01-pow(length(uvx+0.4*pos),2.4),.0)*6.0;
float f42 = max(0.01-pow(length(uvx+0.45*pos),2.4),.0)*5.0;
float f43 = max(0.01-pow(length(uvx+0.5*pos),2.4),.0)*3.0;
uvx = mix(uv,uvd,-.4);
float f5 = max(0.01-pow(length(uvx+0.2*pos),5.5),.0)*2.0;
float f52 = max(0.01-pow(length(uvx+0.4*pos),5.5),.0)*2.0;
float f53 = max(0.01-pow(length(uvx+0.6*pos),5.5),.0)*2.0;
uvx = mix(uv,uvd,-0.5);
float f6 = max(0.01-pow(length(uvx-0.3*pos),1.6),.0)*6.0;
float f62 = max(0.01-pow(length(uvx-0.325*pos),1.6),.0)*3.0;
float f63 = max(0.01-pow(length(uvx-0.35*pos),1.6),.0)*5.0;
vec3 c = vec3(.0);
c.r+=f2+f4+f5+f6; c.g+=f22+f42+f52+f62; c.b+=f23+f43+f53+f63;
c = c*1.3 - vec3(length(uvd)*.05);
c+=vec3(f0);
return c;
}
vec3 cc(vec3 color, float factor,float factor2) // color modifier
{
float w = color.x+color.y+color.z;
return mix(color,vec3(w)*factor,w*factor2);
}
void main(void)
{
vec2 iResolution = resolution; // viewport resolution (in pixels)
float iGlobalTime = CC_Time[1]; // shader playback time (in seconds)
//vec2 uv = gl_FragCoord.xy / iResolution.xy - 0.5;
vec2 uv = (gl_FragCoord.xy - center.xy) / iResolution.xy;
uv.x *= iResolution.x/iResolution.y; //fix aspect ratio
vec3 mouse = vec3(iMouse.xy/iResolution.xy - 0.5,iMouse.z-.5);
mouse.x *= iResolution.x/iResolution.y; //fix aspect ratio
if (iMouse.z<.5)
{
mouse.x=sin(iGlobalTime)*.5;
mouse.y=sin(iGlobalTime*.913)*.5;
}
vec3 color = vec3(1.4,1.2,1.0)*lensflare(uv,mouse.xy);
color -= noise(gl_FragCoord.xy)*.015;
color = cc(color,.5,.1);
gl_FragColor = vec4(color,1.0);
}
四、Gaussian blur:高斯模糊
C++:
auto blurShader = Shader::createWithSrc( ccPositionTextureColor_noMVP_vert, FileUtils::getInstance()->getStringFromFile( FileUtils::getInstance()->fullPathForFilename( "Shaders/example_Blur.fsh" ) ) );
auto programState = blurShader->getGLProgramState();
blurShader->drawCallOnSprite = [blurShader, programState](
cocos2d::Sprite * target,
cocos2d::Renderer * render,
const cocos2d::Mat4 & transform,
std::uint32_t flags,
float globalZOrder,
cocos2d::Texture2D * texture,
cocos2d::BlendFunc & blendFunc,
cocos2d::V3F_C4B_T2F_Quad * quad,
TrianglesCommand::Triangles * triangles )
{
blurShader->quadCommand.init( globalZOrder, texture->getName(), programState, blendFunc, quad, 1, transform, flags );
render->addCommand( &blurShader->quadCommand );
};
blurShader->setUniformsAndAttribs = [shaderSprite, programState]
{
Size size = shaderSprite->getTexture()->getContentSizeInPixels();
programState->setUniformVec2( "resolution", size );
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
programState->setUniformFloat( "blurRadius", 10 ); // 模板半径
programState->setUniformFloat( "sampleNum", 5 ); // 采样数
#endif
};
顶点着色器:
ccPositionTextureColor_noMVP_vert
// #include "renderer/ccShader_PositionTextureColor_noMVP.vert"
// Position Texture Color without MVP shader
//
// gl_Position = CC_PMatrix * a_position
// gl_FragColor = texutreColor * a_color
//
片段着色器:
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform vec2 resolution;
uniform float blurRadius;
uniform float sampleNum;
vec4 blur(vec2);
void main(void)
{
vec4 col = blur(v_texCoord); //* v_fragmentColor.rgb;
gl_FragColor = vec4(col) * v_fragmentColor;
}
vec4 blur(vec2 p)
{
if (blurRadius > 0.0 && sampleNum > 1.0)
{
vec4 col = vec4(0);
vec2 unit = 1.0 / resolution.xy;
float r = blurRadius;
float sampleStep = r / sampleNum;
float count = 0.0;
for(float x = -r; x < r; x += sampleStep)
{
for(float y = -r; y < r; y += sampleStep)
{
float weight = (r - abs(x)) * (r - abs(y));
col += texture2D(CC_Texture0, p + vec2(x * unit.x, y * unit.y)) * weight;
count += weight;
}
}
return col / count;
}
return texture2D(CC_Texture0, p);
}
五、heart:心跳
C++:
const auto winSize = Director::getInstance()->getWinSize();
const auto frameSize = Director::getInstance()->getOpenGLView()->getFrameSize();
const auto visibleSize = Director::getInstance()->getVisibleSize();
const auto retinaFactor = Director::getInstance()->getOpenGLView()->getRetinaFactor();
const auto SizeX = 256;
const auto SizeY = 256;
const auto _resolution = Vec2( SizeX, SizeY );
auto shaderNode = NodeShader::createWithFile( "", "Shaders/example_Heart.fsh" );
auto position = Vec2( winSize.width / 2, winSize.height / 2 );
auto _center = Vec2( position.x * frameSize.width / visibleSize.width * retinaFactor,
position.y * frameSize.height / visibleSize.height * retinaFactor );
shaderNode->setAnchorPoint( Vec2( 0.5f, 0.5f ) );
shaderNode->setPosition( position );
shaderNode->setContentSize( winSize / 2 );
addChild( shaderNode );
shaderNode->setDrawCall(
[ = ]( GLProgramState * const programState, const Mat4 & transform, uint32_t flags )
{
GLfloat vertices[12] = { 0, 0,
SizeX, 0,
SizeX, SizeY,
0, 0,
0, SizeY,
SizeX, SizeY
};
programState->setUniformVec2( "resolution", _resolution );
programState->setUniformVec2( "center", _center );
programState->setVertexAttribPointer( "a_position", 2, GL_FLOAT, GL_FALSE, 0, ( GLvoid * ) vertices );
programState->apply( transform );
glDrawArrays( GL_TRIANGLES, 0, 6 );
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES( 1, 6 );
} );
顶点着色器:
ccPositionTextureColor_vert
// #include "renderer/ccShader_PositionTextureColor.vert"
// Position Texture Color shader
//
// gl_Position = CC_MVPMatrix * a_position(顶点数据传入的顶点坐标)
// gl_FragColor = texutreColor * a_color(顶点数据传入的color)
//
片段着色器:
// Shader from http://www.iquilezles.org/apps/shadertoy/
#ifdef GL_ES
precision highp float;
#endif
uniform vec2 center;
uniform vec2 resolution;
void main(void)
{
float time = CC_Time[1];
vec2 p = 2.0 * (gl_FragCoord.xy - center.xy) / resolution.xy;
// animate
float tt = mod(time,2.0)/2.0;
float ss = pow(tt,.2)*0.5 + 0.5;
ss -= ss*0.2*sin(tt*6.2831*5.0)*exp(-tt*6.0);
p *= vec2(0.5,1.5) + ss*vec2(0.5,-0.5);
float a = atan(p.x,p.y)/3.141593;
float r = length(p);
// shape
float h = abs(a);
float d = (13.0*h - 22.0*h*h + 10.0*h*h*h)/(6.0-5.0*h);
// color
float f = step(r,d) * pow(1.0-r/d,0.25);
gl_FragColor = vec4(f,0.0,0.0,1.0);
}
六、Glow:荧光
C++:
const auto winSize = Director::getInstance()->getWinSize();
const auto frameSize = Director::getInstance()->getOpenGLView()->getFrameSize();
const auto visibleSize = Director::getInstance()->getVisibleSize();
const auto retinaFactor = Director::getInstance()->getOpenGLView()->getRetinaFactor();
const auto SizeX = 256;
const auto SizeY = 256;
const auto _resolution = Vec2( SizeX, SizeY );
auto shaderNode = NodeShader::createWithFile( "", "Shaders/shadertoy_Glow.fsh" );
auto position = Vec2( winSize.width / 2, winSize.height / 2 );
auto _center = Vec2( position.x * frameSize.width / visibleSize.width * retinaFactor,
position.y * frameSize.height / visibleSize.height * retinaFactor );
shaderNode->setAnchorPoint( Vec2( 0.5f, 0.5f ) );
shaderNode->setPosition( position );
shaderNode->setContentSize( winSize / 2 );
addChild( shaderNode );
shaderNode->setDrawCall(
[ = ]( GLProgramState * const programState, const Mat4 & transform, uint32_t flags )
{
GLfloat vertices[12] = { 0, 0,
SizeX, 0,
SizeX, SizeY,
0, 0,
0, SizeY,
SizeX, SizeY
};
programState->setUniformVec2( "resolution", _resolution );
programState->setUniformVec2( "center", _center );
programState->setVertexAttribPointer( "a_position", 2, GL_FLOAT, GL_FALSE, 0, ( GLvoid * ) vertices );
programState->apply( transform );
glDrawArrays( GL_TRIANGLES, 0, 6 );
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES( 1, 6 );
} );
顶点着色器:
ccPositionTextureColor_vert
// #include "renderer/ccShader_PositionTextureColor.vert"
// Position Texture Color shader
//
// gl_Position = CC_MVPMatrix * a_position(顶点数据传入的顶点坐标)
// gl_FragColor = texutreColor * a_color(顶点数据传入的color)
//
片段着色器:
uniform vec2 center;
uniform vec2 resolution;
//uniform float iChannelTime[4]; // channel playback time (in seconds)
//uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)
vec4 iMouse = vec4(0,0,0,0); // mouse pixel coords. xy: current (if MLB down), zw: click
//uniform sampler2D iChannel0; // input channel. XX = 2D/Cube
void main(void)
{
vec2 iResolution = resolution; // viewport resolution (in pixels)
float iGlobalTime = CC_Time[1]; // shader playback time (in seconds)
float pointRadius = 0.06;
float linkSize = 0.04;
float noiseStrength = 0.08; // range: 0-1
float minDimension = min(iResolution.x, iResolution.y);
vec2 bounds = vec2(iResolution.x / minDimension, iResolution.y / minDimension);
//vec2 uv = gl_FragCoord.xy / minDimension;
vec2 uv = (2. * gl_FragCoord.xy - center.xy) / iResolution.xy;
vec3 pointR = vec3(0.0, 0.0, 1.0);
vec3 pointG = vec3(0.0, 0.0, 1.0);
vec3 pointB = vec3(0.0, 0.0, 1.0);
// Make the points orbit round the origin in 3 dimensions.
// Coefficients are arbitrary to give different behaviours.
// The Z coordinate should always be >0.0, as it's used directly to
// multiply the radius to give the impression of depth.
pointR.x += 0.32 * sin(1.32 * iGlobalTime);
pointR.y += 0.3 * sin(1.03 * iGlobalTime);
pointR.z += 0.4 * sin(1.32 * iGlobalTime);
pointG.x += 0.31 * sin(0.92 * iGlobalTime);
pointG.y += 0.29 * sin(0.99 * iGlobalTime);
pointG.z += 0.38 * sin(1.24 * iGlobalTime);
pointB.x += 0.33 * sin(1.245 * iGlobalTime);
pointB.y += 0.3 * sin(1.41 * iGlobalTime);
pointB.z += 0.41 * sin(1.11 * iGlobalTime);
// Centre the points in the display
vec2 midUV = vec2(bounds.x * 0.5, bounds.y * 0.5);
pointR.xy += midUV;
pointG.xy += midUV;
pointB.xy += midUV;
// Calculate the vectors from the current fragment to the coloured points
vec2 vecToR = pointR.xy - uv;
vec2 vecToG = pointG.xy - uv;
vec2 vecToB = pointB.xy - uv;
vec2 dirToR = normalize(vecToR.xy);
vec2 dirToG = normalize(vecToG.xy);
vec2 dirToB = normalize(vecToB.xy);
float distToR = length(vecToR);
float distToG = length(vecToG);
float distToB = length(vecToB);
// Calculate the dot product between vectors from the current fragment to each pair
// of adjacent coloured points. This helps us determine how close the current fragment
// is to a link between points.
float dotRG = dot(dirToR, dirToG);
float dotGB = dot(dirToG, dirToB);
float dotBR = dot(dirToB, dirToR);
// Start with a bright coloured dot around each point
gl_FragColor.x = 1.0 - smoothstep(distToR, 0.0, pointRadius * pointR.z);
gl_FragColor.y = 1.0 - smoothstep(distToG, 0.0, pointRadius * pointG.z);
gl_FragColor.z = 1.0 - smoothstep(distToB, 0.0, pointRadius * pointB.z);
gl_FragColor.w = 1.0;
// We want to show a coloured link between adjacent points.
// Determine the strength of each link at the current fragment.
// This tends towards 1.0 as the vectors to each point tend towards opposite directions.
float linkStrengthRG = 1.0 - smoothstep(dotRG, -1.01, -1.0 + (linkSize * pointR.z * pointG.z));
float linkStrengthGB = 1.0 - smoothstep(dotGB, -1.01, -1.0 + (linkSize * pointG.z * pointB.z));
float linkStrengthBR = 1.0 - smoothstep(dotBR, -1.01, -1.0 + (linkSize * pointB.z * pointR.z));
// If the current fragment is in a link, we need to know how much the
// linked points contribute of their colour.
float sumDistRG = distToR + distToG;
float sumDistGB = distToG + distToB;
float sumDistBR = distToB + distToR;
float contribRonRG = 1.0 - (distToR / sumDistRG);
float contribRonBR = 1.0 - (distToR / sumDistBR);
float contribGonRG = 1.0 - (distToG / sumDistRG);
float contribGonGB = 1.0 - (distToG / sumDistGB);
float contribBonGB = 1.0 - (distToB / sumDistGB);
float contribBonBR = 1.0 - (distToB / sumDistBR);
// Additively blend the link colours into the fragment.
gl_FragColor.x += (linkStrengthRG * contribRonRG) + (linkStrengthBR * contribRonBR);
gl_FragColor.y += (linkStrengthGB * contribGonGB) + (linkStrengthRG * contribGonRG);
gl_FragColor.z += (linkStrengthBR * contribBonBR) + (linkStrengthGB * contribBonGB);
// Use an underlying texture to provide some noise
float noiseMin = 1.0 - noiseStrength;
gl_FragColor.xyz *= (1.0 - noiseStrength) + (noiseStrength * 0.);
}
七、outLine:描边
C++
#define getFileData(a) FileUtils::getInstance()->getStringFromFile(FileUtils::getInstance()->fullPathForFilename(a))
auto outlineShader = Shader::createWithSrc( ccPositionTextureColor_noMVP_vert, getFileData( "Shaders/example_Outline.fsh" ) );
auto programState = outlineShader->getGLProgramState();
outlineShader->drawCallOnSprite = [outlineShader, programState](
cocos2d::Sprite * target,
cocos2d::Renderer * render,
const cocos2d::Mat4 & transform,
std::uint32_t flags,
float globalZOrder,
cocos2d::Texture2D * texture,
cocos2d::BlendFunc & blendFunc,
cocos2d::V3F_C4B_T2F_Quad * quad,
cocos2d::TrianglesCommand::Triangles * triangles )
{
outlineShader->quadCommand.init( globalZOrder, texture->getName(), programState, blendFunc, quad, 1, transform, flags );
render->addCommand( &outlineShader->quadCommand );
};
outlineShader->setUniformsAndAttribs = [programState]
{
Vec3 color( 1.0f, 0.2f, 0.3f );
GLfloat radius = 0.01f;
GLfloat threshold = 1.75;
programState->setUniformVec3( "u_outlineColor", color );
programState->setUniformFloat( "u_radius", radius );
programState->setUniformFloat( "u_threshold", threshold );
};
顶点着色器
ccPositionTextureColor_noMVP_vert
片段着色器
/*
Created by guanghui on 4/8/14.
http://www.idevgames.com/forums/thread-3010.html
*/
varying vec2 v_texCoord;
varying vec4 v_fragmentColor;
uniform vec3 u_outlineColor;
uniform float u_threshold;
uniform float u_radius;
void main()
{
float radius = u_radius;
vec4 accum = vec4(0.0);
vec4 normal = vec4(0.0);
normal = texture2D(CC_Texture0, vec2(v_texCoord.x, v_texCoord.y));
accum += texture2D(CC_Texture0, vec2(v_texCoord.x - radius, v_texCoord.y - radius));
accum += texture2D(CC_Texture0, vec2(v_texCoord.x + radius, v_texCoord.y - radius));
accum += texture2D(CC_Texture0, vec2(v_texCoord.x + radius, v_texCoord.y + radius));
accum += texture2D(CC_Texture0, vec2(v_texCoord.x - radius, v_texCoord.y + radius));
accum *= u_threshold;
accum.rgb = u_outlineColor * accum.a;
accum.a = 1.0;
normal = ( accum * (1.0 - normal.a)) + (normal * normal.a);
gl_FragColor = v_fragmentColor * normal;
}
八、noise:噪声点
C++
auto noiseShader = Shader::createWithSrc( ccPositionTextureColor_noMVP_vert,
FileUtils::getInstance()->getStringFromFile(
FileUtils::getInstance()->fullPathForFilename( "Shaders/example_Noisy.fsh" ) ) );
auto programState = noiseShader->getGLProgramState();
noiseShader->drawCallOnSprite = [noiseShader, programState](
cocos2d::Sprite * target,
cocos2d::Renderer * render,
const cocos2d::Mat4 & transform,
std::uint32_t flags,
float globalZOrder,
cocos2d::Texture2D * texture,
cocos2d::BlendFunc & blendFunc,
cocos2d::V3F_C4B_T2F_Quad * quad,
cocos2d::TrianglesCommand::Triangles * triangles )
{
noiseShader->quadCommand.init( globalZOrder, texture->getName(), programState, blendFunc, quad, 1, transform, flags );
render->addCommand( &noiseShader->quadCommand );
};
noiseShader->setUniformsAndAttribs = [ = ]
{
auto s = shaderSprite->getTexture()->getContentSizeInPixels();
programState->setUniformVec2( "resolution", Vec2( s.width, s.height ) );
}
顶点着色器
ccPositionTextureColor_noMVP_vert
片段着色器
// Shader taken from: http://webglsamples.googlecode.com/hg/electricflower/electricflower.html
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform vec2 resolution;
const float intensity = 0.05;
vec3 noise(vec2 uv)
{
vec2 p = abs(sin(uv * 13.0 + uv.x * CC_Time[1] * sin(uv.y)));
return vec3(sin (0.2 * CC_Time[1] + sin(p * 0.5) * CC_Time[1] / cos(50.0)) * 10.0,0.3+0.5 * abs(sin(CC_Time[1] * tan(5.0))));
}
void main(void)
{
gl_FragColor.xyz = intensity * noise(gl_FragCoord.xy / sin(resolution.xy * CC_Time[1] * 0.01)) + (1. - intensity) *
texture2D(CC_Texture0,v_texCoord.xy).xyz;
gl_FragColor.w = 1.;
}
九、边缘检测
C++
auto edgeDetectShader = Shader::createWithSrc( ccPositionTextureColor_noMVP_vert,
FileUtils::getInstance()->getStringFromFile(
FileUtils::getInstance()->fullPathForFilename( "Shaders/example_EdgeDetection.fsh" ) ) );
auto programState = edgeDetectShader->getGLProgramState();
edgeDetectShader->drawCallOnSprite = [edgeDetectShader, programState](
cocos2d::Sprite * target,
cocos2d::Renderer * render,
const cocos2d::Mat4 & transform,
std::uint32_t flags,
float globalZOrder,
cocos2d::Texture2D * texture,
cocos2d::BlendFunc & blendFunc,
cocos2d::V3F_C4B_T2F_Quad * quad,
cocos2d::TrianglesCommand::Triangles * triangles )
{
edgeDetectShader->quadCommand.init( globalZOrder, texture->getName(), programState, blendFunc, quad, 1, transform, flags );
render->addCommand( &edgeDetectShader->quadCommand );
};
noiseShader->setUniformsAndAttribs = [ = ]
{
auto s = shaderSprite->getTexture()->getContentSizeInPixels();
programState->setUniformVec2( "resolution", Vec2( s.width, s.height ) );
};
顶点着色器
ccPositionTextureColor_noMVP_vert
片段着色器
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform vec2 resolution;
float lookup(vec2 p, float dx, float dy)
{
vec2 uv = p.xy + vec2(dx , dy ) / resolution.xy;
vec4 c = texture2D(CC_Texture0, uv.xy);
return 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;
}
void main(void)
{
vec2 p = v_texCoord.xy;
// simple sobel edge detection
float gx = 0.0;
gx += -1.0 * lookup(p, -1.0, -1.0);
gx += -2.0 * lookup(p, -1.0, 0.0);
gx += -1.0 * lookup(p, -1.0, 1.0);
gx += 1.0 * lookup(p, 1.0, -1.0);
gx += 2.0 * lookup(p, 1.0, 0.0);
gx += 1.0 * lookup(p, 1.0, 1.0);
float gy = 0.0;
gy += -1.0 * lookup(p, -1.0, -1.0);
gy += -2.0 * lookup(p, 0.0, -1.0);
gy += -1.0 * lookup(p, 1.0, -1.0);
gy += 1.0 * lookup(p, -1.0, 1.0);
gy += 2.0 * lookup(p, 0.0, 1.0);
gy += 1.0 * lookup(p, 1.0, 1.0);
float g = gx*gx + gy*gy;
gl_FragColor.xyz = vec3(1.-g);
gl_FragColor.w = 1.;
}
十、GrayScale:灰度图
C++
auto grayScaleShader = Shader::createWithSrc( ccPositionTextureColor_noMVP_vert,
FileUtils::getInstance()->getStringFromFile(
FileUtils::getInstance()->fullPathForFilename( "Shaders/example_GreyScale.fsh" ) ) );
auto programState = grayScaleShader->getGLProgramState();
grayScaleShader->drawCallOnSprite = [grayScaleShader, programState](
cocos2d::Sprite * target,
cocos2d::Renderer * render,
const cocos2d::Mat4 & transform,
std::uint32_t flags,
float globalZOrder,
cocos2d::Texture2D * texture,
cocos2d::BlendFunc & blendFunc,
cocos2d::V3F_C4B_T2F_Quad * quad,
cocos2d::TrianglesCommand::Triangles * triangles )
{
grayScaleShader->quadCommand.init( globalZOrder, texture->getName(), programState, blendFunc, quad, 1, transform, flags );
render->addCommand( &grayScaleShader->quadCommand );
};
grayScaleShader->setUniformsAndAttribs = [ = ]
{
auto s = shaderSprite->getTexture()->getContentSizeInPixels();
programState->setUniformVec2( "resolution", Vec2( s.width, s.height ) );
};
顶点着色器
ccPositionTextureColor_noMVP_vert
片段着色器
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main(void)
{
vec4 c = texture2D(CC_Texture0, v_texCoord);
gl_FragColor.xyz = vec3(0.2126*c.r + 0.7152*c.g + 0.0722*c.b);
gl_FragColor.w = c.w;
}