高级渲染配置

SDK默认生成的配置值是对渲染质量最佳的。

它也提供了灵活性。例如,你能做一些改变当建立渲染目标纹理时。

这节讨论你能做的改变当在渲染质量和性能之间做选择时。

图形API拷贝或硬件渲染粒度

SDK是被这样设计的,假定你要尽可能小心的使用你的视频内存和你能精确创建你需要的对的渲染目标大小。

然而,真正的视频卡和真实的图形APIs有一些尺寸现在(有一个最大值;也有一些最小值)。他们可能也有一些粒度限制,例如,只能创建渲染目标它们是一大批在32像素尺寸或有一个限度在可能方面比率。作为一个应用开发者,你能利用特别的约束去避免使用太多的图像内存。

除了上面说的之外,真实渲染目标表面的大小在内存中可以不是必须相同的和被渲染的部分。后者可能稍微小一点。然而,因为它作为一个视口被指定,它没有任何粒度约束。当你绑定渲染目标作为一个纹理,因为它的所有面被使用,所以UV坐标必须是正确的在不同的渲染大小和表面大小之间。API会为你做这些,但是你需要告诉它相关的信息。

下面的代码展示了两阶段方法去设置目标分辨率。代码首先调用ovr_GetFovTextureSize来计算渲染目标的理想大小。然后,调用图形库去建立一个期望分辨率的渲染目标。通常,由于平台和硬件的特异性,创建的纹理大小可能不同于请求的大小。

 // Get recommended left and right eye render target sizes.
    Sizei recommenedTex0Size = ovr_GetFovTextureSize(session, ovrEye_Left,
                                  session->DefaultEyeFov[0], pixelsPerDisplayPixel);
    Sizei recommenedTex1Size = ovr_GetFovTextureSize(session, ovrEye_Right, 
                                  session->DefaultEyeFov[1], pixelsPerDisplayPixel);

    // Determine dimensions to fit into a single render target.
    Sizei renderTargetSize;
    renderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w;
    renderTargetSize.h = max ( recommenedTex0Size.h, recommenedTex1Size.h );

    // Create texture.
    pRendertargetTexture = pRender->CreateTexture(renderTargetSize.w, renderTargetSize.h);

    // The actual RT size may be different due to HW limits.
    renderTargetSize.w = pRendertargetTexture->GetWidth();
    renderTargetSize.h = pRendertargetTexture->GetHeight();

    // Initialize eye rendering information.
    // The viewport sizes are re-computed in case RenderTargetSize changed due to HW limitations.
    ovrFovPort eyeFov[2] = { session->DefaultEyeFov[0], session->DefaultEyeFov[1] };

    EyeRenderViewport[0].Pos  = Vector2i(0,0);
    EyeRenderViewport[0].Size = Sizei(renderTargetSize.w / 2, renderTargetSize.h);
    EyeRenderViewport[1].Pos  = Vector2i((renderTargetSize.w + 1) / 2, 0);
    EyeRenderViewport[1].Size = EyeRenderViewport[0].Size;
传递给ovr_SubmitFrame的数据作为层描述的一部分。


你可以自由的选择渲染目标大小和左右眼视口作为你喜欢的,提供你指定的这些值当调用ovr_SubmitFrameusing时给ovrTexture.然而,使用ovr_GetFovTextureSize会确保你分配最佳大小给特殊的HMD在使用中。接下来描述怎样修改默认配置来权衡质量和性能。你应该也注意到API支持使用不同的渲染目标为每个眼如果这是你的引擎需要的。OculusWorldDemo允许你紧抓在使用一个单一渲染目标独立于每个眼,通过操纵设置菜单和选择共享渲染目标选项。

强制一个对称视野

API会为每个眼睛返回一个FOV它是不对称的,也就是左边到中心点的距离和右边的不同。

这是因为人们,就和Rift一样,有一个宽的FOV当看向外边时。当你看向里边时,你的鼻子会阻挡。我们也是向下看比向上看好。同样的原因,Rift的视图也不是对称的。它是通过镜头控制的,多种多样的塑料品的位,和屏幕边缘。精确的细节依赖你的脸形状,你的IPD,和你把Rift放在你脸的精确位置;所有这些建立在配置工具中和存储在用户的简况中。这些意味着几乎没有人有所有他们的FOV的四个边设置相同的角度,所以截面椎体产生会是偏离中心的。另外,大部分人的眼睛不会有相同的视野。它们会是接近的,但是极少是完全相同的。

