从零开始shader系列,做个火焰形状的人物描边
准备场景,准备一张图摆上
搞一个空shader,创建材质都给上,搞几个变量放上去,一会要用
CCEffect段
CCEffect %{
techniques:
- passes:
- vert: vs
frag: fs
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
texture: { value: white }
noiseTex: { value: white }
color1 : { value : [0.88,0.29,0.16,1.], editor: { type: "color" } }
color2 : { value : [0.96,0.92,0.45,1.], editor: { type: "color" } }
speed1 : { value : [1.0,1.0,1.0,1.0,] }
speed2 : { value : [1.0,1.0,1.0,1.0,] }
}%
fs代码段
CCProgram fs %{
precision mediump float;
uniform sampler2D texture;
uniform sampler2D noiseTex;
uniform sampler2D fireTex;
uniform Constants {
vec4 color1;
vec4 color2;
vec4 speed1;
vec4 speed2;
};
varying mediump vec2 v_uv0;
varying lowp vec4 v_color;
#include <cc-global>
// 先不要管这里的参数和函数名,备用的,先占位
vec4 fragFire(vec2 uv,vec4 mc,vec2 move,vec2 offmul){
vec4 color = vec4(vec3(0.),1.);
return color;
}
void main() {
float time = cc_time.x;
vec2 uv = v_uv0;
// 先不要管这里的参数和函数名,备用的,先占位
vec4 f1 = fragFire(uv,color1,vec2(0.),vec2(0.));
vec4 colorfire = vec4(f1);
gl_FragColor = colorfire;
}
}%
好了,图黑了!
做一个描边先
vec4 fragFire(vec2 uv,vec4 mc,vec2 move,vec2 offmul){
vec4 color = vec4(vec3(0.),1.);
// 图片取样
vec4 tex3 = texture2D(texture, uv);
// 用传进来的颜色做一个纯色的角色图 透明度用取样取到的放大后的角色图的透明度
color.xyz = mc.xyz;
color.a = tex3.a;
return color;
}
void main() {
float time = cc_time.x;
vec2 uv = v_uv0;
// *.97 + 0.15 给图片做缩放同时矫正位置到中心
// 作用是让纯色图比原图要大一点
vec4 f1 = fragFire(uv* .97 + .015,color1,vec2(0.),vec2(0.));
vec4 colorfire = vec4(f1);
gl_FragColor = colorfire;
}
}%
加一张新图放上去看下,确实是变大了哈
题外话,之前一直在试各种办法做个好看点的外发光shader,各种做法都试了,居然没想到放大一下就完了。。。
我要边缘看起来像火苗
放下噪声图
vec4 fragFire(vec2 uv,vec4 mc,vec2 move,vec2 offmul){
vec4 color = vec4(vec3(0.),1.);
// uv*6 不然噪声图纹理太粗 不像火焰的细纹理
vec4 tex1 = texture2D(noiseTex, uv * 6.);
// 用噪声图取样随机值 给纹理偏移
vec2 off = tex1.xy ;
// offmul 噪声图取值的缩放倍数
vec4 tex3 = texture2D(texture, uv + off * offmul);
color.xyz = mc.xyz;
color.a = tex3.a;
return color;
}
void main() {
float time = cc_time.x;
vec2 uv = v_uv0;
// *.97 + 0.15 给图片做缩放同时矫正位置到中心
// 修改了offmul值为vec2(0.,0.03)
// offmul.x = 0 所以x轴方向不加扰动,制作y轴效果
vec4 f1 = fragFire(uv* .97 + .015,color1,vec2(0.),vec2(0.,0.03));
vec4 colorfire = vec4(f1);
gl_FragColor = colorfire;
}
}%
一层不好看,再来一层
void main() {
float time = cc_time.x;
vec2 uv = v_uv0;
// *.97 + 0.15 给图片做缩放同时矫正位置到中心
vec4 f1 = fragFire(uv* .97 + .015,color1,vec2(0.),vec2(0.,0.03));
// 第二层缩放*99 和第一层大小不一致,noise缩放也不一致,所以两层描边的大小是不一样的
vec4 f2 = fragFire(uv* .99 + .005,color2,vec2(0.),vec2(0.,0.015));
vec4 color = mix(f1,f2,f2.a);
float a = f1.a + f2.a;
vec4 colorfire = vec4(color.xyz,a);
gl_FragColor = colorfire;
}
}%
动起来
直接放最终代码了哈
CCEffect %{
techniques:
- passes:
- vert: vs
frag: fs
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
texture: { value: white }
noiseTex: { value: white }
color1 : { value : [0.88,0.29,0.16,1.], editor: { type: "color" } }
color2 : { value : [0.96,0.92,0.45,1.], editor: { type: "color" } }
speed1 : { value : [1.0,1.0,1.0,1.0,] }
speed2 : { value : [1.0,1.0,1.0,1.0,] }
}%
CCProgram vs %{
precision highp float;
#include <cc-global>
#include <cc-local>
attribute vec3 a_position;
attribute lowp vec4 a_color;
attribute mediump vec2 a_uv0;
varying mediump vec2 v_uv0;
varying lowp vec4 v_color;
varying lowp vec4 v_wp;
void main () {
mat4 mvp;
mvp = cc_matViewProj;
v_color = a_color;
gl_Position = mvp * vec4(a_position, 1);
v_wp = cc_matWorld * vec4(a_position, 1);
v_uv0 = a_uv0;
}
}%
CCProgram fs %{
precision mediump float;
uniform sampler2D texture;
uniform sampler2D noiseTex;
uniform sampler2D fireTex;
uniform Constants {
vec4 color1;
vec4 color2;
vec4 speed1;
vec4 speed2;
};
varying mediump vec2 v_uv0;
varying lowp vec4 v_color;
varying lowp vec4 v_wp;
#include <cc-global>
// offmul 取样的随机数的缩放倍数
// move 火焰抖动幅度 cc_time.x * speed 时间乘速度等于距离
// mc 火焰颜色
vec4 fragFire(vec2 uv,vec4 mc,vec2 move,vec2 offmul){
vec4 color = vec4(0.);
// *6 不然噪声图纹理太粗 不像火焰的细纹理
vec4 tex1 = texture2D(noiseTex, uv * 6. + move);
// 用噪声图取样随机值 给纹理偏移
vec2 off = tex1.xy ;
// off的取值0-1 减去0.5 让值范围变到 -0.5-0.5 效果比之前好看点
off -= .5;
vec4 tex3 = texture2D(texture, uv + off * offmul);
color.xyz = mc.xyz;
color.a = tex3.a;
return color;
}
void main() {
vec2 uv;
vec4 color;
float time = cc_time.x;
uv = v_uv0;
// *.97 + 0.15 给图片做缩放同时矫正位置到中心
vec4 f1 = fragFire(uv* .97 + .015,color1,time * speed1.xy,vec2(0.,0.03));
vec4 f2 = fragFire(uv* .99 + .005,color2,time * speed2.xy,vec2(0.,0.015));
color = mix(f1,f2,f2.a);
float a = f1.a + f2.a;
vec4 colorfire = vec4(color.xyz,a);
// 直接对原图取样 也显示来 省的在创建个图盖上去了
vec4 tex = texture2D(texture, v_uv0);
gl_FragColor = mix(colorfire,tex,tex.a);
// v_color 就是编辑器面板上面能调整的那个颜色 乘了之后那个颜色才有用
gl_FragColor *= v_color;
}
}%
}%
放点别的噪声图和参数效果
vec4 f1 = fragFire(uv* .97 + .015,color1,time * speed1.xy,vec2(0.,0.86));
vec4 f2 = fragFire(uv* .99 + .005,color2,time * speed2.xy,vec2(0.,0.43));
总之吧,噪声图和参数不一样,会出来点奇奇怪怪的东西。。