立体渲染(Stereo Rendering)



GPU架构浅析
首发于 GPU架构浅析
写文章
Multi-View与Multi-Viewport

Multi-View与Multi-Viewport

14 人赞了该文章

随着VR的流行,内置地支持multi-view和multi-viewport已经成为GPU的一种需要。当前GPU主要通过支持已有的扩展来内置实现multi-view和multi-viewport,本篇对常见的几个扩展做下总结。

1. Stereo rendering与Multi-view

Stereo Rendering(立体渲染)是一种让人眼能感受到立体效果的渲染方式,为给予人眼立体效果,需要2个Camera对同一个场景进行成像,即设置不同的View矩阵渲染两张图像,这两张略有差异的图片能使人眼感觉出深度。

在普通的pipeline下,立体渲染的一种方案是在Vertex Shader中实现按不同View渲染两次[1]:

Set MVP_L for left camera
Rendering Geometry
Set MVP_R for right camera
Rendering Geometry

可以看到,同样的Geometry被重复渲染了两遍,CPU-GPU的带宽加倍,而这两份Geometry大部分Shading计算(如Model Transform,Attribute计算等)是相同的,仅仅只有View矩阵存在差异。这些数据或计算上的冗余显然可以在GPU内部优化,以提高Performance

另一种方案是起Geometry Shader,在GS里边给每个View送出各自的position或attribute:

for(int view_id  =0; view_id < 2; view_id++)
{
    MVP = MVP_Matrix[view_id];
    gl_Position = MVP * in_position;
}

这样能避免CPU-GPU带宽问题,同时可以避免相同属性的重复运算,但GS的performance本身并不理想。在GS单个Shader中loop过多的顶点属性,本身会使用较多资源,进而限制Shading的并行度。

OVR_multiview扩展旨在让GPU支持更高效的Multiview rendering(最常见是2个View),启用该扩展时,GPU将在Vertex Shader(VS)中loop,使用ViewID得到per-view的属性,如position和依赖于view的normal(OVR_multiview只允许position依赖于view_ID,不过新的扩展OVR_multiview2放宽了限制,允许其他属性根据view_ID取值)。

新的函数FramebufferTextureMultiviewOVR与FramebufferTextureMultiview类似,但它会使支持该扩展的GPULoop多次。

FramebufferTextureMultiviewOVR( enum target, enum attachment, uint texture, int level, int baseViewIndex, sizei numViews );

一个简单的例子[2],在VS中,我们用modelViewProjection[gl_ViewID_OVR]获取MVP矩阵,而同样的几何体会被渲染两遍,第一次gl_ViewID_OVR=0,第二次gl_ViewID_OVR=1。

#version 300 es
#extension GL_OVR_multiview : enable
layout(num_views = 2) in;
in vec3 vertexPosition;
in vec3 vertexNormal;
uniform mat4 modelViewProjection[2];
uniform mat4 model;
out vec3 v_normal;
void main()
{
gl_Position = modelViewProjection[gl_ViewID_OVR] * vec4(vertexPosition, 1.0);
v_normal = (model * vec4(vertexNormal, 0.0f)).xyz;
}
#version 300 es
precision mediump float;
in vec3 v_normal;
out vec4 f_color;
vec3 light(vec3 n, vec3 l, vec3 c)
{
float ndotl = max(dot(n, l), 0.0);
return ndotl * c;
}
void main()
{
vec3 albedo = vec3(0.95, 0.84, 0.62);
vec3 n = normalize(v_normal);
f_color.rgb = vec3(0.0);
f_color.rgb += light(n, normalize(vec3(1.0)), vec3(1.0));
f_color.rgb += light(n, normalize(vec3(-1.0, -1.0, 0.0)), vec3(0.2, 0.23, 0.35));
f_color.a = 1.0;
}

Shader里输出各自数据给每个View,使用ViewID索引出相应的数据,渲染结果被写到2D array texture的两个slice中,在VR设备中会显示到两个屏幕上。


OVR_multiview除了用来给2只眼睛发送各自的view外,另一个可能的用途是给每只眼睛送出2笔不同分辨率的View,人眼成像通常是中心清晰而周围模糊些。因此,对于中心出给高分辨率,四周给低分辨率,这样可减少像素的渲染。

不过,OVR_multiview还是有不少的限制:
不支持transform feedback(DX的Stream output)、tessellation control or evaluation shaders以及geometry shader

2. Multi Viewport