作为一个例子,我们第一代的DK1头戴,作者的左眼有下面的FOV:

。53.6度向上

。58.9度向下

。50.3度向里(朝向鼻子)

。58.7度向外(远离鼻子)

在代码和文档中,这设计半角因为传统上一个FOV代表一个总边-边角度。在这个例子中,总水平FOV是50.3+58.7=109.0度,总垂直FOV是53.6+58.9=112.5度。

推荐的和最大视野能被从HMD访问就像下面展示:

ovrFovPort defaultLeftFOV = session->DefaultEyeFov[ovrEye_Left];

ovrFovPort maxLeftFOV = session->MaxEyeFov[ovrEye_Left];
DefaultEyeFov涉及到推荐的FOV值基于当前用户的profile设置。MaxEyeFov设计到最大FOV头戴能显示的最大角度不管profile设置。

默认值用额外的GPU加载提供一个好的用户体验。如果你的应用没有消耗大量的GPU资源,你可以使用最大FOV设置去减小依赖profile设置的精确度。你可以提供一个滑动条在应用控制面板中让用户能选择修改FOV设置在默认和最大值之间。但是,如果你的应用是使用GPU很严重,你可以减小FOV默认值就像改进性能通过减小视野中描述的。

上下左右的FOV角度是最方便的形式去设置选择或入口边界在你的图形引擎中。FOV的值也被用来去决定投影矩阵的使用在左右眼场景渲染期间。我们提供一个API使用函数ovrMatrix4f_Projection为这个意图:

ovrFovPort fov;

// Determine fov.
...

ovrMatrix4f projMatrix = ovrMatrix4f_Projection(fov, znear, zfar, 0);
这是普遍的FOV的顶和底边不同于左和右边当观看一个PC监视器时。一般的调用显示器的面比率,很少的显示器是正方形的。然而,一些图形引擎不支持偏离中心的截面椎体。为了兼容这些引擎,你需要修改FOV值通过ovrHmdDesc结构。大体上,这是好的扩展边比收缩它们。这会有一点紧张在图形引擎上,但是会给用户完全沉浸式的体验,甚至它们不能看到一些被渲染的像素。

一些图形引擎要求你表明对称的水平和垂直视野,一些需要一个较少的直接的方法就像一个水平FOV和一个面比率。一些对象频繁的变换FOV,可以强调两眼被设置为相同。下面的代码例子处理这个约束例子:

ovrFovPort fovLeft = session->DefaultEyeFov[ovrEye_Left];
ovrFovPort fovRight = session->DefaultEyeFov[ovrEye_Right];

ovrFovPort fovMax = FovPort::Max(fovLeft, fovRight);
float combinedTanHalfFovHorizontal = max ( fovMax.LeftTan, fovMax.RightTan );
float combinedTanHalfFovVertical = max ( fovMax.UpTan, fovMax.DownTan );

ovrFovPort fovBoth;
fovBoth.LeftTan = fovBoth.RightTan = combinedTanHalfFovHorizontal;
fovBoth.UpTan = fovBoth.DownTan = combinedTanHalfFovVertical;


// Create render target.
Sizei recommenedTex0Size = ovr_GetFovTextureSize(session, ovrEye_Left, 
                                                    fovBoth, pixelsPerDisplayPixel);
Sizei recommenedTex1Size = ovr_GetFovTextureSize(session, ovrEye_Right, 
                                                    fovBoth, pixelsPerDisplayPixel);

...


// Initialize rendering info.
ovrFovPort eyeFov[2];
eyeFov[0]                       = fovBoth;
eyeFov[1]                       = fovBoth;

...


// Compute the parameters to feed to the rendering engine.
// In this case we are assuming it wants a horizontal FOV and an aspect ratio.
float horizontalFullFovInRadians = 2.0f * atanf ( combinedTanHalfFovHorizontal );
float aspectRatio = combinedTanHalfFovHorizontal / combinedTanHalfFovVertical;

GraphicsEngineSetFovAndAspect ( horizontalFullFovInRadians, aspectRatio );
...
注意:你需要决定FOV在创建渲染对象之前,因为FOV影响一个给定质量的推荐渲染目标的大小。

通过减少像素密度改进性能

DK1有一个1280*800像素的分辨率,在两眼之间分离。然而因为宽的Rift的FOV和远景投射工作方式,媒介渲染目标的尺寸需求匹配现在的分辨率在足够高的显示器的中心。

例如,为了达到一个1:1像素映射在屏幕中心为作者的FOV设置一个DK1需求一个很大的渲染目标在2000*1056像素大小。

虽然现在的图形卡能渲染这个分辨率在需求的60HZ,未来的HMDs可能有足够高的分辨率。为了虚拟现实,低于60HZ提供了一个糟糕的用户体验;它一直是一个好方式来减小分辨率来维持帧率。这和一个用户有一个高分辨率2560*1600监视器一样。很少的3D应用能运行在全屏本地分辨率,所以很多应用允许用户选择一个低分辨率监视器放大一级去填充屏幕。

你能使用相同的策略在HMD上。那就是,运行它在一个低视频分辨率和让硬件为你放大一级。然而,这会产生两个过滤的步骤:一个是失真处理和一个视频放大。不幸的是,双过滤产生非常大的人工影响。它通常更影响留下视频模式在本地分辨率,除了媒介渲染目标的限制大小。这给一个相似的增长在性能上,除了更多细节。

一个解决方式是允许用户去调整分辨率通过一个分辨率选择器。然而渲染目标的真实分辨率依赖用户的配置,而不是一个标准硬件设置这意味着“本地分辨率”是不同对不同的人。另外的,呈现分辨率高比物理硬件分辨率能使用户混乱。他们不会理解选择1280*800是一个足够好的下降在质量上,虽然这个分辨率通过硬件指出。

一个好的选项是修改像素PerDisplayPixel值传递给ovr_GetFovTextureSize函数。这也能基于一个滚动条展现在应用渲染设置上。这判定相关的渲染目标像素的大小就和他们映射像素到显示器表面的中心。例如。0.5的一个值会减小渲染目标的大小从2000*1056到1000*528像素,可能允许中间范围PC图形卡维持60HZ。

float pixelsPerDisplayPixel = GetPixelsPerDisplayFromApplicationSettings();

Sizei recommenedTexSize = ovr_GetFovTextureSize(session, ovrEye_Left,  fovLeft, 
                                                   pixelsPerDisplayPixel);
虽然你能设置参数值大于1.0来产生一个高分辨率媒介渲染目标,Oculus没有观察到任何有用增加在质量上和它有一个高性能代价。

OculusWorldDemo允许你去尝试改变渲染目标像素密度。导航到设置菜单和选择像素密度。按上和下箭头键去调整像素密度在眼投射的中心。1.0的值设置渲染目标像素目标来显示表面1:1的点在显示器上。0.5的值设置渲染目标像素的密度为一半在显示器表面。另外的,你能选择Dynamic Res Scaling它会导致像素密度自动调整在0-1之间。


通过减少FOV改善性能

为了减少像素数在媒体渲染目标上,你能增加性能通过减少FOV-像素是被拉伸的。

依赖减少,这能导致隧道美景减少沉浸式的场景。然而,减少FOV增加性能有两个方式。最明显的是填充率。一个固定像素密度在视网膜,一个低FOV有少的像素。因为投射的属性数学,最外边FOV的边是最贵的在像素数的地位。第二个原因是这儿有少量对象可视的在每个帧中这意味着少量动画,少的状态变化和少的绘制调用。

减少FOV设置让玩家做一个非常痛苦的选择。一个虚拟现实的关键体验是沉浸式的在模拟世界中,和一个大范围的FOV。失去这些方面不是我们曾经推荐的。然而,如果你已经牺牲很多分辨率,应用一直没有运行在60HZ在用户的机器上,这是最后的一个手段选项。

我们推荐给玩家一个最大值FOV滚动条这意味着每个眼睛的FOV的四个边。

