creator shader:从零开始,用shader画个彩虹

creator shader:从零开始,用shader画个彩虹

从创建shader和材质开始

分别创建名为 rainbow的effect和material,创建一个场景,新建一张Sprite精灵,使用我们创建出来的rainbow材质,替换掉Sprite精灵的默认材质。

在这里插入图片描述

在这里插入图片描述

点击新建的材质,这里的effect 选择改为 新建的rainbow

在这里插入图片描述

此时应用按钮高亮,点击应用

在这里插入图片描述

使用我们创建出来的rainbow材质,替换掉Sprite精灵的默认材质。

给图片上色

修改片元着色器的代码,

  void main () {
    vec4 o = vec4(1, 1, 1, 1);

    #if USE_TEXTURE
      CCTexture(texture, v_uv0, o);
    #endif

    o *= v_color;

    ALPHA_TEST(o);

    gl_FragColor = o;
  }

删掉,改成


  void main () {
    // color 是三个浮点数的向量,三个分量可以使用color.x color.y color.z分别访问
    // 也可以color.xy color.xz 作为 vec2 随意组合访问
    // xyz访问的分别是第1,2,3个分量,也可以使用rgb分别访问1,2,3三个分量,没有区别
    // 作为color使用,1,2,3三个分量带别的分别是颜色的红绿蓝三色,三个颜色组合成任意颜色
    // 0.,1.,0. 是红色0 绿色1 蓝色0,最终色是 红色
    vec3 color = vec3(0.,1.,0.);

	// gl_FragColor是最终决定每个像素的颜色的值,
	// vec4.xyz 使用上面的color的值,vec4.w 是1.,这个值得意义是透明度,设为1
    vec4 o = vec4(color, 1);
    gl_FragColor = o;
  }

切换到creator面板,看一下我们上色的结果

图片画个圆

  void main () {
    // color 是三个浮点数的向量,三个分量可以使用color.x color.y color.z分别访问
    // 也可以color.xy color.xz 作为 vec2 随意组合访问
    // xyz访问的分别是第1,2,3个分量,也可以使用rgb分别访问1,2,3三个分量,没有区别
    // 作为color使用,1,2,3三个分量带别的分别是颜色的红绿蓝三色,三个颜色组合成任意颜色
    // 0.,1.,0. 是红色0 绿色1 蓝色0,最终色是 红色
    vec3 color = vec3(0.,1.,0.);

    vec2 point = vec2(.5,0.);

    // distance 计算两点距离 这里的point事边缘的中心点,v_uv0是每个像素对应的uv坐标
    float mul = distance(v_uv0,point);
    // step函数,参数1 > 参数2 返回0,否则返回1
    // 这里用step来处理mul,使距离小于0.5的返回值1,大于0.5返回值0
    mul = step(mul,.5);

    // color * mul 对距离在0.5内的像素点,*= 1,颜色值不变,>0.5 时*= 0,使颜色变黑色
    // 结果就是一个圆
    color *= mul;

    // gl_FragColor是最终决定每个像素的颜色的值,
	// vec4.xyz 使用上面的color的值,vec4.w 是1.,这个值得意义是透明度,设为1
    vec4 o = vec4(color, 1);
    gl_FragColor = o;
  }

在这里插入图片描述

mul = step(mul,.5)改成mul=step(mul,.4) 嘿嘿,画个半径0.4的圆

在这里插入图片描述

后面的套路你已经猜出来了!mul = step(distance(v_uv0,point),.5) - step(distance(v_uv0,point),.4);
大圆-小圆=

在这里插入图片描述

把画半圆封装成一个函数吧

  float drawHalfCircle(vec2 center,vec2 uv,float radius) {

    float mul = distance(uv,center);
    mul = step(mul,radius);

    return mul;
  }
  
  
  // 参数: center 圆心
  // uv 像素点坐标
  // radius 圆半径
  // width 线宽
  float drawHalfCircleLine(vec2 center,vec2 uv,float radius,float width) {
    float c1 = drawHalfCircle(center,uv,radius);
    float c2 = drawHalfCircle(center,uv,radius - width);
    return c1 - c2;
  }
  
  void main () {
// 省略重复的代码  .......
    float circleline = drawHalfCircleLine(point,v_uv0,0.5,0.05);
    float ret = circleline;
    color = vec3(0.,1.,0.) * ret;
// 省略重复的代码  .......
  }  

在这里插入图片描述

