Настройка динамичности c Прозрачность цветового ключа
Добавьте следующую униформу в шейдер фрагмента
uniform float backgroundAlpha;
Измените последнюю строку фрагмента шейдера с
gl_FragColor = max(texColor0 - mask * chromaKey, 0.0) + texColor1 * mask;
до
vec4 col = max(texColor0-mask*chromaKey,0.0) + texColor1*mask*vec4(vec3(1), backgroundAlpha);
if (col.a > 0.0) {
gl_FragColor = col;
} else {
discard;
}
Затем установите униформу на альфа-уровень, необходимый для фона
const bgLoc = gl.getUniformLocaton(program, "backgroundAlpha");
gl.uniform1f(bgLoc, 0);
// or with p5
theShader.setUniform('backgroundAlpha', 0); // 0 is full transparent
Убедитесь, что установлен режим наложения
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
// however you do that in P5.js
Важно Убедитесь, что вы рисуете этот объект после любых объектов, которые находятся за ним. Если вы этого не сделаете, то полупрозрачные края не будут отображать фоновые объекты, только то, что находится за вашим объектом во время рендеринга.
Обратите внимание , что если вы хотите, чтобы это всегда было Для полной прозрачности вам не нужно добавлять вторую карту текстур, удалять униформу tex1
и связанный код в JS и фрагментный шейдер. Тогда последняя строка просто ... (форма backgroundAlpha
не нужна)
vec4 col = max(texColor0 - mask * chromaKey, 0.0);
if (col.a > 0.0) {
gl_FragColor = col;
} else {
discard;
}
Лучший шейдер кеинга
Следующий шейдер удаляет ключевой цвет keyRGBA
внутри диапазон от 0 до range.y
сглаживание перехода с помощью кривой (Эрмита) для значений range.x
до range.y
.
Преобразование цветового пространства, которое использовал ваш код, выглядело очень странно, я не смог найти ничего, что использовало бы это преобразование. Я использовал цветовое пространство Y C b C r Яркость Y
игнорируется, поэтому все, что нужно, это компоненты цветности
uniform sampler2D tex0;
uniform vec4 keyRGBA; // key color as rgba
uniform vec2 keyCC; // the CC part of YCC color model of key color
uniform vec2 range; // the smoothstep range
uniform vec2 iResolution;
vec2 RGBToCC(vec4 rgba) {
float Y = 0.299 * rgba.r + 0.587 * rgba.g + 0.114 * rgba.b;
return vec2((rgba.b - Y) * 0.565, (rgba.r - Y) * 0.713);
}
void main() {
vec4 src1Color = texture2D(tex0, gl_FragCoord.xy / iResolution);
vec2 CC = RGBToCC(src1Color);
float mask = sqrt(pow(keyCC.x - CC.x, 2.0) + pow(keyCC.y - CC.y, 2.0));
mask = smoothstep(range.x, range.y, mask);
if (mask == 0.0) { discard; }
else if (mask == 1.0) { gl_FragColor = src1Color; }
else { gl_FragColor = max(src1Color - (1.0 - mask) * keyRGBA, 0.0); }
}
Установите униформу range
, keyRGBA
и keyCC
можно установить следующим образом
const RGBAToCC = (r, g, b) => {
const y = 0.299 * r + 0.587 * g + 0.114 * b;
return [(b - y) * 0.565, (r - y) * 0.713];
};
const keyRGBA = [0.05, 0.63, 0.14, 1]; // the green from your code
const range = [0.11, 0.22]; // A guess at the range needed
const keyCC = RGBAToCC(...keyRGBA);
theShader.setUniform('keyCC', keyCC);
theShader.setUniform('keyRGBA', keyRGBA);
theShader.setUniform('range', range);
Примечание , что значение альфа keyRGBA
должно быть 1