扫描二维码关注公众号,回复: 1449517 查看本文章

2.1 NV_viewport_array2

Multi-viewport,即在一个Shader中把primitive同时渲染到多个Viewport上去时。Geometry Shader是最常规的选择,因为只有GS才能看到整个per-primitive的build-in属性gl_ViewportIndex。 NV_viewport_array2扩展便是为了支持比GS Loop更高效的Multi-viewport, 应用可在Vertex Shader/Control Shader/Evaluatoin Shader/Geometry Shader设置build-in属性gl_ViewportMask指定需要发送的viewport,而GPU原则上可用可编程或Fixed Function的方式,在Raster之前Loop每个有效的viewport,并把Raster结果送出。

通过viewport_relative声明,NV_viewport_array2还支持把vertex emit到不同的layer上

 layout (viewport_relative) out highp int gl_Layer;

因此,GPU内部的逻辑过程大概是这样子的:

//In a vertex shader or evaluation shader
for(int i=0; i<Viewport_Num; i++
{
  if((viewport_mask>>i)&1)
  {
     gl_layer+=(viewport_relative) ? i : 0;
  }
  
  Emit vertex;

  }
}

这个扩展被Nvidia Maxwell用于cubemap rendering的加速


2.2 NV_viewport_swizzle

在一些multi viewport的应用中(比如通过单个pass把primitive渲染到cube的6个面上),有时顶点position可能需要简单的修改,比如通过翻转,XY坐标的互换来简单调整每个面上物体的朝向。NV_viewport_swizzle支持per-viewport swizzle,应用可以通过函数设置XYZW的swizzle方式

    void ViewportSwizzleNV(uint index,
                           enum swizzlex, enum swizzley,
                           enum swizzlez, enum swizzlew)

其中swizzlex,swizzley,swizzlez,swizzlew的取值可以是

        VIEWPORT_SWIZZLE_POSITIVE_X_NV                  
        VIEWPORT_SWIZZLE_NEGATIVE_X_NV                  
        VIEWPORT_SWIZZLE_POSITIVE_Y_NV                  
        VIEWPORT_SWIZZLE_NEGATIVE_Y_NV                  
        VIEWPORT_SWIZZLE_POSITIVE_Z_NV                  
        VIEWPORT_SWIZZLE_NEGATIVE_Z_NV                  
        VIEWPORT_SWIZZLE_POSITIVE_W_NV                  
        VIEWPORT_SWIZZLE_NEGATIVE_W_NV                  

以swizzlex为例,对于这8中swizzle方式,GPU将对position坐标做不同的调整:

        if (swizzlex == VIEWPORT_SWIZZLE_POSITIVE_X_NV) x' = x;
        if (swizzlex == VIEWPORT_SWIZZLE_NEGATIVE_X_NV) x' = -x;
        if (swizzlex == VIEWPORT_SWIZZLE_POSITIVE_Y_NV) x' = y;
        if (swizzlex == VIEWPORT_SWIZZLE_NEGATIVE_Y_NV) x' = -y;
        if (swizzlex == VIEWPORT_SWIZZLE_POSITIVE_Z_NV) x' = z;
        if (swizzlex == VIEWPORT_SWIZZLE_NEGATIVE_Z_NV) x' = -z;
        if (swizzlex == VIEWPORT_SWIZZLE_POSITIVE_W_NV) x' = w;
        if (swizzlex == VIEWPORT_SWIZZLE_NEGATIVE_W_NV) x' = -w;

swizzle针对的坐标是clipping space坐标,即在转化成NDC坐标之前执行swizzle。设置设置适当的swizzle,可以借助GPU直接渲染到cube map的6个面上。

一个例子:

      layout(triangles) in;
      layout(passthrough) in Inputs {
        vec2 texcoord;
        vec3 normal;
        vec4 baseColor;
      }
      layout(passthrough) in gl_PerVertex {
        vec4 gl_Position;
      } gl_in[];
      layout(viewport_relative) out int gl_Layer;

      void main()
      {
        // Figure out which faces the primitive projects onto and
        // generate a corresponding viewport mask.
        uint mask = 0;
        for (int i = 0; i < 6; i++) {
          if (!shouldCull(face)){//If primitive don't project onto this face
            mask |= 1U << i;
          }
        }
        gl_ViewportMask = mask;
        gl_Layer = 0;
      }



3. w scaling与分辨率


NV_clip_space_w_scaling