ovrFovPort defaultFovLeft = session->DefaultEyeFov[ovrEye_Left];
ovrFovPort defaultFovRight = session->DefaultEyeFov[ovrEye_Right];

float maxFovAngle = ...get value from game settings panel...;
float maxTanHalfFovAngle = tanf ( DegreeToRad ( 0.5f * maxFovAngle ) );

ovrFovPort newFovLeft  = FovPort::Min(defaultFovLeft, FovPort(maxTanHalfFovAngle));
ovrFovPort newFovRight = FovPort::Min(defaultFovRight, FovPort(maxTanHalfFovAngle));


// Create render target.
Sizei recommenedTex0Size = ovr_GetFovTextureSize(session, ovrEye_Left  newFovLeft, pixelsPerDisplayPixel);
Sizei recommenedTex1Size = ovr_GetFovTextureSize(session, ovrEye_Right, newFovRight, pixelsPerDisplayPixel);

...


// Initialize rendering info.
ovrFovPort eyeFov[2];
eyeFov[0]                       = newFovLeft;
eyeFov[1]                       = newFovRight;

...


// Determine projection matrices.
ovrMatrix4f projMatrixLeft = ovrMatrix4f_Projection(newFovLeft, znear, zfar, 0);
ovrMatrix4f projMatrixRight = ovrMatrix4f_Projection(newFovRight, znear, zfar, 0)
它可能是有趣的去尝试没有方形的FOV。例如,夹住足够的上和下范围当保留全水平FOV为一个‘Cinemascope’感觉。

OculusWorldDemo允许你去阐释减少FOV在默认之下。导航到设置菜单,选择Max FOV值。按下上和下箭头去改变最大角度在度数上。

通过单通道渲染改善性能

一个重大的立体渲染的消耗是渲染连个视图,每个眼睛一个。

一些应用,立体影像方面可能不是特别重要的和一个单通道视图可能是被接受的作为性能的回报。另一方面,一些用户可能获得眼紧张从一个立体视图和希望转换到一个单通道。然而,他们一直希望戴着HMD就像它给他们一个高FOV和头部追踪。

OculusWorldDemo允许用户抓紧单通道渲染模式通过按下F7键。

为了单通道渲染,你的代码应该用下面变换:

。设置FOV到最大对称FOV基于两个眼。

。调用ovhHmd_GetFovTextureSize和FOV去判定推荐的渲染目标大小。

。两眼的配置使用相同渲染目标和相同视口当调用ovr_SubmitFrame.

。渲染场景用共享渲染目标。

合并左右眼的FOV到一个单独媒介渲染。渲染一直是失真两次,每个眼一次,因为镜头不是精确的在用户的眼前面。然而,这一直是一个重大性能增加。

设置一个虚拟IPD为0意味着每件事似乎是巨大的和无限远的,所以用户会失去很多景深在场景中。

注意:这是重要的去缩放虚拟IPD和虚拟头部运动一起,如果虚拟IPD是设置为0,所有虚拟头部运动归于脖子运动也是被淘汰的。悲哀的,这失去很多景色归于平行。但是如果头部运动和IPD不同意,它能导致严重的失真和不舒服。谨慎尝试。