画彩虹?

    float circleline1 = drawHalfCircleLine(point,v_uv0,0.5,0.05);
    float circleline2 = drawHalfCircleLine(point,v_uv0,0.45,0.05);
    float circleline3 = drawHalfCircleLine(point,v_uv0,0.4,0.05);

    vec3 colorred = vec3(1.,0.,0.);
    vec3 colorgreen = vec3(0.,1.,0.);
    vec3 colorblue = vec3(0.,0.,1.);
    
    vec3 ret = circleline1 * colorred
      + circleline2 * colorgreen
      + circleline3 * colorblue;
    
    color = ret;

在这里插入图片描述

颜色你再调调吧。

边缘有锯齿?

  float drawHalfCircle(vec2 center,vec2 uv,float radius) {

    float dis = distance(uv,center);
    // dis = step(dis,radius);
    dis = smoothstep(radius,radius -.005,dis);

    return dis;
  }

drawHalfCircle函数换成上面的再看下。

在这里插入图片描述

挺好。smoothstep下回再聊。

哎转一下转两下,调调圆心坐标试一下。


其他文章:




creator shader:从零开始 第二篇,做个动态的光影



贴一下公众号

72赞

厉害了,大佬!正准备看!

作业已抄完!

哇哇,大佬继续不要停!


补充几句:
别把这当做对图片范围上色啊,片元着色器是对每一个像素点进行计算的,例如
渲染区域为(0, 0, 1280, 574) 这么大,那么,gl_Fragment 的x分量 范围就在0~1280之间, y分量就在0~574之间
对一个像素点来说,如gl_Fragment.xy = 200,200 v_uv0就是 vec2(200./1280.,200./574.)
对一个像素点的计算,

    float circleline1 = drawHalfCircleLine(point,v_uv0,0.5,0.05);
    float circleline2 = drawHalfCircleLine(point,v_uv0,0.45,0.05);
    float circleline3 = drawHalfCircleLine(point,v_uv0,0.4,0.05);

    vec3 colorred = vec3(1.,0.,0.);
    vec3 colorgreen = vec3(0.,1.,0.);
    vec3 colorblue = vec3(0.,0.,1.);
    
    vec3 ret = circleline1 * colorred
      + circleline2 * colorgreen
      + circleline3 * colorblue;

对一个点来说,上面的三条线计算中,只可能有一条线的值是1,其他的都是0,或没有1全0
比如计算出点在line1范围内,circleline1值1.,其他lin2 line3 值都是0
结果就是 red * 1 + green * 0 + blue * 0,最终200,200的点的颜色值为 red * 1 + 0 + 0红色

如果计算出点不在三条线任一范围内,结果就是 red0+green0+blue*0 = 0 黑色
glsl gl_FragCoord 与 屏幕关系

流啤,这么棒的教程必须给大佬顶一下

抄作业 抄作业!谢谢楼主。

:laughing:嫖了楼主一个思路,想自己做一个渐变色的,结果没做好,渐变不怎么明显,锯齿也很严重,不清楚该怎么处理了


在这里插入图片描述

红色通道

在这里插入图片描述

绿色通道

在这里插入图片描述

蓝色通道

在这里插入图片描述

要用距离,给三个通道分别映射,0-0.5半径内距离,映射为对应曲线的函数,才能圆润起来

2赞

好吧。。。这就触及到我的知识盲区了。。。我还以为只需要操作值衰减就可以了

写的很详细,易懂

vec3 color = vec3(0.);
float x = v_uv0.x;float y = v_uv0.y;
color = vec3(
             sin(4.*x+0.85)*2.-0.5,
             sin(5.*x-1.),
             sin(3.*x-1.5) *1.5
             );
vec4 o = vec4(color, 1);
gl_FragColor = o;

image

不在盲区,初中数学就能搞定。
更多色彩变换,需要把函数曲线调的更细腻,多试试
曲线编辑网站

3赞

函数不在盲区,关键色彩这块是盲区,刚搜了半天都是ps技巧,我试试你这个

随便放个图,用ps打开,通道分别看红绿蓝三个通道的颜色变换,最亮是1,最暗是0,然后调个曲线差不多的函数就行

只看蓝色通道就这样,曲线大概估一下,然后用shader做出来调整最终值

1赞

:upside_down_face:我只想说,世上无难事,只要肯放弃。。。

:+1:collect!

谢谢大佬,用你这个曲线弄了个感觉挺棒的! :laughing:
截屏2021-08-10 下午2.55.17

1赞

为啥 预览 模式先显示不对呢

默认创建精灵使用的是引擎自带的图,这个图会参与合图导致uv变成合图后的大图uv,把精灵纹理换一张不参与合图的图片进行了image 就是换一张自己的图,别勾选这个勾

1赞

果然 , 多谢