通常渲染结束后,整张图像还需要做一次后处理——Barrel distortion(桶形失真),以抵消VR设备固有的pincushion distortion(枕形失真)。而经过Barrel distortion的图像的特点边沿的分辨率较低,这意味着原始图像靠近边沿的许多像素对最终的校正图像并无贡献[3]。


NV_clip_space_w_scaling为VR应用提供w-scaling的功能,通过AP为viewport指定两个参数xcoeff和ycoeff:

void ViewportPositionWScaleNV(uint index, float xcoeff, float ycoeff);

GPU负责在Perspective division和Viewport Transform之前对w做以下scaling:

w' = xcoeff * x + ycoeff * y + w;

对于4个象限设置不同符号的xcoeff/ycoeff(需要把所有Geometry重复画到4个同样的viewport上,但每次只scissor出一个象限),使得距离中心越远则w越大,分辨率越低。

GPU只负责做w-scaling使得分辨率呈线性变化,至于un-scaling和后处理(barrel distortion)还是需要AP完成。下面的fragment shader可以包含到后处理的Shader中,负责做un-scale,然后让后处理继续做barrel distortion。

        // Vertex Shader
        // Draw a triangle that covers the whole screen
        const vec4 positions[3] = vec4[3](vec4(-1, -1, 0, 1),
                                          vec4( 3, -1, 0, 1),
                                          vec4(-1,  3, 0, 1));
        out vec2 uv;
        void main()
        {
          vec4 pos = positions[ gl_VertexID ];
          gl_Position = pos;
          uv = pos.xy;
        }

        // Fragment Shader
        uniform sampler2D tex;
        uniform float xcoeff;
        uniform float ycoeff;
        out vec4 Color;
        in vec2 uv;

        void main()
        {
          // Handle uv as if upper right quadrant
          vec2 uvabs = abs(uv);

          // unscale: transform w-scaled image into an unscaled image
          //   scale: transform unscaled image int a w-scaled image
          float unscale = 1.0 / (1 + xcoeff * uvabs.x + xcoeff * uvabs.y);
          //float scale = 1.0 / (1 - xcoeff * uvabs.x - xcoeff * uvabs.y);

          vec2 P = vec2(unscale * uvabs.x, unscale * uvabs.y);

          // Go back to the right quadrant
          P *= sign(uv);

          Color = texture(tex, P * 0.5 + 0.5);
        }

Reference

[1] Optimizing Virtual Reality: Understanding Multiview

[2] Using multiview rendering - Mali Developer Center

[3] Optimizing VR renderers with OVR_multiview - Imagination Technologies

[4] NVIDIA OpenGL in 2016

图形处理器(GPU)
14 1 条评论
分享
收藏

文章被以下专栏收录

GPU架构浅析

GPU架构浅析
通过专栏与大家交流探讨GPU Pipeline相关的图形学知识,以及GPU架构问题。

推荐阅读

前端如何适配手机屏幕之viewport

前端如何适配手机屏幕之viewport

响应式网页开发基础:DPR 与 viewport

响应式设计与开发中,有两个重要的概念,一直会贯穿整个流程,但是又有很多人搞不清楚。它们就是 DPR 与 viewport,下面让我们看看这两个概念。什么是 DPR?我们知道在 Chrome 浏览器控制台…

响应式网页开发基础:DPR 与 viewport

响应式设计与开发中,有两个重要的概念,一直会贯穿整个流程,但又有很多人搞不清楚。它们就是 DPR 与 viewport,下面让我们看看这两个概念。什么是 DPR?我们知道在 Chrome 浏览器控制台 c…

前端每周清单第 31 期: iOS 11 Viewport 解析,Preact PWA 性能优化案例,JS 内存泄露分析

前端每周清单第 31 期: iOS 11 Viewport 解析,Preact PWA 性能优化案例,JS 内存泄露分析

1 条评论

切换为时间排序
安迪的夏
安迪的夏 11 个月前
去年帕斯卡发布会上,有一个VRworks方面的新特性Single Pass Stereo,基于多重同步投影技术,单次渲染再投射以实现左右的view
不过目前除了fun house似乎还没有什么实际应用...
多重同步投影的应用很宽泛,最直接的便是能解决三联屏这样的环绕透视的扭曲,其实哪怕16:9单屏都存在边缘扭曲的现象,不过这个技术的实现依赖于游戏开发者的附加,除了ansel以外其他诸多新技术都不是驱动层可调用的.
GPU架构浅析
首发于 GPU架构浅析
写文章
Multi-View与Multi-Viewport

