近期项目需求做一个透明背景的视频叠加摄像头的交互,于是去了解了一下透明背景视频的实现方法。
1、webm视频格式
首先想到的当然是先跟动画大哥交流能否制作出透明背景的视频,给出的答案是webm格式的视频是可以背景透明的,OK,拿到视频,放到项目中,chorme打开,完美播放,这也太简单了吧,但移动端是不会同意让你这么轻易就播放视频的,Safari,微信,都不支持,没办法,只能继续寻找方案。
2、CSS 样式去掉背景
利用css样式 mix-blend-mode 混合模式,有一个属性 screen 就是黑色和其它元素进行混合的时候表现为透明。但这种方法有一种情况没法解决,就是如果视频中有元素是半透明的就无法成功了。
有关这种方法详细描述可以参考链接:
如何让MP4 video视频背景色变成透明?
3、webgl 渲染带透明通道的视频
首先,你需要一个这样的视频
或者一个这样的视频
尽量使得视频尺寸宽高比为1:2或者2:1,这样渲染出来的视频就是1:1大小了。然后用webgl将视频渲染在画布上,渲染的同时将视频上下,或者左右进行叠加计算。
webgl渲染可以用three.js,上下叠加的代码如下:
let videoWidth=1080; //视频实际的宽度
//定义渲染器
var renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(new THREE.Color("lightgrey"), 0);
renderer.setSize(videoWidth, videoWidth);
//居中显示
renderer.domElement.style.position = "absolute";
renderer.domElement.style.top = (window.innerHeight - videoWidth) / 2 + "px";
renderer.domElement.style.left = (window.innerWidth - videoWidth) / 2 + "px";
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.Camera();
scene.add(camera);
//播放视频
var video = document.getElementById("video");
video.play();
//获取视频纹理
var texture = new THREE.VideoTexture(video);
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.format = THREE.RGBFormat;
//定义几何体
var geometry = new THREE.PlaneBufferGeometry(1, 1);
//处理视频纹理
var uniforms = {
time: { type: "f", value: 1.0 },
texture: { type: "sampler2D", value: texture }
var material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader:
`varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
fragmentShader:
`#ifdef GL_ES
precision highp float;
#endif
uniform float time;
uniform sampler2D texture;
varying vec2 vUv;
void main( void ) {
gl_FragColor = vec4(
texture2D(texture, vec2(vUv.x, 0.5 + vUv.y/2.)).rgb,
texture2D(texture, vec2(vUv.x, vUv.y/2.)).r
transparent: true
var mesh = new THREE.Mesh(geometry, material)
scene.add(mesh);
var animate = function() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
requestAnimationFrame(animate);
如果是左右,只需要改一下叠加的方向就行,代码中的 fragmentShader 属性改为如下:
fragmentShader:
`#ifdef GL_ES
precision highp float;
#endif
uniform float time;
uniform sampler2D texture;
varying vec2 vUv;
void main( void ) {
gl_FragColor = vec4(
texture2D(texture, vec2(vUv.x/2., vUv.y)).rgb,
texture2D(texture, vec2(vUv.x/2., vUv.y)).r
以上,完美解决视频背景透明问题。
建议大家视频的大小不要超过4M,否则手机会发烫并且可能会触发页面的重载,低版本的ios会因为渲染视频导致出现其他无法预知的bug。
近期项目需求做一个透明背景的视频叠加摄像头的交互,于是去了解了一下透明背景视频的实现方法。1、webm视频格式首先想到的当然是先跟动画大哥交流能否制作出透明背景的视频,给出的答案是webm格式的视频是可以背景透明的,OK,拿到视频,放到项目中,chorme打开,完美播放,这也太简单了吧,但移动端是不会同意让你这么轻易就播放视频的,Safari,微信,都不支持...
直播近年来的风头可以说是一时无两,游戏直播、颜值/才艺直播、带货直播;火爆的直播间通常有各种刷屏大礼物,通常是透明背景,这就是透明视频的主要用途之一;
多数视频格式并不支持alpha通道,支持alpha通道的视频格式可以参考文献:
List of video formats supporting alpha channels
少数视频格式支持alpha通道,如webm、mov等;其中webm是google的标准,是一种视频容器格式,内部编码一般是v
对应源码位置:cocos2d-x-3.3\cocos\render\CCTexture*
从Sprite谈起
Sprite其实内部必然包含一个纹理图片,但我们写代码时候用到的是传入一个图片路径,从下面看:
//直接 传入Texture2D 对象
Sprite* Sprite::createWithTexture(Texture2D *texture)
Sprite *sprite = ...
渲染驱动方式,事件驱动方式
this->addChild(pSprite, 0); 的第二个参数(int zOrder)表示要添加到this类对象中的顺序。是由里向外的方向。值越大表示越在外面。
CCNode:public CCObject
锚点就是改变作用点
坐标系转换函数:CCDirector::convertToGL(CCPoint);//z转换为O...