shader基础-形状-距离场

157 阅读5分钟

1. 通过修改距离场可以变化形状

#ifdef GL_ES
precision mediump float;   // 如果是在OpenGL ES环境下,设置中等精度的浮点数
#endif

uniform vec2 u_resolution;  // uniform变量,用于传入画布分辨率
uniform vec2 u_mouse;       // uniform变量,用于传入鼠标位置
uniform float u_time;       // uniform变量,用于传入当前时间

void main(){                // 着色器的主函数
  vec2 st = gl_FragCoord.xy/u_resolution.xy;  // 将片元的坐标规范化到[0,1]的范围内
  st.x *= u_resolution.x/u_resolution.y;      // 根据屏幕宽高比调整x坐标,保证图形不会被拉伸
  vec3 color = vec3(0.0);                     // 初始化颜色为黑色
  float d = 0.0;                              // 初始化距离值为0

  // Remap the space to -1. to 1.
  st = st *2.-1.;                             // 将坐标范围重新映射到[-1,1]

  // Make the distance field
  d = length( abs(st)-.3 );                    // 计算当前点到半径为0.3的圆的距离
  // d = length( min(abs(st)-.3,0.) );         // 注释的代码,生成实心圆形的距离场
  // d = length( max(abs(st)-.3,0.) );         // 注释的代码,生成空心圆形的距离场

  // Visualize the distance field
  gl_FragColor = vec4(vec3(fract(d*10.0)),1.0); // 根据距离值生成颜色,用于可视化距离场

  // Drawing with the distance field
  // gl_FragColor = vec4(vec3( step(.3,d) ),1.0);                 // 注释的代码,使用step函数生成硬边界的圆
  // gl_FragColor = vec4(vec3( step(.3,d) * step(d,.4)),1.0);     // 注释的代码,生成环形区域
  // gl_FragColor = vec4(vec3( smoothstep(.3,.4,d)* smoothstep(.6,.5,d)) ,1.0); // 注释的代码,生成带有平滑过渡的环形区域
}

效果如图

image.png

2. 选择实心圆和环形过度可以生成类似星星的样式

#ifdef GL_ES
precision mediump float;   // 如果是在OpenGL ES环境下,设置中等精度的浮点数
#endif

uniform vec2 u_resolution;  // uniform变量,用于传入画布分辨率
uniform vec2 u_mouse;       // uniform变量,用于传入鼠标位置
uniform float u_time;       // uniform变量,用于传入当前时间

void main(){                // 着色器的主函数
  vec2 st = gl_FragCoord.xy/u_resolution.xy;  // 将片元的坐标规范化到[0,1]的范围内
  st.x *= u_resolution.x/u_resolution.y;      // 根据屏幕宽高比调整x坐标,保证图形不会被拉伸
  vec3 color = vec3(0.0);                     // 初始化颜色为黑色
  float d = 0.0;                              // 初始化距离值为0

  // Remap the space to -1. to 1.
  st = st *2.-1.;                             // 将坐标范围重新映射到[-1,1]

  // Make the distance field
  //d = length( abs(st)-.3 );                    // 计算当前点到半径为0.3的圆的距离
   d = length( min(abs(st)-.3,0.) );         // 注释的代码,生成实心圆形的距离场
  // d = length( max(abs(st)-.3,0.) );         // 注释的代码,生成空心圆形的距离场

  // Visualize the distance field
  gl_FragColor = vec4(vec3(fract(d*10.0)),1.0); // 根据距离值生成颜色,用于可视化距离场

  // Drawing with the distance field
  // gl_FragColor = vec4(vec3( step(.3,d) ),1.0);                 // 注释的代码,使用step函数生成硬边界的圆
  // gl_FragColor = vec4(vec3( step(.3,d) * step(d,.4)),1.0);     // 注释的代码,生成环形区域
   gl_FragColor = vec4(vec3( smoothstep(.3,.4,d)* smoothstep(.6,.5,d)) ,1.0); // 注释的代码,生成带有平滑过渡的环形区域
}

