色度键片段着色器找不到颜色 [英] Chroma key Fragment Shader fails to find the color
问题描述
我正在尝试编写一个片段着色器,以用作特定颜色的色键过滤器(例如,使所有具有特定绿色的像素透明).
I'm trying to write a fragment-shader that functions as a chroma-key filter for a specific color (for example make all pixels with a specific green transparent).
我正在编写的着色器用于通过PIXI.js的WebGL.
The shader I'm writing is for use in WebGL trough PIXI.js.
JSFiddle: https://jsfiddle.net/IbeVanmeenen/hexec6eg/14/
JSFiddle: https://jsfiddle.net/IbeVanmeenen/hexec6eg/14/
So far, I wrote this code for the shader, based on the shader I've found here.
varying vec2 vTextureCoord;
uniform float thresholdSensitivity;
uniform float smoothing;
uniform vec3 colorToReplace;
uniform sampler2D uSampler;
void main() {
vec4 textureColor = texture2D(uSampler, vTextureCoord);
float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;
float maskCr = 0.7132 * (colorToReplace.r - maskY);
float maskCb = 0.5647 * (colorToReplace.b - maskY);
float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;
float Cr = 0.7132 * (textureColor.r - Y);
float Cb = 0.5647 * (textureColor.b - Y);
float blendValue = smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));
gl_FragColor = vec4(textureColor.rgb, textureColor.a * blendValue);
}
现在,当我定义和测试此功能时,什么也没有发生. 问题出在着色器上,因为我尝试过的其他滤镜都起作用.
Now, when I define and test this, nothing happens. The problem lies with the shader, because the other filters I tried work.
我用于测试的颜色是rgb(85, 249, 44)
.
带有PIXI的着色器的完整代码如下:
The Full code for the shader with PIXI is below:
function ChromaFilter() {
const vertexShader = null;
const fragmentShader = [
"varying vec2 vTextureCoord;",
"uniform float thresholdSensitivity;",
"uniform float smoothing;",
"uniform vec3 colorToReplace;",
"uniform sampler2D uSampler;",
"void main() {",
"vec4 textureColor = texture2D(uSampler, vTextureCoord);",
"float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;",
"float maskCr = 0.7132 * (colorToReplace.r - maskY);",
"float maskCb = 0.5647 * (colorToReplace.b - maskY);",
"float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;",
"float Cr = 0.7132 * (textureColor.r - Y);",
"float Cb = 0.5647 * (textureColor.b - Y);",
"float blendValue = smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));",
"gl_FragColor = vec4(textureColor.rgb, textureColor.a * blendValue);",
"}"
].join('\n');
let uniforms = {};
PIXI.Filter.call(this,
vertexShader,
fragmentShader,
uniforms
);
this.uniforms.thresholdSensitivity = 0.4;
this.uniforms.smoothing = 0.1;
this.uniforms.colorToReplace = [0.33, 0.97, 0.17];
this.glShaderKey = 'chromakey';
}
ChromaFilter.prototype = Object.create(PIXI.Filter.prototype);
ChromaFilter.prototype.constructor = ChromaFilter;
这将应用于视频精灵,如下所示:
This is applied to the video-sprite like this:
videoBase = new PIXI.VideoBaseTexture(videoLoaderVid);
videoBase.on('loaded', () => {
video = videoBase.source;
video.volume = 0;
video.pause();
video.currentTime = 0;
videoTexture = new PIXI.Texture(videoBase);
videoSprite = new PIXI.Sprite(videoTexture);
const filter = new ChromaFilter();
videoSprite.filters = [filter];
resolve();
});
PIXI的设置如下:
And PIXI is set up like this:
stage = new PIXI.Container();
renderer = PIXI.autoDetectRenderer(720, 720, {
preserveDrawingBuffer: true,
clearBeforeRender: true
});
canvasContainer.appendChild(renderer.view);
视频图片位于其自己的DisplayObjectContainer上,并显示在另一个DisplayObjectContainer上方(因此需要色度滤镜)
The video-sprite sits on it's own DisplayObjectContainer and is displayed above another DisplayObjectContainer (hence the need for a chroma-filter)
更新:
可在此处找到固定的着色器:
https://gist.github.com/IbeVanmeenen/d4f5225ad7d2fa54fabcc38d740ba30e
The fixed shader can be found here:
https://gist.github.com/IbeVanmeenen/d4f5225ad7d2fa54fabcc38d740ba30e
在此处可以找到固定的演示:
https://jsfiddle.net/IbeVanmeenen/hexec6eg/17/
And a fixed demo can be found here:
https://jsfiddle.net/IbeVanmeenen/hexec6eg/17/
推荐答案
着色器很好,问题是没有通过制服(colorToReplace
,thresholdSensitivity
和smoothing
),它们都已设置好到0s.运气不好,我发现要解决此问题,您需要删除传递给PIXI.Filter
构造函数的第三个参数:
The shader is fine, the problem is that uniforms (colorToReplace
, thresholdSensitivity
and smoothing
) aren't passed, they're all set to 0s. By blind luck I've found that to fix that you need to remove third parameter you're passing to PIXI.Filter
constructor:
/* ... */
PIXI.Filter.call(this, vertexShader, fragmentShader) // no uniforms param here
/* ... */
PS.您尚未在聊天中回答,所以我在这里发布我的发现.
PS. You haven't answer in chat, so I'm posting my findings here.
这篇关于色度键片段着色器找不到颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!