第十六章 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眼镜中,为了获取得沉浸式的体验,需要给用户提供比较大的视场角(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:

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

"}";

为了防止看不懂给出的图解说明

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: