【问题标题】:How to render 360 x 235 degree FOV image with threejs?如何使用 threejs 渲染 360 x 235 度 FOV 图像?
【发布时间】:2019-08-24 11:06:12
【问题描述】:

我有一台相机可以拍摄声称代表 235 度视野的圆形图像,例如:

我有一些使用threejs 的经验,并使用它正确渲染存储为等角投影的360x360 图像 - 网络上有大量示例可以做到这一点。

但我想使用threejs 来渲染我的圆形图像,可能是球内的纹理。我查看了一些示例(例如https://threejs.org/examples/#webgl_panorama_dualfisheyeMapping image onto a sphere in Three.js),这些示例似乎为我指明了正确的方向,但我认为我对threejs 如何将这些部分组合在一起还不够了解。

第二个(眼球)似乎让我很接近,但遵循眼球代码恰好意味着我的图像显示了两次(我想这是有道理的,因为我的图像是方形的,并且纹理必须覆盖整个球体。

所以我尝试使用 SphereGeometry 构造函数的长版本来制作部分球体 (360 * 235),但更改 phi 给了我一个看起来像橙色缺失切片的东西。更改 theta 给了我正确的形状,但纹理没有正确放置。

所以我的总体问题是如何完成这项工作,但我认为困扰我的主要问题是:

  1. 是什么控制了纹理在网格上的绘制方式? (这样我就可以只绘制一次纹理,并且只在我需要的球体部分上)

  2. 我看到设置 UV 是必要的(geometry.faceVertexUvs?),我阅读了https://en.wikipedia.org/wiki/UV_mapping,所以我有点理解这意味着什么,但我不知道从哪里开始找出正确的 UV对于我的图像(仍然像数字 1 一样,如何阻止它显示在球体的“背面”)

【问题讨论】:

  • 问题是你的原始“圆形照片”缺少球体的一部分,或者换句话说,它只会填充等角投影的一部分,因此源代码应该考虑到它以某种方式:在圆周围添加一个边缘,“最多 360°”(但我不知道这是否是几何废话),或将圆形图像转换为“从 235 开始带有黑色条带的等角矩形”图像,然后包裹一个球体。

标签: javascript three.js texture-mapping


【解决方案1】:

好的,所以我去阅读了更多关于 UV 的信息,并做了很多实验。这是我大部分理解的工作代码(只是相关的部分):

var geometry = new THREE.SphereGeometry( 30, 256, 128, 0, Math.PI * 2, 0, Math.PI );
geometry.scale( - 1, 1, 1 );//inside out

var imgWidth = 0.8;//I thought this should be 235/360, but used trial and error for less fisheye distortion

var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
for ( i = 0; i < faceVertexUvs.length; i ++ ) {

    var uvs = faceVertexUvs[ i ];
    var face = geometry.faces[ i ];
    //y is top to bottom
    //z is in-out?
    //x is side-side? positive x is front, negative is back

    for ( var j = 0; j < 3; j ++ ) {
        var fvNj = face.vertexNormals[j];
        var yaw = Math.atan2(fvNj.z, fvNj.x)/(Math.PI); //around, -1 to 1
        var pitch = Math.asin(fvNj.y)/Math.PI; //height, -0.5 to 0.5
        pitch = pitch * -1 + 0.5;//flip and make zero to one
        pitch *= imgWidth;

        if(pitch < 0.5){
            //how to do fisheye correction??
            //var correction = (fvNj.x == 0 && fvNj.z == 0) ? 1 : (Math.acos(fvNj.y) / Math.sqrt(fvNj.x * fvNj.x + fvNj.z * fvNj.z)) * (2 / Math.PI);
            var x = Math.cos(yaw * Math.PI);// -1 to 1
            var y = Math.sin(yaw * Math.PI);// -1 to 1
            var u = 0.5 + x*pitch;
            var v = 0.5 + y*pitch;  

            uvs[ j ].x = u;
            uvs[ j ].y = v;
        }else{
            uvs[j].x = 0;
            uvs[j].y = 0;
        }
    }
}

mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );

【讨论】:

  • 我不知道如何将您的原始图像放入此来源。
【解决方案2】:

如您所知,您的源图片不完整,因为它覆盖了 360x235。您必须“扩展”它以覆盖整个 360x360 球体。

我有一台相机,它也可以创建相同的图像;到目前为止,我无法找到完整的 javascript 源代码来获取这些原始图像、转换为正确的格式并在球体上变形,所以我不得不找到另一个解决方案:提前转换图像。

我为此使用 ffmpeg。

使用这个命令行:

ffmpeg -i qNfrX.jpg -vf v360=fisheye:e:ih_fov=235:iv_fov=235 test.jpg 

你会得到这张图片:

改用这个命令行:

ffmpeg -i qNfrX.jpg -vf v360=fisheye:e:ih_fov=235:iv_fov=235:pitch=-90 test2.jpg

使用不同的俯仰角,你会得到这个图像:

然后你可以使用一个这些equirectangular images来包裹一个球体,但在这我不能直接帮忙;也许这个来源可以提供帮助,但我仍在研究它:

https://github.com/legokichi/three-fisheye

【讨论】:

    猜你喜欢
    • 2014-07-08
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 2019-01-14
    • 1970-01-01
    • 2016-04-28
    • 2014-04-08
    相关资源
    最近更新 更多