第十五章 OpenGL ES-VR 全景模式原理

第十五章 OpenGL ES-VR 全景模式原理

第一章 OpenGL ES 基础-屏幕、纹理、顶点坐标
第二章 OpenGL ES 基础-GLSL语法简单总结
第三章 OpenGL ES 基础-GLSL渲染纹理
第四章 OpenGL ES 基础-位移、缩放、旋转原理
第五章 OpenGL ES 基础-透视投影矩阵与正交投影矩阵
第六章 OpenGL ES 基础-FBO、VBO理解与运用
第七章 OpenGL ES 基础-输入输出框架思维
第八章 OpenGL ES 基础-MVP矩阵理解
第九章 OpenGL ES 基础-高斯模糊原理
第十章 OpenGL ES 基础-图像USM锐化
第十一章 OpenGL ES 基础-基础光照
第十二章 OpenGL ES 基础-色温、色调、亮度、对比度、饱和度、高光
第十三章 OpenGL ES-RGB、HSV、HSL模型介绍
第十四章 OpenGL ES-方框模糊(均值模糊)
第十五章 OpenGL ES-VR 全景模式原理
第十六章 OpenGL ES-桶形畸变算法-常用VR

VR 全景模式原理

VR 全景模式原理将画面渲染到球面上,相当于从球心去观察内部球面,观察到的画面 360 度无死角,与普通播平面渲染的本质区别在渲染图像部分,画面渲染到一个矩形平面上,而全景需要将画面渲染到球面,利用 OpenGL 构建一个球体。OpenGL ES 中所有 3D 物体均是由三角形构成的,构建一个球体只需要利用球坐标系中的经度角、维度角以及半径计算出球面点的三维坐标,最后这些坐标点构成一个个小矩形,每个矩形就可以分成 2 个三角形。
在这里插入图片描述

纬度和经度的含义:

1、首先,纬度是地球表面上某一点与赤道之间的角度,取值范围为-90度到+90度。经度是地球表面上某一点与本初子午线之间的角度,取值范围为-180度到+180度。
2、将纬度和经度转换为弧度表示。OpenGL中的数学函数通常使用弧度作为单位,因此需要将纬度和经度从角度转换为弧度。可以使用以下公式进行转换:
弧度 = 角度 * π / 180
3、根据转换后的纬度和经度计算右手世界坐标。右手世界坐标系是OpenGL中常用的坐标系,其中x轴指向右侧,y轴指向上方,z轴指向观察者的反方向。
首先,根据纬度和经度计算球面上的点的坐标。可以使用以下公式:

  • x = cos(纬度) cos(经度)
  • y = sin(纬度)
  • z = cos(纬度) sin(经度)
x=r*cosθ*sinsβ
y=r*sinθ
y=r*cosθ*cosβ

在这里插入图片描述

球体网格实现

// 这个函数 `createSphere` 用于根据指定的参数在3D空间中生成一个球体网格。