Multi-View与Multi-Viewport

14 人赞了该文章

随着VR的流行,内置地支持multi-view和multi-viewport已经成为GPU的一种需要。当前GPU主要通过支持已有的扩展来内置实现multi-view和multi-viewport,本篇对常见的几个扩展做下总结。

1. Stereo rendering与Multi-view

Stereo Rendering(立体渲染)是一种让人眼能感受到立体效果的渲染方式,为给予人眼立体效果,需要2个Camera对同一个场景进行成像,即设置不同的View矩阵渲染两张图像,这两张略有差异的图片能使人眼感觉出深度。

在普通的pipeline下,立体渲染的一种方案是在Vertex Shader中实现按不同View渲染两次[1]:

Set MVP_L for left camera
Rendering Geometry
Set MVP_R for right camera
Rendering Geometry

可以看到,同样的Geometry被重复渲染了两遍,CPU-GPU的带宽加倍,而这两份Geometry大部分Shading计算(如Model Transform,Attribute计算等)是相同的,仅仅只有View矩阵存在差异。这些数据或计算上的冗余显然可以在GPU内部优化,以提高Performance

另一种方案是起Geometry Shader,在GS里边给每个View送出各自的position或attribute:

for(int view_id  =0; view_id < 2; view_id++)
{
    MVP = MVP_Matrix[view_id];
    gl_Position = MVP * in_position;
}

这样能避免CPU-GPU带宽问题,同时可以避免相同属性的重复运算,但GS的performance本身并不理想。在GS单个Shader中loop过多的顶点属性,本身会使用较多资源,进而限制Shading的并行度。

OVR_multiview扩展旨在让GPU支持更高效的Multiview rendering(最常见是2个View),启用该扩展时,GPU将在Vertex Shader(VS)中loop,使用ViewID得到per-view的属性,如position和依赖于view的normal(OVR_multiview只允许position依赖于view_ID,不过新的扩展OVR_multiview2放宽了限制,允许其他属性根据view_ID取值)。

新的函数FramebufferTextureMultiviewOVR与FramebufferTextureMultiview类似,但它会使支持该扩展的GPULoop多次。

FramebufferTextureMultiviewOVR( enum target, enum attachment, uint texture, int level, int baseViewIndex, sizei numViews );

一个简单的例子[2],在VS中,我们用modelViewProjection[gl_ViewID_OVR]获取MVP矩阵,而同样的几何体会被渲染两遍,第一次gl_ViewID_OVR=0,第二次gl_ViewID_OVR=1。

#version 300 es
#extension GL_OVR_multiview : enable
layout(num_views = 2) in;
in vec3 vertexPosition;
in vec3 vertexNormal;
uniform mat4 modelViewProjection[2];
uniform mat4 model;
out vec3 v_normal;
void main()
{
gl_Position = modelViewProjection[gl_ViewID_OVR] * vec4(vertexPosition, 1.0);
v_normal = (model * vec4(vertexNormal, 0.0f)).xyz;
}
#version 300 es
precision mediump float;
in vec3 v_normal;
out vec4 f_color;
vec3 light(vec3 n, vec3 l, vec3 c)
{
float ndotl = max(dot(n, l), 0.0);
return ndotl * c;
}
void main()
{
vec3 albedo = vec3(0.95, 0.84, 0.62);
vec3 n = normalize(v_normal);
f_color.rgb = vec3(0.0);
f_color.rgb += light(n, normalize(vec3(1.0)), vec3(1.0));
f_color.rgb += light(n, normalize(vec3(-1.0, -1.0, 0.0)), vec3(0.2, 0.23, 0.35));
f_color.a = 1.0;
}

Shader里输出各自数据给每个View,使用ViewID索引出相应的数据,渲染结果被写到2D array texture的两个slice中,在VR设备中会显示到两个屏幕上。


OVR_multiview除了用来给2只眼睛发送各自的view外,另一个可能的用途是给每只眼睛送出2笔不同分辨率的View,人眼成像通常是中心清晰而周围模糊些。因此,对于中心出给高分辨率,四周给低分辨率,这样可减少像素的渲染。

不过,OVR_multiview还是有不少的限制:
不支持transform feedback(DX的Stream output)、tessellation control or evaluation shaders以及geometry shader

2. Multi Viewport

2.1 NV_viewport_array2

