元宇宙-漫游世界后与Cocos一起看湖南卫视直播|征稿活动V5

使用参考资源

CocosCreator v3.6.2

cocomat 腾讯开源公共组件框架

Cocos Creator 3D特制 Video MeshRender 播放器(Cocos商店购买)

TcPlayer 腾讯开源 Web 播放器

视频流 hls 库

正文

场景漫游引发的思考

元宇宙,虚拟世界。OK,不同的人有不同的理解!在一个阳光明媚的上午,我偶然浏览到了一个炫酷的场景漫游视频,引发了我在 cocos 上实现的思考:

  1. 在 cocos 里实现场景漫游需要什么?

  2. 在 cocos 里能漫游预览什么?

  3. 社区里大家都实现过什么,有哪些没实现的?

  4. 在游戏里玩游戏,或者在游戏里刷视频是不是很好玩?

基础的漫游解决方案

3D 的场景漫游,首先最核心的就是摄像机运动,主角移动。逛逛商城,发现摇杆组件大家都封装过,有解决方案了。

摄像机位置移动,我想到了动画编辑器,或者是其他工具导出的一系列 Vec3 坐标点,让摄像机沿着移动,照着切线方向。也有解决方案了。

模型、粒子、模型动画,这些静态展示的,美工建模师都可以输出。

对了,有些场景需要 3D 文本,还有 2D 的 Spine 动画以 3D 的形式做展示,尝试解决了下这个。

cocos 的模型是直接放的,摄像机是动画编辑器编辑好路径与速度与旋转,进行播放的;文字与 spine 是单独一个分组摄像机渲染到一个 renderTexture 上,然后赋给材质,用 3D 物体平面渲染的 Plane。

如下图,一个摄像机分组为 show2,然后仅渲染该分组,渲染后的纹理赋值给材质,材质挂到 plane 上:

核心代码:


start() {

    this.renderTexture = new RenderTexture();

    this.renderTexture.initialize({ width: 720, height: 720 });

    this.show2Camera.targetTexture = this.renderTexture;

    this.show2Material.setProperty('mainTexture', this.renderTexture);

}

OK,文本和 spine 搞定了,相信大家也发现了上面演示 gif 最后的视频渲染,视频渲染是最有意思的。

视频渲染尝试

我先简单说说关于视频渲染到 webgl 里的原理:

在 Web 平台,我们知道 video 标签赋予一个 src 后便可以播放视频,那么想个办法把 video 标签的播放内容采集,形成纹理传进去呗!在 webgl 里渲染图片,我们会这样:


const gl = canvas.getContext('webgl');

const image = new Image();

image.src = "./kuokuo.png";

// 图片加载完渲染到 webgl

image.onload = function () {

    // ... 省略顶点配置,shader书写

    gl.activeTexture(gl.TEXTURE0);

    // 创建纹理对象

    const texture = gl.createTexture();

    gl.bindTexture(gl.TEXTURE_2D, texture);

    // 核心

    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

    // ... 省略配置 texture

    // 绘制

    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

};

大家可以看到,texImage2D 的最后一个参数就是原生的 image 对象,实际上就是绑定纹理数据进去。视频也是同理,texImage2D 这个方法最后一个参数可以直接传入 video 标签。那就 OK 了,只剩下最后一步,如何在 cocos 中实现?

在 CocosCreator v2.x 版本中,因为是 js 引擎代码,底层暴露不多,需要重写类。具体实现可以直接看 cocomat 封装的 CCMVideo 组件,其核心代码:

https://github.com/cocos/cocomat/blob/main/coco-mat/lib/CCMVideo/CCMVideo.ts


this.impl = document.createElement('video');

this.impl.crossOrigin = 'anonymous';

this.impl.autoplay = false;

this.impl.loop = false;

this.impl.muted = false;

// ....

this.update = dt => {

    if (this.isInPlaybackState()) {

        gl.bindTexture(gl.TEXTURE_2D, this.textures[0]._glID);

        // 核心

        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.impl);

        // @ts-ignore

        cc.renderer.device._restoreTexture(0);

    }

};

大家可自行查看。

关于 CocosCreator v3.x 版本中,引擎用 ts 重写了,底层也暴露了不少能力,就咱们谈的这个视频渲染,可以取 cc 下的 gfx 模块:


import { gfx } from 'cc';

// 就是上述的 gl

gfx.deviceManager.gfxDevice;

gfx.Device;

// 官方封装方法

gfx.Device.createTexture(...args);

gfx.Device.copyTexImagesToTexture(...args);

研究了好一阵终于搞出来,代码写的很乱,想整理下发官方商城,但发现有一个大佬已经写好了。针不戳!现在你的代码是我的了!

链接:https://store.cocos.com/app/detail/3726

原本研究就到此结束了,休息一下,搂着老婆看会电视!但是看着看着,我心想:在元宇宙里看电视该是多么炫酷的一件事呀!!!湖南卫视!整!

直播渲染尝试

先研究下网上已经有的直播拉流解决方案:m3u8,rtsp,rtmp,flv,mp4 等等,那大厂都用啥呢?去 B 站直播间逛下:

就决定是你了皮卡丘(m3u8),百度一波 m3u8 直播拉流的实现,发现了腾讯的 TcPlayer + hls 的实现方式,原生的 html 实验很简单,引入两个 SDK 然后 new 一个 TcPlayer 传入直播拉流地址就可以:


<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8">

    <title>直播测试</title>

    <script src="TcPlayer-2.3.3.js" charset="utf-8"></script>

    <script src="hls.min.js" charset="utf-8"></script>

</head>

<body>

    <div id="kuokuo_test_video" style="width:100%; height:auto;"></div>

    <script>

        window.kuokuoPlayer = new TcPlayer('kuokuo_test_video', {

            m3u8: "http://219.151.31.38/liveplay-kk.rtxapp.com/live/program/live/hnwshd/4000000/mnf.m3u8",

            autoplay: true,

            width: '500', //视频分辨率宽度

            height: '500' //视频分辨率高度

        });

    </script>

</body>

</html>

引入到 Cocos 里:

然后魔改了一波 Video MeshRender 播放器的代码,原理就是把我新建的一个用来播放湖南卫视直播的 video 标签,替换掉渲染的那个 video 标签,采集内容的原理都是一样的。

最终实现的效果:

舒服,可以在游戏里看电视直播了!

更多文章与分享

个人网站:www.kuokuo666.com

2022!Day Day Up!

12赞

大佬一如既往地优秀呀, 非常赞 :+1: :+1:

前排必火!

m3u8的延迟应该很高吧

不会,如果卡应该是后端处理的流卡了。前端拉流基本只跟网速有关,js 处理很快。b 站以及一些需要加密视频的网站基本都是 m3u8

头上要带个啥的话。
我宁愿带个摄像机
天天看美女
image

太棒了,公司正好要求在 3D 场景接入一个视频播放,nice!

1赞

有源码么?

大佬,有源代码可以发一份吗

代码里用了商城的商用组件,现在 cocos 商城里有多个现成的解决方案,思路一致

好的,我找找

如果是多个视频呢,会不会很卡

大佬具体在cocos里面怎么播放m3u8能说明一下码

cocos里不能播放 m3u8,能播放的是 html 里的 video 标签,然后读取 video 标签的数据做渲染。cocos store 里有。