在纹理球体上给出4个点提取2d平面并且它是投影纹理

时间:2017-06-07 15:43:06

标签: opengl swift3 opengl-es scenekit

设置场景 我正在研究scenekit中的一个功能,我在一个球体的中心有一个摄像头。球体周围有纹理。让我们说它是在房间内拍摄的360度图像。

到目前为止 我已经确定了球体上与地板角落相对应的位置。我可以从相机的角度提取并创建一个与地板尺寸相匹配的新平面2d平面。例如。如果房间有一个长长的矩形地板,我会创建一个梯形的平面。

问题 但我希望新的2d飞机具有地板的纹理,而不仅仅是形状。我如何做到这一点,因为我想要提取的不是原始纹理图像,而是投影到球体上的结果?

仅供参考我对scenekit和3d图形的东西很新,我甚至比opengl更新

1 个答案:

答案 0 :(得分:1)

我认为您的图像的结构可以让您直接选择任意方向的像素。例如。如果方向的方位角映射到图像的x坐标,并且方向的高度映射到图像的y坐标,则可以将方向转换为这些参数并在这些坐标处选择颜色。如果不是这种情况,则必须找到相应射线(从相机开始)与球体的交点,并在该交点处找到纹理坐标。然后,您可以使用此纹理坐标选择颜色。

现在,您基本上有两种选择。第一个选项是为平面生成新纹理。第二个选项是从着色器中采样球形图像。

选项1 - 生成新纹理

您知道平面的范围,因此您可以生成一个新的纹理,其尺寸与平面的范围成比例。您可以使用任意分辨率。您需要做的就是填充此纹理的像素。为此,您只需为给定像素生成光线,并在球形图像中找到相应的颜色,如下所示:

input: d1, d2, d3, d3 (the four direction vectors of the plane corners)
//  d3 +------+ d4
//  d1 +------+ d2
for x from 0 to texture width
    for y from 0 to texture height
        //Find the direction vector for this pixel through bilinear interpolation
        a = x / (width - 1) //horizontal interpolation parameter
        b = y / (height - 1) //vertical interpolation parameter
        d = (1 - a) * ((1 - b) * d1 + b * d3) + a * ((1 - b) * d2 + b * d4)
        normalize d
        //Sample the spherical image at d
        color = sample(d)
        //write the color to the new planar texture
        texture(x, y) = color
    next
next

然后,您有一个可以应用于平面的新纹理。如果将平面表示为两个三角形,则重心插值可能更合适。但只要飞机是矩形的,结果就会一样。

请注意,sample()方法取决于您的图像结构,需要正确实施。

选项2 - 着色器中的样本

在选项2中,您执行与选项1中相同的操作。但是您可以在片段着色器中执行此操作。您使用平面的顶点及其各自的方向(这可能只是顶点位置)并让GPU插值它们。这样可以直接指向您可以使用的方向d。这是一些伪着色器代码:

in vec3 direction;
out vec4 color;
void main()
{
    color = sample(normalize(direction));
}

如果您的图像是立方体贴图,您甚至可以让GPU进行采样。