Chromakey Webgl шейдер с p5js - PullRequest
0 голосов
/ 05 апреля 2020

Я снова пытаюсь портировать шейдерный шейдер кеинга для использования с p5. js. Примеры шейдерной передачи также передают фоновое изображение шейдеру для смешивания с передним планом в качестве текстуры. Но я не хочу использовать фоновое изображение с шейдером кеинга, потому что мой фон - это другой объект (сфера skydome) внутри трехмерного пространства для анимации камеры и параллакса. Я использую веб-камеру в качестве изображения для передачи в шейдер. Мне нужна помощь в понимании последнего фрагмента кода фрагмента шейдера, когда я пытаюсь игнорировать зеленый цвет от кеинга. Я изменил исходную линию шейдера

color = mix(color, bg, incrustation);

на

color = max(color, incrustation);

Мой фрагментный шейдер:

#ifdef GL_ES
precision mediump float;
#endif

// our texture coming from p5
uniform sampler2D tex0;
//uniform sampler2D tex1;
uniform vec2 iResolution;

vec3 rgb2hsv(vec3 rgb)
{
    float Cmax = max(rgb.r, max(rgb.g, rgb.b));
    float Cmin = min(rgb.r, min(rgb.g, rgb.b));
    float delta = Cmax - Cmin;

    vec3 hsv = vec3(0., 0., Cmax);

    if (Cmax > Cmin)
    {
        hsv.y = delta / Cmax;

        if (rgb.r == Cmax)
            hsv.x = (rgb.g - rgb.b) / delta;
        else
        {
            if (rgb.g == Cmax)
                hsv.x = 2. + (rgb.b - rgb.r) / delta;
            else
                hsv.x = 4. + (rgb.r - rgb.g) / delta;
        }
        hsv.x = fract(hsv.x / 6.);
    }
    return hsv;
}

float chromaKey(vec3 color)
{
    vec3 backgroundColor = vec3(0.157, 0.576, 0.129);
    vec3 weights = vec3(4., 1., 2.);

    vec3 hsv = rgb2hsv(color);
    vec3 target = rgb2hsv(backgroundColor);
    float dist = length(weights * (target - hsv));
    return 1. - clamp(3. * dist - 1.5, 0., 1.);
}

vec3 changeSaturation(vec3 color, float saturation)
{
    float luma = dot(vec3(0.213, 0.715, 0.072) * color, vec3(1.));
    return mix(vec3(luma), color, saturation);
}

void main()
{
  // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

    vec3 color = texture(tex0, uv).rgb;

    float incrustation = chromaKey(color);

    color = changeSaturation(color, 0.5);
    color = max(color, incrustation);

  // Output to screen
    //gl_FragColor = vec4(color, 1.);
  if (vec4(color, 1.).a > 0.0) {
        gl_FragColor = vec4(color, 1.);
  } else {
        discard;
  } 

}

Вершинный шейдер:

// our vertex data
attribute vec3 aPosition;

void main() {

  // copy the position data into a vec4, using 1.0 as the w component
  vec4 positionVec4 = vec4(aPosition, 1.0);
  positionVec4.xy = positionVec4.xy * 2.0 - 1.0;

  // send the vertex information on to the fragment shader
  gl_Position = positionVec4;
}

P5. js функция рисования эскиза:

function draw() {

  orbitControl();

  background(0,40, 200);

  ambientLight(255);

  push();
  translate(-35, 0, -250);
  normalMaterial();
  texture(imgSky);
  sphere(1200);
  pop();

  shaderTexture.shader(theShader); 
  theShader.setUniform('tex0', cam);
  theShader.setUniform('iResolution', [width, height]);
  shaderTexture.rect(0, 0, width, height);
  texture(shaderTexture);

  plane(width, height);
  pop();

}

Оригинальный шейдерный шейдер

Мой пример на Glitch

Портирование кода Shadertoy на p5. js Руководство по шейдерам

...