image.png

3. 极坐标的变换

极坐标下的半径函数(r-θ)图案。它是通过改变角度θ和对应的半径r值,然后使用这个函数生成一系列形状和纹理。

#ifdef GL_ES
precision mediump float;   // 如果是在OpenGL ES环境下,设置中等精度的浮点数
#endif

uniform vec2 u_resolution;  // uniform变量,用于传入画布分辨率
uniform vec2 u_mouse;       // uniform变量,用于传入鼠标位置
uniform float u_time;       // uniform变量,用于传入当前时间

void main(){
    vec2 st = gl_FragCoord.xy/u_resolution.xy;  // 将片元的坐标规范化到[0,1]的范围内
    vec3 color = vec3(0.0);                     // 初始化颜色为黑色

    vec2 pos = vec2(0.5)-st;                    // 计算当前坐标点到中心点(0.5, 0.5)的向量

    float r = length(pos)*2.0;                  // 计算当前坐标点到中心点的距离,然后乘以2
    float a = atan(pos.y,pos.x);                // 计算当前坐标点相对于中心点的角度

    float f = cos(a*3.);                        // 通过角度计算一个cos值,用于后面的颜色生成
    // f = abs(cos(a*3.));                      // 注释的代码,取cos值的绝对值
    // f = abs(cos(a*2.5))*.5+.3;               // 注释的代码,通过调整cos值的频率和振幅,改变形状
    // f = abs(cos(a*12.)*sin(a*3.))*.8+.1;     // 注释的代码,通过复合函数生成更复杂的形状
    // f = smoothstep(-.5,1., cos(a*10.))*0.2+0.5; // 注释的代码,使用平滑函数改变形状的边缘

    color = vec3( 1.-smoothstep(f,f+0.02,r) );   // 根据距离r和f值生成颜色,使用了平滑函数smoothstep

    gl_FragColor = vec4(color, 1.0);             // 将计算得到的颜色赋给片元
}

效果如下。

image.png

4. 使用sin cos组合可以生成雪花。

#ifdef GL_ES
precision mediump float;   // 如果是在OpenGL ES环境下,设置中等精度的浮点数
#endif

uniform vec2 u_resolution;  // uniform变量,用于传入画布分辨率
uniform vec2 u_mouse;       // uniform变量,用于传入鼠标位置
uniform float u_time;       // uniform变量,用于传入当前时间

void main(){
    vec2 st = gl_FragCoord.xy/u_resolution.xy;  // 将片元的坐标规范化到[0,1]的范围内
    vec3 color = vec3(0.0);                     // 初始化颜色为黑色

    vec2 pos = vec2(0.5)-st;                    // 计算当前坐标点到中心点(0.5, 0.5)的向量

    float r = length(pos)*2.0;                  // 计算当前坐标点到中心点的距离,然后乘以2
    float a = atan(pos.y,pos.x);                // 计算当前坐标点相对于中心点的角度

    float f = cos(a*3.);                        // 通过角度计算一个cos值,用于后面的颜色生成
    // f = abs(cos(a*3.));                      // 注释的代码,取cos值的绝对值
    // f = abs(cos(a*2.5))*.5+.3;               // 注释的代码,通过调整cos值的频率和振幅,改变形状
     f = abs(cos(a*12.)*sin(a*3.))*.8+.1;     // 注释的代码,通过复合函数生成更复杂的形状
    //f = smoothstep(-.5,1., cos(a*10.))*0.2+0.5; // 注释的代码,使用平滑函数改变形状的边缘

    color = vec3( 1.-smoothstep(f,f+0.02,r) );   // 根据距离r和f值生成颜色,使用了平滑函数smoothstep

    gl_FragColor = vec4(color, 1.0);             // 将计算得到的颜色赋给片元
}

效果如下。

image.png