元宇宙-漫游世界后与Cocos一起看湖南卫视直播

使用参考资源

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!

元宇宙-漫游世界后与Cocos一起看湖南卫视直播

https://www.kuokuo666.com/home/kk053.html

作者

KUOKUO众享

发布于

2022-11-16

更新于

2024-03-05

许可协议

评论