从零开始_用shader画个彩虹

17659860984980.04381247210981831

老链接图片链接挂了,补个贴。

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

从创建shader和材质开始

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

17659860985510.715719488551922
17659860985550.09425218598079499

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

17659860985590.17817205308067008

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

17659860985610.49938217290740317

使用我们创建出来的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;
 }

17659860985700.4236377836325935

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

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

大圆-小圆=

17659860985760.6630449117026467

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

 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;
// 省略重复的代码  .......
 }

17659860985790.9824447996052644

## 画彩虹?

   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;

17659860985820.8304701478434069

颜色你再调调吧。

## 边缘有锯齿?

 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函数换成上面的再看下。
17659860985880.8338267477794923

挺好。smoothstep下回再聊。


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


公众号欢迎关注

17659861000750.2599713665486282

5赞

交作业


learnShader.zip (1.4 MB)

// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.

CCEffect %{
techniques:
  - passes:
      - vert: vs
        frag: fs
        blendState:
          targets:
            - blend: true
            - blendSrc: src_alpha
            - blendDst: one_minus_src_alpha
        rasterizerState:
          cullMode: none
        properties:
          texture: { value: white }
          alphaThreshold: { value: 0.5 }

}%

CCProgram vs %{
precision highp float;

#include <cc-global>
#include <cc-local>

in vec3 a_position;
in vec4 a_color;
out vec4 v_color;

#if USE_TEXTURE
  in vec2 a_uv0;
  out vec2 v_uv0;
#endif

void main() {
  vec4 pos = vec4(a_position, 1);
  
  #if CC_USE_MODEL
    pos = cc_matViewProj * cc_matWorld * pos;
  #else
    pos = cc_matViewProj * pos;
  #endif
  
  #if USE_TEXTURE
    v_uv0 = a_uv0;
  #endif
  
  v_color = a_color;
  gl_Position = pos;
}
}%

CCProgram fs %{
precision highp float;

#include <alpha-test>
#include <texture>

in vec4 v_color;

#if USE_TEXTURE
  in vec2 v_uv0;
  uniform sampler2D texture;
#endif

// 绘制半圆弧(抗锯齿)
float drawHalfCircle(vec2 center, vec2 uv, float radius) {
  float dis = distance(uv, center);
  dis = smoothstep(radius, radius - 0.005, dis);
  return dis;
}

// 绘制半圆弧线条(通过两个半圆相减得到线宽)
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() {
  // ========== 1. 定义彩虹7种标准颜色(红橙黄绿青蓝紫) ==========
  vec3 color_red = vec3(1.0, 0.0, 0.0); // 红
  vec3 color_orange = vec3(1.0, 0.65, 0.0); // 橙
  vec3 color_yellow = vec3(1.0, 1.0, 0.0); // 黄
  vec3 color_green = vec3(0.0, 1.0, 0.0); // 绿
  vec3 color_cyan = vec3(0.0, 1.0, 1.0); // 青
  vec3 color_blue = vec3(0.0, 0.0, 1.0); // 蓝
  vec3 color_purple = vec3(0.5, 0.0, 0.5); // 紫
  
  // ========== 2. 彩虹基础参数 ==========
  vec2 rainbow_center = vec2(0.5, 1); // 彩虹圆心
  float base_radius = 0.5; // 最外层红色半径
  
  // ========== 3. 按现实彩虹比例设置各颜色宽度(外宽内窄) ==========
  float width_red = 0.06; // 红色最宽
  float width_orange = 0.055; // 橙色
  float width_yellow = 0.05; // 黄色
  float width_green = 0.045; // 绿色
  float width_cyan = 0.04; // 青色
  float width_blue = 0.035; // 蓝色
  float width_purple = 0.03; // 紫色最窄
  
  // ========== 4. 计算各颜色圆环的半径(从外到内依次递减) ==========
  float radius_red = base_radius;
  float radius_orange = radius_red - width_red;
  float radius_yellow = radius_orange - width_orange;
  float radius_green = radius_yellow - width_yellow;
  float radius_cyan = radius_green - width_green;
  float radius_blue = radius_cyan - width_cyan;
  float radius_purple = radius_blue - width_blue;
  
  // ========== 5. 绘制7色半圆弧 ==========
  float circle_red = drawHalfCircleLine(rainbow_center, v_uv0, radius_red, width_red);
  float circle_orange = drawHalfCircleLine(rainbow_center, v_uv0, radius_orange, width_orange);
  float circle_yellow = drawHalfCircleLine(rainbow_center, v_uv0, radius_yellow, width_yellow);
  float circle_green = drawHalfCircleLine(rainbow_center, v_uv0, radius_green, width_green);
  float circle_cyan = drawHalfCircleLine(rainbow_center, v_uv0, radius_cyan, width_cyan);
  float circle_blue = drawHalfCircleLine(rainbow_center, v_uv0, radius_blue, width_blue);
  float circle_purple = drawHalfCircleLine(rainbow_center, v_uv0, radius_purple, width_purple);
  
  // ========== 6. 混合最终颜色和透明度 ==========
  // 颜色混合:各颜色只在自己的环带区域显示
  vec3 final_rgb = circle_red * color_red
  + circle_orange * color_orange
  + circle_yellow * color_yellow
  + circle_green * color_green
  + circle_cyan * color_cyan
  + circle_blue * color_blue
  + circle_purple * color_purple;
  
  // 透明度计算:仅彩虹区域不透明,其他区域透明
  float final_alpha = circle_red + circle_orange + circle_yellow + circle_green + circle_cyan + circle_blue + circle_purple;
  
  // 最终像素颜色
  vec4 o = vec4(final_rgb, final_alpha);
  
  // 可选:叠加底层纹理(取消注释即可)
  // vec4 tex_color = CCSampleTexture(texture, v_uv0);
  // o = mix(tex_color, o, o.a);
  
  gl_FragColor = o;
}
}%

mask!

这配色,你说实话你是不是美术来的

前端转来cocos做了一年UI崽啦 :monkey:

image
跟着哥哥学习shader,有几个问题啊。
1.我在ai上听说不能用tab,只能用空格,但是我用tab对齐怎么也没有报错啊
2.一些内置的api是什么意思啊,或者说怎么知道有那些api,每一句都要问ai :rofl:
3.里面怎么调试啊,是只能用颜色输出数值来判断吗?

https://thebookofshaders.com/13/?lan=ch
https://www.ronja-tutorials.com/
https://registry.khronos.org/OpenGL-Refpages/gl4/html/
https://learnopengl-cn.github.io/
https://www.bilibili.com/video/BV1sh41147zb/?vd_source=345574436597031baec605b9466b49f0

2赞