threejs实现绿幕视频透明播放

项目所需,开发全景平台时需要支持绿幕视频播放。先看疗效:

原视频
在这里插入图片描述

加入场景看效果
在这里插入图片描述
核心处理方式是写shader材质,在fragmentShader中做透明度的计算。透明度依赖背景色的选择、容错度的处理。

可以参考https://cloud.tencent.com/developer/article/1356177
当然,实现透明视频播放的方式有两种,一种用灰度,两分屏的方式;另一种就是绿幕视频,用纯色当背景处理透明度。
第一种:灰度透明视频
在这里插入图片描述
这种处理原理就是用右侧的灰度值计算透明度即可。两侧的是动态同步播放的。
shader编写

 gl_FragColor = vec4(texture2D(pointTexture, vec2(vUv.x/2., vUv.y)).rgb,
                texture2D(pointTexture, vec2(0.5+vUv.x/2., vUv.y)).r);

第二种 绿幕透明视频
在这里插入图片描述
用绿色或蓝色的偏多。这种处理起来,在头发边缘处,应该半透的地方会有特殊处理。
shader

		
            uniform sampler2D pointTexture;//注意新版的必须用pointTexture,用texture会报错
            uniform vec3 backColor;//背景色
            varying vec2 vUv;
            uniform float u_threshold;
            float u_clipBlack=0.2;
            float u_clipWhite=4.;

            float rgb2cb(float r, float g, float b){
    
     return 0.5 + -0.168736*r - 0.331264*g + 0.5*b; } 
            float rgb2cr(float r, float g, float b){
    
     return 0.5 + 0.5*r - 0.418688*g - 0.081312*b; } 
            float smoothclip(float low, float high, float x){
    
     if (x <= low){
    
     return 0.0; } if(x >= high){
    
     return 1.0; } return (x-low)/(high-low); }
            vec4 greenscreen(vec4 colora, float Cb_key,float Cr_key, float tola,float tolb, float clipBlack, float clipWhite)
            {
    
     
	            float cb = rgb2cb(colora.r,colora.g,colora.b); 
	            float cr = rgb2cr(colora.r,colora.g,colora.b); 
	            float alpha = distance(vec2(cb, cr), vec2(Cb_key, Cr_key)); 
                alpha = smoothclip(tola, tolb, alpha); 
                float r = max(gl_FragColor.r - (1.0-alpha)*backColor.r, 0.0); 
                float g = max(gl_FragColor.g - (1.0-alpha)*backColor.g, 0.0); 
                float b = max(gl_FragColor.b - (1.0-alpha)*backColor.b, 0.0); 
                if(alpha < clipBlack){
    
     alpha = r = g = b = 0.0; } 
                if(alpha > clipWhite){
    
     alpha = 1.0; } 
                if(clipWhite < 1.0){
    
     alpha = alpha/max(clipWhite, 0.9); } 
                return vec4(r,g,b, alpha); 
            }
            void main( void ) {
    
    

                gl_FragColor = vec4(texture2D(pointTexture, vUv).rgb, 1);

                float tola = 0.0; 
                float tolb = u_threshold/2.0; 
                float cb_key = rgb2cb(backColor.r, backColor.g, backColor.b); 
                float cr_key = rgb2cr(backColor.r, backColor.g, backColor.b); 
                gl_FragColor = greenscreen(gl_FragColor, cb_key, cr_key, tola, tolb, u_clipBlack, u_clipWhite);
                
            }

原理是用背景色与当前色做向量相似度计算,用于透明度的赋值。
1、计算key色的红、蓝分量,组成向量A。
2、计算目标颜色的红蓝分量,组成向量B。
3、计算两个向量的距离(一个分量在另一个分量上的投影)
当AB向量接近,alpha趋于1
AB向量很远,alpha趋于0
4、以alpha作为过滤指标,滤掉目标颜色rgb值中的key色分量,计算出该点的rgb值
5、将1-alpha作为该点的透明度值(rgba中的a)
6、将该点像素值设置为新的rgba

基本是这样的原理

猜你喜欢

转载自blog.csdn.net/mansir123/article/details/123850372
今日推荐