像素精灵元素GLSL - 概览与总结

808 阅读3分钟

所有图形

点击图案查看完整代码

黑白分明

通用函数方法总结

#ifdef GL_ES
precision mediump float;
#endif

float QTR_PI = 0.78539816339;                       // 四分之一PI
float HALF_PI = 1.5707963267948966192313216916398;  // 二分之一PI
float PI = 3.1415926535897932384626433832795;       // PI 
float TWO_PI = 6.2831853071795864769252867665590;  // 2PI
float TAU = 6.2831853071795864769252867665590;  // 2PI
float PHI = 1.618033988749894848204586834;  // 黄金分割率
float EPSILON = 0.0000001;

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;


/** 绘制线条
* @param {float } x 坐标点
* @param {float } s 划线的位置
* @param {float } w 现对与屏幕宽度的线宽
*/
float stroke(float x, float s, float w){
    float d = step(s, x + w * 0.5) - step(s, x - w * 0.5);
    return clamp(d, 0.0, 1.0);
}
/** 填充一个区域
* @param x 坐标点
* @param size 大小 
*/
float fill(float x, float size){
    return 1.0 - step(size,x);
}

/** 绘制星星状的图形
* @param st 坐标点
* @param  V 边数
* @param s 图形大小
*/
float starSDF(vec2 st, int V, float s){
   st = st * 4.0 - 2.0;
   float a = atan(st.y,st.x) / TAU;
   float seg = a * float(V);
   a = ((floor(seg)+0.5) / float(V) + mix(s, -s, step(0.5, fract(seg)))) * TAU;
   return abs(dot(vec2(cos(a), sin(a)),st));
}

/** 绘制一个圆
* @param st 坐标点
*/
float circleSDF(vec2 st){
    return length(st-0.5) * 2.0;
}

/** 旋转
* @param v 坐标值
* @param angle 旋转的弧度
*/
vec2  rotate(vec2 st, float angle){
    float cos_theta = cos(angle);
    float sin_theta = sin(angle);
    vec2 _st =  mat2(cos_theta, -sin_theta, sin_theta, cos_theta) * (st - 0.5);
    return _st + 0.5;
}


/** 绘制一个多边形
* @param st 坐标点
* @param V 边数
*/
float polySDF(vec2 st, int V){
    st = st*2.-1.;
    float a = atan(st.x,st.y)+PI;
    float r = length(st);
    float v = TAU/float(V);
    return cos(floor(.5+a/v)*v-a)*r;

}

/** 绘制放射状图形
* @param st 坐标点
* @param N 放射块数
*/
float raysSDF(vec2 st, int N){
    st -= 0.5;
    return fract(atan(st.y,st.x) / TAU * float(N));
}

/** 使用fill 或 stroke 后的图形交集部分呈现黑色
*  不使用fill 或 stroke 后的图形交集部分呈现白色
* @param v 坐标值
* @param pct 十字大小
*/
float flip(float v, float pct){
    return mix(v, 1.0 - v, pct);
}

/**
* @param st 坐标值
* @param s 区域大小
*/
float rectSDF(vec2 st, vec2 s){
    st = st * 2.0 -1.0;
    return max(abs(st.x / s.x), abs(st.y / s.y));
}

/** 绘制一个鱼泡
* @param st 坐标点
* @param w 参数越大,绘制的图形就越小
*/
float vesicaSDF(vec2 st, float w){
	vec2 offset = vec2(w*.5,0.);
	return max( circleSDF(st-offset), circleSDF(st+offset));
}

/** stroke 划线 两个线条重合部分,前一个图形断开,后一个图形穿过
* @param c 前一个图形的绘制结果颜色
* @param d 后一个图形的运算结果
* @param s 后一个图形的大小参数
* @param w 后一个图形的线宽参数
*/
vec3 bridge(vec3 c, float d, float s, float w){
    c *= 1.0 - stroke(d, s, w * 2.0);
    return c + stroke(d, s, w);
}


/** 绘制一个正三角形
* @param st 坐标点
*/
float triSDF(vec2 st){
	st = (st * 2.0 - 1.0) * 2.0;
	return max(abs(st.x) * 0.866025 + st.y * 0.5, -st.y * 0.5);
}

/** 绘制一个菱形
* @param st 坐标点
*/
float rhombSDF(vec2 st){
	return max(triSDF(st), triSDF(vec2(st.x,1.-st.y)));
}

/** 缩放坐标点范围,图形随之缩放
* @param st 坐标点
* @param s x方向与y方向缩放参数,值越大,图形越小,值越小图形越大
*/
vec2 scale(vec2 st, vec2 s){
	return (st - 0.5) * s + 0.5;
}

/** 绘制花瓣图案
* @param st 坐标点
* @param N 花瓣数
*/
float flowerSDF(vec2 st, int N) {
	st = st * 2.0 - 1.0;
	float r = length(st) * 2.0;
	float a = atan(st.y, st.x);
	float v = float(N) * 0.5;
	return 1.0 - (abs(cos(a * v)) * 0.5 + 0.5) / r;
}

/** 绘制螺旋图
* @param st 坐标点
* @param t 旋转的圈数
*/
float spiralSDF(vec2 st, float t) {
    st -= .5;
    float r = dot(st,st);
    float a = atan(st.y,st.x);
    return abs(sin(fract(log(r)*t+a*0.159)));
}

/** 绘制十字图形
* @param st 坐标点
* @param s 图形大小参数
*/
float crossSDF(vec2 st, float s){
	vec2 size = vec2(0.25, s);
	return min(rectSDF(st, size.xy), rectSDF(st, size.yx));
}

/** 绘制一个六边形
* @param st 坐标点
*/
float hexSDF(vec2 st){
	st = abs(st * 2.0 - 1.0);
	return max(abs(st.y), st.x * 0.866025 + st.y * 0.5);
}

/** 绘制一个爱心图❤️
* @param st 坐标点
*/
float heartSDF(vec2 st) {
	st -= vec2(0.5, 0.8);
	float r = length(st) * 5.0;
	st = normalize(st);
	return r - ((st.y * pow(abs(st.x), 0.67)) / (st.y + 1.5) - (2.0) * st.y + 1.26);
}

void main() {
  vec2 st = gl_FragCoord.xy/u_resolution.xy;
  st.x *= u_resolution.x/u_resolution.y;
  vec3 color = vec3(0.);
  
  //TODO 这里实现你的图形

  gl_FragColor = vec4(color, 1.0);
}

个人感触

像素精灵元素,是根据gl_FragCoord返回整个画布的像素位置,在各个像素点上,通过各种图形的特性,将图形的显示的区域用白色来表示,借助shader提供的内置函数,step smoothstep mix clamp 等进行图形的计算,通过以上列出的示例到练习,可以更加深层次的理解每一个函数的应用场景,对shader的编写更加得心应手,希望每一个正在学习shader的同学都亲自去练习每一个示例,你会有不一样的收获,一起加油!🤝🤝🤝

《像素精灵元素GLSL》期待你的关注与点赞