本文中收集GLSL常用的代码片段和造型函数。将这些封装好的函数复制到vertexShader和fragmentShader中,然后在main()中通过函数名直接调用。
Snippets from shdr.bkcore.com
DefaultVertex
precision highp float;
attribute vec3 position;
attribute vec3 normal;
uniform mat3 normalMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec3 fNormal;
varying vec3 fPosition;
void main()
{
fNormal = normalize(normalMatrix * normal);
vec4 pos = modelViewMatrix * vec4(position, 1.0);
fPosition = pos.xyz;
gl_Position = projectionMatrix * pos;
}
DefaultFragment
precision highp float;
uniform float time;
uniform vec2 resolution;
varying vec3 fPosition;
varying vec3 fNormal;
void main()
{
gl_FragColor = vec4(fNormal, 1.0);
}
DemoVertex
precision highp float;
attribute vec3 position;
void main()
{
gl_Position = vec4(position, 1.0);
}
DemoFragment
precision highp float;
uniform float time;
uniform vec2 resolution;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main()
{
vec2 pixel = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;
pixel.x *= resolution.x/resolution.y;
gl_FragColor = vec4(pixel,.0,1.);
}
ExtractCameraPos
vec3 ExtractCameraPos(mat4 a_modelView)
{
mat3 rotMat =mat3(a_modelView[0].xyz,a_modelView[1].xyz,a_modelView[2].xyz);
vec3 d = a_modelView[3].xyz;
vec3 retVec = -d * rotMat;
return retVec;
}
GetDirection
vec3 getDirection(vec3 origine, vec2 pixel)
{
vec3 ww = normalize(vec3(0.0) - origine);
vec3 uu = normalize(cross( vec3(0.0,1.0,0.0), ww ));
vec3 vv = normalize(cross(ww,uu));
return normalize( pixel.x*uu + pixel.y*vv + 1.5*ww );
}
Luma
vec3 luma = vec3(0.299, 0.587, 0.114);
Fresnel
float fresnel(float costheta, float fresnelCoef)
{
return fresnelCoef + (1. - fresnelCoef) * pow(1. - costheta, 5.);
}
Ashikhmin(Dir)
float Ashikhmin(vec3 lightDir, vec3 viewDir, vec3 normal, float exponent, float fresnelCoef)
{
vec3 H = normalize(lightDir+viewDir);
float numerateur_s = ( exponent + 1.)/(8.*3.14159) * pow(dot(normal,H), exponent );
float denominateur_s = dot(lightDir,H)*(dot(normal,lightDir) + dot(normal, viewDir) - dot(normal, lightDir) * dot(normal, viewDir));
float K = fresnel(dot(normal,lightDir), fresnelCoef) * ( numerateur_s / denominateur_s ) ;
return K;
}
Blinn-Phong(Dir)
vec2 blinnPhongDir(vec3 lightDir, float lightInt, float Ka, float Kd, float Ks, float shininess)
{
vec3 s = normalize(lightDir);
vec3 v = normalize(-fPosition);
vec3 n = normalize(fNormal);
vec3 h = normalize(v+s);
float diffuse = Ka + Kd * lightInt * max(0.0, dot(n, s));
float spec = Ks * pow(max(0.0, dot(n,h)), shininess);
return vec2(diffuse, spec);
}
OrenNayard(Dir)
float OrenNayarDir(vec3 lightDir, vec3 viewDir, vec3 normal, float exponent)
{
float LdotN = dot(lightDir,normal);
float VdotN = dot(viewDir,normal);
float result = clamp( LdotN, 0. , 1.);
float soft_rim = clamp( 1. - VdotN/2., 0. , 1.);
float fakey = pow(1. - result * soft_rim , 2.);
float fakey_magic = 0.62;
fakey = fakey_magic - fakey*fakey_magic;
float K = mix(result, fakey, exponent) ;
return K;
}
Ward(Dir)
float Ward(vec3 lightDir, vec3 viewDir, vec3 normal, float exponent)
{
vec3 H = normalize(lightDir + viewDir);
float delta = acos(dot(H,normal));
float alpha2 = exponent * exponent;
float temp = exp(-pow(tan(delta), 2.) / (alpha2)) / (4. * 3.1415 * alpha2);
float temp2 = sqrt(dot(viewDir,normal) * dot(lightDir,normal));
float K = temp2 * temp;
return K;
}
ColorNormal
vec3 colorNormal(vec3 col1, vec3 col2, vec3 col3)
{
vec3 n = normalize(fNormal);
return clamp(col1*n.x + col2*n.y + col3*n.z,
vec3(0.0), vec3(1.0));
}
Rimlight
vec3 rim(vec3 color, float start, float end, float coef)
{
vec3 normal = normalize(fNormal);
vec3 eye = normalize(-fPosition.xyz);
float rim = smoothstep(start, end, 1.0 - dot(normal, eye));
return clamp(rim, 0.0, 1.0) * coef * color;
}
Split
vec3 split(vec3 left, vec3 right, float ratio, bool horizontal)
{
float i = float(horizontal);
float m = i*gl_FragCoord.x/resolution.x;
m += (1.0-i)*gl_FragCoord.y/resolution.y;
float d = float(m < ratio);
return left*d + right*(1.0-d);
}
Transpose(mat3)
mat3 transpose( mat3 m )
{
mat3 ret = m;
ret[0][1] = m[1][0];
ret[0][2] = m[2][0];
ret[1][0] = m[0][1];
ret[1][2] = m[2][1];
ret[2][0] = m[0][2];
ret[2][1] = m[1][2];
return ret;
}
Shaping functions | 造型函数
Useful little functions from Iñigo Quiles
http://www.iquilezles.org/www/articles/functions/functions.htm
Almost Identity
float almostIdentity( float x, float m, float n )
{
if( x>m ) return x;
const float a = 2.0*n - m
const float b = 2.0*m - 3.0*n;
const float t = x/m;
return (a*t + b)*t*t + n;
}
Exponential Impulse
float expImpulse( float k, float x ){
float h = k*x;
return h*exp(1.0-h);
}
Polynomial Impulse
float quaImpulse( float k, float x )
{
return 2.0*sqrt(k)*x/(1.0+k*x*x);
}
Cubic Pulse
float cubicPulse( float c, float w, float x ){
x = abs(x - c);
if( x>w ) return 0.0;
x /= w;
return 1.0 - x*x*(3.0-2.0*x);
}
Exponential Step
float expStep( float x, float k, float n ){
return exp( -k*pow(x,n) );
}
Gain
float gain(float x, float k)
{
const float a = 0.5*pow(2.0*((x<0.5)?x:1.0-x), k);
return (x<0.5)?a:1.0-a;
}
Parabola
float parabola( float x, float k ){
return pow( 4.0*x*(1.0-x), k );
}
Power curve
float pcurve( float x, float a, float b ){
float k = pow(a+b,a+b) / (pow(a,a)*pow(b,b));
return k * pow( x, a ) * pow( 1.0-x, b );
}
Sinc curve
float sinc( float x, float k )
{
const float a = PI*((k*x-1.0);
return sin(a)/a;
}
Table of equations from Kynd
Easing functions for transition| 缓动函数过渡
Robert Penner’s easing functions in GLSL
https://github.com/stackgl/glsl-easings
https://thebookofshaders.com/edit.php#06/easing.frag
Linear
float linear(float t) {
return t;
}
easeInSine
float sineIn(float t) {
return sin((t - 1.0) * HALF_PI) + 1.0;
}
easeOutSine
float sineOut(float t) {
return sin(t * HALF_PI);
}
easeInOutSine
float sineInOut(float t) {
return -0.5 * (cos(PI * t) - 1.0);
}
easeInQuad
float quadraticIn(float t) {
return t * t;
}
easeOutQuad
float quadraticInOut(float t) {
float p = 2.0 * t * t;
return t < 0.5 ? p : -p + (4.0 * t) - 1.0;
}
easeInOutQuad
float quadraticOut(float t) {
return -t * (t - 2.0);
}
easeInCubic
float cubicIn(float t) {
return t * t * t;
}
easeOutCubic
float cubicOut(float t) {
float f = t - 1.0;
return f * f * f + 1.0;
}
easeInOutCubic
float cubicInOut(float t) {
return t < 0.5
? 4.0 * t * t * t
: 0.5 * pow(2.0 * t - 2.0, 3.0) + 1.0;
}
easeInQuart
float quarticIn(float t) {
return pow(t, 4.0);
}
easeOutQuart
float quarticOut(float t) {
return pow(t - 1.0, 3.0) * (1.0 - t) + 1.0;
}
easeInOutQuart
float quarticInOut(float t) {
return t < 0.5
? +8.0 * pow(t, 4.0)
: -8.0 * pow(t - 1.0, 4.0) + 1.0;
}
easeInQuint
float qinticIn(float t) {
return pow(t, 5.0);
}
easeOutQuint
float qinticOut(float t) {
return 1.0 - (pow(t - 1.0, 5.0));
}
easeInOutQuint
float qinticInOut(float t) {
return t < 0.5
? +16.0 * pow(t, 5.0)
: -0.5 * pow(2.0 * t - 2.0, 5.0) + 1.0;
}
easeInExpo
float exponentialIn(float t) {
return t == 0.0 ? t : pow(2.0, 10.0 * (t - 1.0));
}
easeOutExpo
float exponentialOut(float t) {
return t == 1.0 ? t : 1.0 - pow(2.0, -10.0 * t);
}
easeInOutExpo
float exponentialInOut(float t) {
return t == 0.0 || t == 1.0
? t
: t < 0.5
? +0.5 * pow(2.0, (20.0 * t) - 10.0)
: -0.5 * pow(2.0, 10.0 - (t * 20.0)) + 1.0;
}
easeInCirc
float circularIn(float t) {
return 1.0 - sqrt(1.0 - t * t);
}
easeOutCirc
float circularOut(float t) {
return sqrt((2.0 - t) * t);
}
easeInOutCirc
float circularInOut(float t) {
return t < 0.5
? 0.5 * (1.0 - sqrt(1.0 - 4.0 * t * t))
: 0.5 * (sqrt((3.0 - 2.0 * t) * (2.0 * t - 1.0)) + 1.0);
}
easeInBack
float backIn(float t) {
return pow(t, 3.0) - t * sin(t * PI);
}
easeOutBack
float backOut(float t) {
float f = 1.0 - t;
return 1.0 - (pow(f, 3.0) - f * sin(f * PI));
}
easeInOutBack
float backInOut(float t) {
float f = t < 0.5
? 2.0 * t
: 1.0 - (2.0 * t - 1.0);
float g = pow(f, 3.0) - f * sin(f * PI);
return t < 0.5
? 0.5 * g
: 0.5 * (1.0 - g) + 0.5;
}
easeInElastic
float elasticIn(float t) {
return sin(13.0 * t * HALF_PI) * pow(2.0, 10.0 * (t - 1.0));
}
easeOutElastic
float elasticOut(float t) {
return sin(-13.0 * (t + 1.0) * HALF_PI) * pow(2.0, -10.0 * t) + 1.0;
}
easeInOutElastic
float elasticInOut(float t) {
return t < 0.5
? 0.5 * sin(+13.0 * HALF_PI * 2.0 * t) * pow(2.0, 10.0 * (2.0 * t - 1.0))
: 0.5 * sin(-13.0 * HALF_PI * ((2.0 * t - 1.0) + 1.0)) * pow(2.0, -10.0 * (2.0 * t - 1.0)) + 1.0;
}
easeInBounce
float bounceIn(float t) {
return 1.0 - bounceOut(1.0 - t);
}
easeOutBounce
float bounceOut(float t) {
const float a = 4.0 / 11.0;
const float b = 8.0 / 11.0;
const float c = 9.0 / 10.0;
const float ca = 4356.0 / 361.0;
const float cb = 35442.0 / 1805.0;
const float cc = 16061.0 / 1805.0;
float t2 = t * t;
return t < a
? 7.5625 * t2
: t < b
? 9.075 * t2 - 9.9 * t + 3.4
: t < c
? ca * t2 - cb * t + cc
: 10.8 * t * t - 20.52 * t + 10.72;
}
easeInOutBounce
float bounceInOut(float t) {
return t < 0.5
? 0.5 * (1.0 - bounceOut(1.0 - t * 2.0))
: 0.5 * bounceOut(t * 2.0 - 1.0) + 0.5;
}
How to use
在GLSL在线编辑器中调试
GLSL Shader online editer:
在ThreeJS中使用
更多资料
- Shaping functions from Golan Levin
- Iñigo Quiles‘ articles
- webgl-noise