UNPKG

@virtualscenery/greenscreenstream

Version:

Genereate new MediaStreams or Canvas elements based on MediaStreams (webcam) with any background image/video. Greenscreen your webcam and enable virtual backgrounds in your web applications.

134 lines (123 loc) 4.64 kB
/** * GLSL fragment shader source code as a string. * * This shader samples a texture (`A`) using normalized screen coordinates * and outputs the resulting color to `fragColor`. * * Uniforms: * - `resolution`: The resolution of the output in pixels (vec2). * - `A`: The input texture (sampler2D). * * Usage: * Assign this constant to a shader program that expects the above uniforms. */ export const MAIN_FRAG: string = ` uniform vec2 resolution; uniform sampler2D A; out vec4 fragColor; void main(){ vec2 uv = gl_FragCoord.xy/resolution.xy; fragColor = texture(A, uv); } `; /** * GLSL vertex shader source code for the main vertex shader. * * This shader takes a 2D position attribute (`pos`) as input and sets the `gl_Position` * for rendering. It also declares an output variable `fragColor`, though it is not assigned * in this shader. The shader is intended for use in rendering full-screen quads or similar * geometry where only position is required. * * @remarks * - `layout(location = 0) in vec2 pos;` specifies the input attribute location. * - `gl_Position` is set using the input position with z = 0.0 and w = 1.0. * - The output `fragColor` is declared for compatibility with fragment shaders. */ export const MAIN_VERT: string = ` layout(location = 0) in vec2 pos; out vec4 fragColor; void main() { gl_Position = vec4(pos.xy,0.0,1.0); } `; /** * GLSL vertex shader source code for a simple buffer. * * This shader takes a 2D position attribute (`pos`) as input and sets the `gl_Position` * for each vertex. It also declares an output variable `fragColor`, which can be used * in the fragment shader stage. The shader is intended for use in rendering full-screen * quads or similar geometry where only position data is required. * * @remarks * - The input attribute `pos` is expected at location 0. * - The output `fragColor` is declared but not assigned in this shader; it is typically * used in the fragment shader. */ export const BUFFER_VERT: string = ` layout(location = 0) in vec2 pos; out vec4 fragColor; void main() { gl_Position = vec4(pos.xy,0.0,1.0); } `; /** * GLSL fragment shader source for chroma key compositing. * * This shader blends a foreground (webcam) texture with a background texture * using chroma keying (typically for green screen effects). It converts colors * from RGB to YUV space to perform color similarity checks, allowing for * configurable tolerance via the `maskRange` uniform. * * Uniforms: * - `time`: Current time (unused in this shader). * - `resolution`: The resolution of the output image. * - `webcam`: Foreground texture (e.g., webcam feed). * - `background`: Background texture to composite behind the foreground. * - `chromaKey`: The chroma key color to remove (in RGBA). * - `maskRange`: vec2 specifying the inner and outer tolerance for chroma keying. * * Outputs: * - `fragColor`: The final composited color for each fragment. * * The shader uses a helper function `colorclose` to determine how close a pixel's * color is to the chroma key color in YUV space, and blends the foreground and * background accordingly. */ export const BUFFER_FRAG: string = ` uniform float time; uniform vec2 resolution; uniform sampler2D webcam; uniform sampler2D background; uniform vec4 chromaKey; uniform vec2 maskRange; out vec4 fragColor; mat4 RGBtoYUV = mat4( 0.257, 0.439, -0.148, 0.0, 0.504, -0.368, -0.291, 0.0, 0.098, -0.071, 0.439, 0.0, 0.0625, 0.500, 0.500, 1.0 ); float colorclose(vec3 yuv, vec3 keyYuv, vec2 tol) { float tmp = sqrt(pow(keyYuv.g - yuv.g, 2.0) + pow(keyYuv.b - yuv.b, 2.0)); if (tmp < tol.x) return 0.0; else if (tmp < tol.y) return (tmp - tol.x)/(tol.y - tol.x); else return 1.0; } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 fragPos = 1. - fragCoord.xy / resolution.xy; vec4 fg = texture(webcam, vec2(1.-fragPos.x,fragPos.y)); vec4 bg = texture(background, vec2(1.-fragPos.x,fragPos.y)); vec4 keyYUV = RGBtoYUV * chromaKey; vec4 yuv = RGBtoYUV * fg; float mask = 1.0 - colorclose(yuv.rgb, keyYUV.rgb, maskRange); fragColor = max(fg - mask * chromaKey, 0.0) + bg * mask; } void main(){ mainImage(fragColor,gl_FragCoord.xy); } `;