void VR_FullViewSphere3D::createSphere(float radius, int rings, int sectors, void *tag)
{
    // 定义必要的变量和常数
    float PI            = M3D_PI;
    float nowradius     = radius;
    int longtitude      = rings;
    int latitude        = sectors;
    float longtiRatio   = 1.0f;
    float latiRatio     = 2.0f;

    // 计算所需的顶点、纹理坐标和索引的总数
    int numPoints      = longtitude * (latitude + 1) * 3;
    int numTexcoords   = longtitude * (latitude + 1) * 2;
    int numIndices     = (longtitude - 1) * latitude * 6;

    // 为顶点数据、纹理坐标和索引分配内存
    m_vertexs1   = (float *)malloc(sizeof(float) * numPoints);
    m_texcoords1 = (float *)malloc(sizeof(float) * numTexcoords);
    m_indices1   = (short *)malloc(sizeof(short) * numIndices);

    int t = 0, v = 0, counter = 0;
    float theta = 0.0f, phi = 0.0f;

    // 生成顶点和纹理坐标
    for (int i = 0; i < longtitude; i++) {
        phi = (PI / 2 - i / (longtitude - 1 + 0.0) * PI) * longtiRatio;

        for (int j = 0; j < latitude + 1; j++) {
            theta = (j / (latitude + 0.0) * PI - PI / 2) * latiRatio;
            float r = -nowradius * (float)cosf(phi);

            float x = r * (float)sinf(theta);
            float y = nowradius * (float)sinf(phi);
            float z = r * (float)cosf(theta);

            // 分配顶点坐标
            m_vertexs1[v++] = x;  // X轴
            m_vertexs1[v++] = y;  // Y轴
            m_vertexs1[v++] = z;  // Z轴

            // 分配纹理坐标
            m_texcoords1[t++] = 1.0f - (float)((j + 0.0) / (latitude + 0.0)); // X轴
            m_texcoords1[t++] = (float)((i + 0.0) / (longtitude - 1.0));       // Y轴
        }
    }

    // 生成三角形的索引
    for (int i = 0; i < longtitude - 1; i++) {
        for (int j = 0; j < latitude; j++) {
            // 第一个三角形
            m_indices1[counter++] = (short)(i * (latitude + 1) + j);    // 上顶点
            m_indices1[counter++] = (short)(i * (latitude + 1) + j + 1); // 右上顶点
            m_indices1[counter++] = (short)((i + 1) * (latitude + 1) + j); // 下顶点

            // 第二个三角形
            m_indices1[counter++] = (short)((i + 1) * (latitude + 1) + j);
            m_indices1[counter++] = (short)(i * (latitude + 1) + j + 1);
            m_indices1[counter++] = (short)((i + 1) * (latitude + 1) + j + 1); // 右下顶点
        }
    }

    m_NumIndices = numIndices; // 存储生成的索引总数
}

这个方法根据给定的半径、环数和扇区数,在3D空间中创建一个球体网格。它计算用于渲染球体的顶点、纹理坐标和索引。

在计算球体的纬度角度(phi) 落在 [-π/2, π/2] 的范围时,也就是-90度到+90度,采用了如下的计算方式:

phi = (PI / 2 - i / (longtitude - 1 + 0.0) * PI) * longtiRatio;

这里的目的是为了在球体上均匀生成经线(经度)并控制其分布。详细解释如下:

  • (longtitude - 1 + 0.0):这里将(longtitude - 1)是类似计算机语言数组下标0开始,目的是为了避免整数相除后得到的结果被截断成整数。
  • i / (longtitude - 1 + 0.0):这一部分将当前经线编号i映射到一个范围在[0, 1]之间的值。当i=0时,表示顶端纬度,i=longtitude-1时表示底端纬度。
  • (PI / 2 - i / (longtitude - 1 + 0.0) * PI):根据上述得到的比例值,乘以π并减去π/2,可以将范围从[0, 1]映射到[π/2, -π/2]之间,即从顶端到底端的纬度范围。
  • longtiRatio:这个参数用于调节经度方向上的角度变化,影响经线所在的位置。

综上所述,这种计算方式能够确保在球体表面上沿着经线均匀生成点,并且通过调节longtiRatio参数,可以控制经线的分布密度或者改变球面形状。

在计算球体的经度角度(theta)落在 [-π, π] 的范围时,也就是-180度到+180度,采用了如下的计算方式:

theta = (j / (latitude + 0.0) * PI - PI / 2) * latiRatio;

这里的目的是为了在球体上均匀生成纬线(纬度)并控制其分布。详细解释如下:

  • (latitude + 0.0):将latitude转换为浮点数,以避免整数相除后结果被截断成整数。
  • j / (latitude + 0.0):将当前纬线编号j映射到一个范围在[0, 1]之间的值。当j=0时,表示经线从左侧开始,j=latitude时表示经线到达右侧。
  • (j / (latitude + 0.0) * PI - PI / 2):将上述比例乘以π并减去π/2,将范围从[0, 1]映射到[-π/2, π/2]之间,即从左侧到右侧的经线范围。
  • latiRatio:此参数用于调节纬度方向上的角度变化,影响纬线所在的位置,latiRatio=2实现-180度到+180度。
  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baoyu45585

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值