本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
目标效果:       程序运行出现图一walker的欢迎界面,从模糊变清晰,过了几秒自动跳到图二的导航界面,下边有小圆点表示第几个页面,第四个导航页面有一个Go按钮,点击跳转到登录界面。 项目压缩包: http://pan.baidu.com/s/1c2t11Kk 1.首先新建两个Android页面,生成WelcomeActivity.java页面和对应的xml布局,GiudeActivity.java页面和对应的xml布局。 2.activity_welcome.xml页面添加背景图。 activit
找了一段时间的实习,总结一下LeetCode上面试出现频率比较高的题,只总结一部分,后续还会继续更新。 一、Two Sum 题意是给出一个数组,输出和为k的两个数。数组为无序的。 这道题的解题思路是先把数组排序,再用两个指针,分别指向头和尾,并算出头和尾的和s,再把s与k比较,如果s小于k,头指针往后移,如果s大小k,尾指针往前移。直到找到为止。如果头尾指针相遇还没找到,则证明不存在。 代码如下: public class Main { public static void main(String[] a
移动APP现在发展的如火如荼,各大应用商店都涌现了一大批优秀的app产品,但是作为一名app的消费者,以及app开发工程师,我觉得今天有必要在这里和大家一起来探讨一下如何实现一个简单的app开发过程,或者说一个app的结构该大致怎么实现。 在市面上,我们所使用的大部分工具应用类型的app都是有一定的界面结构的( 类似淘宝,QQ, 微信 ),其中最主要的界面结构归纳起来就是使用 “ 导航栏(navigationBar) + 主视图(mainView)+工具栏(tabBar) ”来实现,如图所示:      
Android 系统从 2008 年到现在( 2016 年 4 月),八年时间里版本从 1.0 一直升到 6.0 ,由于 Android 系统更新速度快,导致市面上的 Android 设备运行的 Android 系统版本不一(专业术语叫碎片化严重) 2016 年的最新 Android 版本分布图(截止到 2016 年 1 月) ,从图中可以知道目前主流的系统是三款,但是还是有些版本的系统还在使用,作为 Android 程序开发者,必须尽量照顾到各种版本的系统,否则你提出的解决方案是不完善的,对于 Andr
Android开发艺术探索——第四章View的工作原理 4.1 (一)初识ViewToot和DecorView 基本概念 ViewRoot对应于ViewRootImpl类,是连接WindowManager和DecorView的纽带,View的三大流程均是通过ViewRoot来完成的。在ActivityThread中,当Activity对象被创建完成后,会将DecorView添加到View中。同时,会创建ViewRootImpl对象,并将ViewTootImpl对象和DecorView建立关联。 源码如下:
Android值Drawable系列:    一起来说说那些你不知道的Drawable: http://blog.csdn.net/mr_dsw/article/details/50998681 Android实践之Drawable的使用: http://blog.csdn.net/mr_dsw/article/details/50999818 开源项目circular-progress-button源码解析: http://blog.csdn.net/mr_dsw/article/details/512

实践--天气预报应用实例 - 2016-04-27 14:04:00

主要功能 省市县三级列表展示城市,按选择查询对应城市的当天天气和近期天气情况 可以手动的切换城市 可以手动更新天气以及后台的自动更新天气 自定义折线图显示近期的温度变化 桌面小组件实时显现天气和时间 效果图如下 这个小应用开发过程中用到的 自定义View–折线图 和 实践–桌面小组件之天气小组件 在前面的博客中都有讲解,如有疑惑,请前往查看。 数据的获取 http: //www .weather .com .cn /data/list3/city .xml 这个网址返回的是全国所有的省的数据,大家访问自行
本博客原地址: http://www.jianshu.com/p/b6fe647e368b (1)ButterKnife是什么? 在开发过程中,我们总是会写大量的findViewById和点击事件,像初始view、设置view监听这样简单而重复的操作让人觉得特别麻烦,当然不会偷懒的程序员不是好程序员,自然也出现了相应的解决方案–依赖注入。而ButterKnife则是依赖注入中相对简单易懂的很不错的开源框架,(其实ButterKnife也不算严格意义上的依赖注入,后面文章中会做分析)。但ButterKnif

Android5.0之NavigationView的使用 - 2016-04-27 14:04:25

导航菜单的制作方式多种多样,网上也有各种炫酷效果的具体实现方式,那么今天我主要是想来说说Google在Android5.0之后推出的NavigationView的具体使用方式。 NavigationView在很多App上都已经可以看到其效果图,国内的比如知乎(侧拉菜单滑出来的那一部分属于NavigationView),如下图: 还有Google自己的那些app,也基本全都采用了NavigationView,如下图,分别是Gmail、Google Map以及Google Play: OK,看完了图,接下来我

RCNN学习笔记(5):faster rcnn - 2016-04-26 22:04:16

reference link: http://blog.csdn.net/shenxiaolu1984/article/details/51152614 http://blog.csdn.net/xyy19920105/article/details/50817725 思想 从RCNN到fast RCNN,再到本文的faster RCNN,目标检测的四个基本步骤(候选区域生成,特征提取,分类,位置精修)终于被 统一到一个深度网络框架之内 。所有计算没有重复,完全在GPU中完成,大大提高了运行速度。  fa