Примеры можно попробовать в редакторе http://www.kickjs.org/tool/shader_editor/shader_editor.html
Значения uniform задаются на вкладке Uniforms (не забываем жать Update).
Общий для всех шейдеров:
precision highp float;
attribute vec3 vertex;
attribute vec2 uv1;
varying vec2 vUv;
uniform mat4 _mv; // в three.js по умолчанию это modelViewMatrix
uniform mat4 _mvProj; // в three.js по умолчанию это projectionMatrix
void main() {
vUv = uv1;
gl_Position = _mvProj * _mv * vec4(vertex, 1.0);
}
precision highp float;
varying vec2 vUv;
uniform sampler2D tex;
void main(void)
{
// просто берем цвет текселя по uv-координатам
gl_FragColor = texture2D(tex, vUv);
}
precision highp float;
varying vec2 vUv;
uniform sampler2D tex;
void main(void)
{
// получаем цвет текселя по uv-координатам
vec4 texel = texture2D(tex, vUv);
// получаем яркость усредняя компоненты цвета
float l = (texel.r + texel.g + texel.b)/3.0;
// отдаем цвет, в котором в каждой компоненте
// значение яркости
gl_FragColor = vec4(l, l, l, texel.a);
}
precision highp float;
varying vec2 vUv;
uniform sampler2D tex;
void main(void)
{
// получаем цвет текселя по uv-координатам
vec4 texel = texture2D(tex, vUv);
// коэффициенты вклада в яркость пиксела
// соответствующих компонент цвета
vec3 luma = vec3(0.299, 0.587, 0.114);
// вычисляем яркость
// эквивалент texel.r*luma.r + texel.g*luma.g + texel.b*luma.b
float l = dot(texel.rgb, luma);
// отдаем цвет, в котором в каждой компоненте
// значение яркости
gl_FragColor = vec4(l, l, l, texel.a);
}
Оставляет только яркие участки изображения и выкручивает контраст.
precision highp float;
varying vec2 vUv;
uniform sampler2D tex;
uniform float defaultOpacity; // хорошее значение 1.0
uniform vec3 defaultColor; // хорошее значение vec3(0, 0, 0)
uniform float luminosityThreshold; // порог, хорошее значение для дефолтной текстуры 0.4
uniform float smoothWidth; // ширина плавного перехода, хорошее значение для дефолтной текстуры 0.2
void main(void)
{
// получаем цвет текселя по uv-координатам
vec4 texel = texture2D(tex, vUv);
// получаем яркость фрагмента (аналогично ч/б)
vec3 luma = vec3(0.299, 0.587, 0.114);
float l = dot(texel.rgb, luma);
// вычисляем коэффициент смешения (альфа)
// если яркость меньше порога - 0.0
// если яркость больше порога + ширина плавного перехода - 1.0
// если в пределах полосы плавного перехода - интерполированное значение
float alpha = smoothstep(luminosityThreshold, luminosityThreshold + smoothWidth, l);
// смешиваем дефолтный цвет (черный) и цвет текселя
vec4 outputColor = vec4(defaultColor.rgb, defaultOpacity);
gl_FragColor = mix(outputColor, texel, alpha);
}
Нужно два прохода, один размывает по горизонтали (direction = vec2(1, 0)
), второй - полученный результат по вертикали (direction = vec2(0, 1)
).
precision highp float;
varying vec2 vUv;
uniform sampler2D tex;
uniform vec2 texSize; // размеры текстуры
uniform vec2 direction; // направление размытия
// радиус размытия
#define KERNEL_RADIUS 20
float gaussianPdf(in float x, in float sigma) {
return 0.39894 * exp(-0.5 * x * x / (sigma * sigma)) / sigma;
}
void main(void)
{
float sigma = float(KERNEL_RADIUS);
// диапазон uv-координат - 0.0-1.0,
// так что нам нужен шаг в 1.0/texSize
vec2 invSize = 1.0 / texSize;
float weightSum = gaussianPdf(0.0, sigma);
vec3 diffuseSum = texture2D(tex, vUv).rgb * weightSum;
// для каждого текселя достаем значения соседних,
// и добавляем их с соответствующими весами к текущему
for(int i = 1; i < KERNEL_RADIUS; i++) {
float x = float(i);
float w = gaussianPdf(x, sigma);
vec2 vUvOffset = direction * invSize * x;
vec3 sample1 = texture2D(tex, vUv + vUvOffset).rgb;
vec3 sample2 = texture2D(tex, vUv - vUvOffset).rgb;
diffuseSum += (sample1 + sample2) * w;
weightSum += 2.0 * w;
}
gl_FragColor = vec4(diffuseSum/weightSum, 1.0);
}