Multi-viewport,即在一个Shader中把primitive同时渲染到多个Viewport上去时。Geometry Shader是最常规的选择,因为只有GS才能看到整个per-primitive的build-in属性gl_ViewportIndex。 NV_viewport_array2扩展便是为了支持比GS Loop更高效的Multi-viewport, 应用可在Vertex Shader/Control Shader/Evaluatoin Shader/Geometry Shader设置build-in属性gl_ViewportMask指定需要发送的viewport,而GPU原则上可用可编程或Fixed Function的方式,在Raster之前Loop每个有效的viewport,并把Raster结果送出。

通过viewport_relative声明,NV_viewport_array2还支持把vertex emit到不同的layer上

 layout (viewport_relative) out highp int gl_Layer;

因此,GPU内部的逻辑过程大概是这样子的:

//In a vertex shader or evaluation shader
for(int i=0; i<Viewport_Num; i++
{
  if((viewport_mask>>i)&1)
  {
     gl_layer+=(viewport_relative) ? i : 0;
  }
  
  Emit vertex;

  }
}

这个扩展被Nvidia Maxwell用于cubemap rendering的加速


2.2 NV_viewport_swizzle

在一些multi viewport的应用中(比如通过单个pass把primitive渲染到cube的6个面上),有时顶点position可能需要简单的修改,比如通过翻转,XY坐标的互换来简单调整每个面上物体的朝向。NV_viewport_swizzle支持per-viewport swizzle,应用可以通过函数设置XYZW的swizzle方式

    void ViewportSwizzleNV(uint index,
                           enum swizzlex, enum swizzley,
                           enum swizzlez, enum swizzlew)

其中swizzlex,swizzley,swizzlez,swizzlew的取值可以是

        VIEWPORT_SWIZZLE_POSITIVE_X_NV                  
        VIEWPORT_SWIZZLE_NEGATIVE_X_NV                  
        VIEWPORT_SWIZZLE_POSITIVE_Y_NV                  
        VIEWPORT_SWIZZLE_NEGATIVE_Y_NV                  
        VIEWPORT_SWIZZLE_POSITIVE_Z_NV                  
        VIEWPORT_SWIZZLE_NEGATIVE_Z_NV                  
        VIEWPORT_SWIZZLE_POSITIVE_W_NV                  
        VIEWPORT_SWIZZLE_NEGATIVE_W_NV                  

以swizzlex为例,对于这8中swizzle方式,GPU将对position坐标做不同的调整:

        if (swizzlex == VIEWPORT_SWIZZLE_POSITIVE_X_NV) x' = x;
        if (swizzlex == VIEWPORT_SWIZZLE_NEGATIVE_X_NV) x' = -x;
        if (swizzlex == VIEWPORT_SWIZZLE_POSITIVE_Y_NV) x' = y;
        if (swizzlex == VIEWPORT_SWIZZLE_NEGATIVE_Y_NV) x' = -y;
        if (swizzlex == VIEWPORT_SWIZZLE_POSITIVE_Z_NV) x' = z;
        if (swizzlex == VIEWPORT_SWIZZLE_NEGATIVE_Z_NV) x' = -z;
        if (swizzlex == VIEWPORT_SWIZZLE_POSITIVE_W_NV) x' = w;
        if (swizzlex == VIEWPORT_SWIZZLE_NEGATIVE_W_NV) x' = -w;

swizzle针对的坐标是clipping space坐标,即在转化成NDC坐标之前执行swizzle。设置设置适当的swizzle,可以借助GPU直接渲染到cube map的6个面上。

一个例子:

      layout(triangles) in;
      layout(passthrough) in Inputs {
        vec2 texcoord;
        vec3 normal;
        vec4 baseColor;
      }
      layout(passthrough) in gl_PerVertex {
        vec4 gl_Position;
      } gl_in[];
      layout(viewport_relative) out int gl_Layer;

      void main()
      {
        // Figure out which faces the primitive projects onto and
        // generate a corresponding viewport mask.
        uint mask = 0;
        for (int i = 0; i < 6; i++) {
          if (!shouldCull(face)){//If primitive don't project onto this face
            mask |= 1U << i;
          }
        }
        gl_ViewportMask = mask;
        gl_Layer = 0;
      }



3. w scaling与分辨率


NV_clip_space_w_scaling

