• 元宇宙-漫游世界后与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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    大家可以看到,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);
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    大家可自行查看。

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

    import { gfx } from 'cc';
    // 就是上述的 gl
    gfx.deviceManager.gfxDevice;
    gfx.Device;
    
    // 官方封装方法
    gfx.Device.createTexture(...args);
    gfx.Device.copyTexImagesToTexture(...args);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

    链接: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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    引入到 Cocos 里:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P60qPiko-1668587004317)(https://www.kuokuo666.com/blogImgs/imgs-22/1115/show4.png)]

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

    最终实现的效果:

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

    更多文章与分享

    个人网站:www.kuokuo666.com

    2022!Day Day Up!

  • 相关阅读:
    如何使用html、css制作一个期末作业网站【羽毛球体育运动主题html网页设计】
    【SpringBoot】理解Spring Boot自动配置的底层原理
    基于Spring MVC + Spring + MyBatis的【超市会员管理系统】
    C++之OpenCV入门到提高003:矩阵的掩膜(Mask)处理
    sqllab第十七关通关笔记
    水稻插秧机分叉机构壳体零件数控加工工艺工装设计
    企业实施ERP系统遇到的问题及应对措施
    玩转gRPC—不同编程语言间通信
    深度强化学习-A3C算法
    基于Java+SpringBoot+MyBatis的高铁/火车售票/订票系统
  • 原文地址:https://blog.csdn.net/kuokuo666/article/details/127887798