web平台使用threejs实现三维视频融合的思路

本文探讨了如何使用threejs在web平台上实现三维视频融合。通过创建纹理并将其投射到物体上,利用shader编程和相机设置来模拟投影效果。文章介绍了两种方案,一种涉及复杂的shader编程,另一种则是利用深度测试简化处理。文中还提供了实现效果的示例和参考资源。
摘要由CSDN通过智能技术生成

web平台使用threejs实现三维视频融合的思路

案例

  • 相必大家都看到网上的三维视频融合案例,如这里的https://blog.csdn.net/lxg9305171/article/details/79970009
  • 在这里插入图片描述
  • 这里的 https://zhuanlan.zhihu.com/p/92525723
    在这里插入图片描述
  • 怎么样,第一眼看到是否有点惊叹,可能曾几何时自己也会有这种想法,但一想到是3维的,还要各种矩阵运算,坐标变换,于是就懵圈了,然后就不了了之了,但现在既然看到有人做出来了,说明再困难也是可以啃过去的
  • 于是我又重拾信心,想探讨一下这种效果在web端实现的可能性
  • 于是我找到了web平台的开源3d库threejs,它可以让我们的三维开发变得更容易,比起你自己去搞webgl,那这个库简直就是救世主了
  • 工具算是有了,那么思路呢

方案一

  • 其实这种效果跟我们看到的投影仪的效果非常类似,就是把视频当做一片片纹理,投射到物体上,那么我们一开始别搞太复杂,能把一张纹理图投射出去就很不错了
  • 那么怎么投射呢,threejs有没有类似unity的投射器(projector)可以用呢。不好意思,我找了半天没看到跟project相关的字眼,如果threejs真的有,麻烦告知一声
  • 那最悲催的事情就来了,既然没有就得靠自己了,从写shader开始吧
  • 投射说白了其实就是你写一段shader程序,然后把shader扔给要投射的物体,物体在渲染时就根据你写的shader把纹理图映射过去,当然,事情肯定没有这么简单,这里主要是为了让你更加容易理解这个过程
  • 好吧,让人闻风丧胆的shader编程终究是避无可避的
  • 投射就好像在我们看到的场景中有个投影仪一样,那么我们在场景中就用一个相机来替代这个投影仪了,于是现在场景中有两个相机了,一个是我们在屏幕上看到的画面的相机,我们称他为主相机吧,另一个是就是投影相机了,用来投影纹理图的,这两个相机一般位置角度都是不同的,因此这个渲染就是我们的难点了
  • 怎么在主相机画面中看到投影相机的画面的投射,这确实是一个头疼问题,好在问题也不是不可以解决,就是要在顶点着色器里把顶点的世界坐标计算出来,然后通过raying这个关键字扔给片元着色器,这样片元着色器就拿到了要渲染的那个片元的世界坐标
  • 这个世界坐标有啥用呢,我们的投影相机老大说他要用这个坐标去判断一下是不是在他的视锥体内,不在他范围内他都没想理你
  • 还要用这个世界坐标去计算他在投影相机老大里的齐次裁剪坐标,然后去映射纹理
  • 投影相机老大还说了,要实现上面两点,必须得把他的视图矩阵和投影矩阵告诉他,不然他没法计算,于是你就要通过uniform关键字偷偷将它们传给片元着色器
  • 一切准备就绪,判断在不在投影相机的视锥体内主要就是靠齐次裁剪坐标,如果xyz三个分量的值都在[-w,w]中,那这个片元对应的点的世界坐标就在投影相机老大的地盘里了,在我(指投影相机)地盘里那自然要负起责任,把他的纹理映射坐标给计算出来了
  • 怎么计算,就是先把齐次裁剪坐标进行归一化变成ndc坐标(除以w分量就是了),然后再跟屏幕坐标(在opengl左下角才是原点)进行映射,这个映射是通过一个矩阵完成的
  • 到这里基本上投射也就完成了
  • 以下是顶点着色器
 		varying vec2 vUv;
        varying vec3 worldPos;//世界坐标


        void main()
            {
   
                vUv = uv;
                worldPos=(modelMatrix*vec4( position, 1.0 )).xyz;//获得世界坐标
                vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
                //projectionMatrix * mvPosition; 最终得到MVP矩阵
                glPos=gl_Position = projectionMatrix * mvPosition;
            }
  • 以下是片元着色器
		//目标纹理
        uniform sampler2D textureD;
        //需要传递投影相机的视图矩阵和投影矩阵
        uniform mat4 mviewMatrix;
        uniform mat4 mprojectionMatrix;


        //纹理坐标[0,1]
        varying vec2 vUv;
        //世界坐标
        varying vec3 worldPos;



        //射线的两个点以及平面的一个点和法向量
        vec3 RayPlaneIntersection(vec3 ray1,vec3 ray2,vec3 planePoint,vec3  planeVec)
        {
   
            vec3 p;
            float t;
            t = (dot(planeVec,planePoint) - dot(planeVec ,ray1)) / dot(planeVec,ray2);
            p = ray1 + t*ray2;
            return p;
        }
        //判断是否在投影相机里
        bool judgeInProjectCamera(vec3 worldPos){
   
            vec4 viewPos=mviewMatrix*vec4(worldPos,1.0);//得到在投影相机中相机坐标
            vec4 p_pos=mprojectionMatrix*viewPos;//得到在投影相机中的齐次裁剪空间
            p_pos=p_pos/p_pos.w;
           if(abs(p_pos.x)>1.0||abs(p_pos.y)>1.0||abs(p_pos.z)>1.0){
   
           return false;
           }else{
   
           return true;
           }
        }


        void main(void){
   

            vec4 mviewPos=mviewMatrix*vec4(worldPos,1.0);//得到在投影相机中相机坐标
            vec4 ngl_pos=mprojectionMatrix*mviewPos;//得到在投影相机中的齐次裁剪空间
            if(!judgeInProjectCamera(worldPos)){
   
                //说明点在视锥体外
                //discard; //丢弃片元
                gl_FragColor=vec4(1,1,1,0);

            }else{
   

                //if(worldPos.y>2.0){discard;return ;}//如果只想图片投射到地板上可以打开这个


        // ndc坐标转uv坐标矩阵,此矩阵只适用于屏幕坐标以左下角为原点的
        // 0.5  0.0  0.0  0.5
        // 0.0  -0.5  0.0  0.5
        // 0.0  0.0  0.5  0.5
        // 0.0  0.0  0.0  1.0
        mat4 texNormalMatrix=mat4
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值