通常渲染结束后,整张图像还需要做一次后处理——Barrel distortion(桶形失真),以抵消VR设备固有的pincushion distortion(枕形失真)。而经过Barrel distortion的图像的特点边沿的分辨率较低,这意味着原始图像靠近边沿的许多像素对最终的校正图像并无贡献[3]。


NV_clip_space_w_scaling为VR应用提供w-scaling的功能,通过AP为viewport指定两个参数xcoeff和ycoeff:

void ViewportPositionWScaleNV(uint index, float xcoeff, float ycoeff);

GPU负责在Perspective division和Viewport Transform之前对w做以下scaling:

w' = xcoeff * x + ycoeff * y + w;

对于4个象限设置不同符号的xcoeff/ycoeff(需要把所有Geometry重复画到4个同样的viewport上,但每次只scissor出一个象限),使得距离中心越远则w越大,分辨率越低。

GPU只负责做w-scaling使得分辨率呈线性变化,至于un-scaling和后处理(barrel distortion)还是需要AP完成。下面的fragment shader可以包含到后处理的Shader中,负责做un-scale,然后让后处理继续做barrel distortion。

        // Vertex Shader
        // Draw a triangle that covers the whole screen
        const vec4 positions[3] = vec4[3](vec4(-1, -1, 0, 1),
                                          vec4( 3, -1, 0, 1),
                                          vec4(-1,  3, 0, 1));
        out vec2 uv;
        void main()
        {
          vec4 pos = positions[ gl_VertexID ];
          gl_Position = pos;
          uv = pos.xy;
        }

        // Fragment Shader
        uniform sampler2D tex;
        uniform float xcoeff;
        uniform float ycoeff;
        out vec4 Color;
        in vec2 uv;

        void main()
        {
          // Handle uv as if upper right quadrant
          vec2 uvabs = abs(uv);

          // unscale: transform w-scaled image into an unscaled image
          //   scale: transform unscaled image int a w-scaled image
          float unscale = 1.0 / (1 + xcoeff * uvabs.x + xcoeff * uvabs.y);
          //float scale = 1.0 / (1 - xcoeff * uvabs.x - xcoeff * uvabs.y);

          vec2 P = vec2(unscale * uvabs.x, unscale * uvabs.y);

          // Go back to the right quadrant
          P *= sign(uv);

          Color = texture(tex, P * 0.5 + 0.5);
        }

Reference

[1] Optimizing Virtual Reality: Understanding Multiview

[2] Using multiview rendering - Mali Developer Center

[3] Optimizing VR renderers with OVR_multiview - Imagination Technologies

[4] NVIDIA OpenGL in 2016

图形处理器(GPU)
14 1 条评论
分享
收藏

文章被以下专栏收录

GPU架构浅析

GPU架构浅析
通过专栏与大家交流探讨GPU Pipeline相关的图形学知识,以及GPU架构问题。

推荐阅读

前端如何适配手机屏幕之viewport

前端如何适配手机屏幕之viewport

响应式网页开发基础:DPR 与 viewport

响应式设计与开发中,有两个重要的概念,一直会贯穿整个流程,但是又有很多人搞不清楚。它们就是 DPR 与 viewport,下面让我们看看这两个概念。什么是 DPR?我们知道在 Chrome 浏览器控制台…

响应式网页开发基础:DPR 与 viewport

响应式设计与开发中,有两个重要的概念,一直会贯穿整个流程,但又有很多人搞不清楚。它们就是 DPR 与 viewport,下面让我们看看这两个概念。什么是 DPR?我们知道在 Chrome 浏览器控制台 c…

前端每周清单第 31 期: iOS 11 Viewport 解析,Preact PWA 性能优化案例,JS 内存泄露分析

前端每周清单第 31 期: iOS 11 Viewport 解析,Preact PWA 性能优化案例,JS 内存泄露分析

1 条评论

切换为时间排序
安迪的夏
安迪的夏 11 个月前
去年帕斯卡发布会上,有一个VRworks方面的新特性Single Pass Stereo,基于多重同步投影技术,单次渲染再投射以实现左右的view
不过目前除了fun house似乎还没有什么实际应用...
多重同步投影的应用很宽泛,最直接的便是能解决三联屏这样的环绕透视的扭曲,其实哪怕16:9单屏都存在边缘扭曲的现象,不过这个技术的实现依赖于游戏开发者的附加,除了ansel以外其他诸多新技术都不是驱动层可调用的.

猜你喜欢

转载自blog.csdn.net/linuxheik/article/details/80519831