• OpenGL 桶形畸变算法-常用VR


    OpenGL 桶形畸变算法-常用VR

    什么是桶形畸变?

    图像放大率随着距光轴的距离而减小。在这样的畸变中,直线在中心向外凸出,像桶一样。
    桶形畸变中,从图像的中心点到图像的边缘点图像的相对大小逐渐变小,看起来就像把一张正常大小的图片包裹在一个球上一样。鱼眼相机,就是利用这种类型的畸变将一个无限宽的物体平面映射成有限的图像区域来呈现出一种半球形状的效果的。当使用变焦镜头时如果把焦距调至镜头的中段就会出现桶形畸变,此外使用广角镜头时桶形畸变的效果最明显。

    在这里插入图片描述
    呈现效果
    在这里插入图片描述

    为什么要做桶形畸变?

    在VR眼镜中,为了获取得沉浸式的体验,需要给用户提供比较大的视场角(FOV),作为廉价的VR方案,肯定不可能在用户面前放上一个超大的曲面显示屏。替代方案就是在用户眼前小的显示屏上放置一个放大透镜。
    在这里插入图片描述
    这样有个靠近眼睛的透镜,可以让用户获得比较大的视场角,但这样做的代价就是光线经过透镜后会产生径向畸变,视角场越大,畸变就会越严重。

    桶形畸变公式

    网络上找到桶行畸变算法,查看了一下畸变比较大
    在这里插入图片描述
    在这里插入图片描述

    正常大多使用畸变算法两种公式

    
    // 公式1:
    float r2 = x * x + y * y;
    x *= 1.0 + k1 * r2 + k2 * r2 * r2;
    y *= 1.0 + k1 * r2 + k2 * r2 * r2;
    
    // 公式2:
    float r2 = x * x + y * y;
    x = 1.0 + k1 * r2 * r2 + k2 * r2 * r2* r2 * r2;
    y = 1.0 + k1 * r2 * r2 + k2 * r2 * r2* r2 * r2;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这两个公式都涉及桶形畸变算法,但在具体的实现上有一些差异:

    1. 公式 1

      • 然后对每个坐标点 ( (x, y) ) 应用畸变系数 ( k1 ) 和 ( k2 ),以使图像坐标受到径向距离 ( r ) 的影响。主要特点是对径向距离进行一次和二次畸变。
      • 这个公式中,在乘以畸变系数之前,坐标 ( (x, y) ) 已经被计算 ( r^2 ) 的值所影响。
    2. 公式 2

      • 这个公式通过多次乘以 r2 * r2来引入更高阶的畸变效应,即 ( k1 * r^4 ) 和 ( k2 * r^6 )。
      • 与公式 1 不同,此公式直接将 ( x ) 和 ( y ) 与四次方和六次方的 ( r^2 ) 相乘,从而导致了更强烈的畸变效果。主要特点是对径向距离进行二次和四次畸变。

    两个公式都可以用于实现桶形畸变效果,但第一个公式引入了一次和二次畸变项,而第二个公式则集中在四次畸变项上。您可以根据需要选择适合您的畸变效果的公式。

    我们这边采用第一种,第一个公式引入了一次和二次畸变项,对应shader写法:

    static const char* barreldistortionvertexSource =SHADER_STRING(
            attribute vec4 av_Position;
            attribute vec2 aTexCoord;
            varying vec2 vTexCoord;
            varying float vbarrelDistortion;
            varying float vblackEdgeValue;
            uniform mat4 u_Matrix;
            uniform float barrelDistortion;
            uniform float blackEdgeValue;
            varying float fx_DistortionMax;
            varying float fx_DistortionMin;
            varying float fy_DistortionMax;
            varying float fy_DistortionMin;
    
    
            uniform float fx_barrelDistortionMax;
            uniform float fx_barrelDistortionMin;
            uniform float fy_barrelDistortionMax;
            uniform float fy_barrelDistortionMin;
            void main() {
                vTexCoord = aTexCoord;
                vbarrelDistortion = barrelDistortion;
                vblackEdgeValue= blackEdgeValue;
                fx_DistortionMax = fx_barrelDistortionMax;
                fx_DistortionMin = fx_barrelDistortionMin;
                fy_DistortionMax = fy_barrelDistortionMax;
                fy_DistortionMin = fy_barrelDistortionMin;
                gl_Position =av_Position ;
            }
    
    );
    
    
    static const char* vr_fragment_barreldistortion ="#extension GL_OES_EGL_image_external : require\n"
            "        precision mediump float;\n"
            "        varying vec2 vTexCoord;\n"
            "        varying float vbarrelDistortion;\n"
            "        varying float vblackEdgeValue;\n"
            "        uniform sampler2D sTexture;\n"
            "        varying float fx_DistortionMax;\n"
            "        varying float fx_DistortionMin;\n"
            "        varying float fy_DistortionMax;\n"
            "        varying float fy_DistortionMin;\n"
            "        void main() {\n"
            "        if (vbarrelDistortion <= 0.0) {\n"
            "        gl_FragColor =texture2D(sTexture, vTexCoord);\n"
            "}\n"
            "        else\n"
            "{\n"
            "        vec2 uv=vTexCoord;\n"
            "        uv = uv * 2.0 - 1.0;\n"
            "        float demoScale = 1.8 - vblackEdgeValue;\n"
            "        uv *= demoScale;\n"
            "        float barrelDistortion1 = -0.068; // 0.441 K1 in text books\n"
            "        float barrelDistortion2 = 0.320000; // 0.156 K2 in text books\n"
            "        float r2 = uv.x*uv.x + uv.y*uv.y;\n"
            "        uv *= 1.0 + barrelDistortion1 * r2  + barrelDistortion2 * r2 * r2;\n"
            "        uv = 0.5 * (uv * 1.0 + 1.0);\n"
            "        vec4 color;\n"
            "        if(uv.x>fx_DistortionMax||uv.y>fy_DistortionMax||uv.x
            "        color = vec4(0.0,0.0,0.0,1.0);\n"
            "}else{\n"
            "        color = texture2D(sTexture, uv);\n"
            "}\n"
            "        gl_FragColor = color;\n"
            "}\n"
            "}";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    为了防止看不懂给出的图解说明
    在这里插入图片描述

  • 相关阅读:
    ROS2学习(六)Bag回放使用plotjugger
    git常见使用 --实习中用到的
    博达:经营管理再升级,从选对CRM开始
    2023年中国金属涂胶板行业供需分析:销量同比增长2.8%[图]
    Redis优化 RDB AOF持久化
    Cerebral Cortex:调节γ振荡可以促进大脑连接性而改善认知障碍
    NLP&KG&Others会议投稿
    C语言实现简单CRC校验
    K-近邻算法分类和回归
    在微信公众号上怎么搭建付费课程功能
  • 原文地址:https://blog.csdn.net/u012836015/article/details/136500612