Chroma key Fragment Shader无法找到颜色[英] Chroma key Fragment Shader fails to find the color

本文是小编为大家收集整理的关于Chroma key Fragment Shader无法找到颜色的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在尝试编写一个片段阴影,该片段被用作特定颜色的色度键滤波器(例如,用特定的绿色透明的所有像素制作所有像素).

我正在写的着色器可用于WebGl proff pixi.js.

jsfiddle:

到目前为止,我为着色器编写了此代码,基于我找到的着色器在这里.

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);
}

现在,当我定义并测试此问题时,什么也不会发生. 问题在于着色器,因为我尝试过工作的其他过滤器.

我用于测试的颜色是rgb(85, 249, 44).

带有Pixi的着色器的完整代码如下:

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;

这适用于这样的视频宣传:

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是这样的:

stage = new PIXI.Container();

renderer = PIXI.autoDetectRenderer(720, 720, {
    preserveDrawingBuffer: true,
    clearBeforeRender: true
});

canvasContainer.appendChild(renderer.view);

视频词坐落在其自己的DisplayObjectContainer上,并在另一个DisplayObjectContainer上方显示(因此需要Chroma-Filter)


更新:

固定着色器可以在这里找到:

可以在这里找到固定的演示:
https://jsfiddle.net/ibevanmeenn/ibevanmeenn/hexec6eg/hexec6eg/17/17/17/

推荐答案

着色器很好,问题是均匀(colorToReplace,thresholdSensitivity和smoothing)未传递,它们都设置为0.盲目的运气,我发现要解决您需要删除第三个参数,您将传递给PIXI.Filter构造函数:

/* ... */
PIXI.Filter.call(this, vertexShader, fragmentShader) // no uniforms param here
/* ... */

ps.您没有在聊天中回答,所以我在这里发布我的发现.

本文地址:https://www.itbaoku.cn/post/2091107.html

问题描述

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).

The shader I'm writing is for use in WebGL trough PIXI.js.

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.

The color I use for the test is rgb(85, 249, 44).

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();
});

And PIXI is set up like this:

stage = new PIXI.Container();

renderer = PIXI.autoDetectRenderer(720, 720, {
    preserveDrawingBuffer: true,
    clearBeforeRender: true
});

canvasContainer.appendChild(renderer.view);

The video-sprite sits on it's own DisplayObjectContainer and is displayed above another DisplayObjectContainer (hence the need for a chroma-filter)


UPDATE:

The fixed shader can be found here:
https://gist.github.com/IbeVanmeenen/d4f5225ad7d2fa54fabcc38d740ba30e

And a fixed demo can be found here:
https://jsfiddle.net/IbeVanmeenen/hexec6eg/17/

推荐答案

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. You haven't answer in chat, so I'm posting my findings here.