前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >升采样(Upsampling)技术

升采样(Upsampling)技术

作者头像
逍遥剑客
发布2018-05-23 16:56:44
2.1K0
发布2018-05-23 16:56:44
举报

最近老是想着学习下Upsampling, 因为在做优化时这是一项非常实用的技术

参考AMD的PPT: Mixed Resolution Rendering, 有这么几种情况可以应用:

  • 把半透明元素(如粒子)单独画到一个小的BlendBuffer上, 再跟原场景混合, 减小填充率的负担
  • SSAO, 一般不会做FullSize的处理, 所以Upsampling基本上是必须的一步
  • 屏幕空间的软阴影, 同上
  • 间接光照, 实时计算量比较大, 所以也是低精度进行

或许这个关键词可以概括这项技术: Bilateral Upsampling

通常应用的前提条件或者说场景如下:

  • 延迟渲染, 有个DownSample过的DepthBuffer和原大小的DepthBuffer
  • 一些比较低频或者粒度要求没有那么高的效果, 画到1/4(或更小)大小的FrameBuffer上, 使用DownSample过的DepthBuffer做DepthTest
  • 低分辨率的效果叠加到原分辨率的场景上, 需要根据两个DepthBuffer的进行插值, 避免边缘出现锯齿状的走样

性能提升是显而易见的: 节省填充率, 节省采样带宽消耗, 节省显存等

缺点嘛是有一点点效果上的瑕疵, 不过一般用于低频的效果, 人眼很难注意到

这里有篇法文的文章不错, 连蒙带猜还是看得差不多能懂的:

http://bbs.demoscene.fr/code/upsampling-technique/msg11403/#msg11403

代码语言:javascript
复制
float SceneZ = ReadDepth( _In.UV ); // On lit le vrai Z full size

float2 UV = _In.UV - _dUV;  // Avec Unity, je dois mettre un offset sur les UV d'entrée... Don't ask !

float4 SkyZ;
SkyZ.x = tex2D( _TexDownsampledZBuffer, UV ).x; UV.xy += _dUV.xz;
SkyZ.y = tex2D( _TexDownsampledZBuffer, UV ).x; UV.xy += _dUV.zy;
SkyZ.z = tex2D( _TexDownsampledZBuffer, UV ).x; UV.xy -= _dUV.xz;
SkyZ.w = tex2D( _TexDownsampledZBuffer, UV ).x;UV.xy -= _dUV.zy;

float4 V[4];
V[0] = SampleValue( UV ); UV.xy += _dUV.xz;
V[1] = SampleValue( UV ); UV.xy += _dUV.zy;
V[3] = SampleValue( UV ); UV.xy -= _dUV.xz;
V[2] = SampleValue( UV ); UV.xy -= _dUV.zy;

// Compute bias weights toward each sample based on Z discrepancies
float WeightFactor = 2.0;
float ZInfluenceFactor = 0.001;
float4 DeltaZ = ZInfluenceFactor * abs(SceneZ - SkyZ);
float4 Weights = saturate( WeightFactor / (1.0 + DeltaZ) );

// Default UV interpolants for a normal bilinear interpolation
float2 uv = frac( UV.xy / _dUV.xy );

// This vector gives the bias toward one of the UV corners. It lies in [-1,+1]
// For equal weights, the bias sums to 0 so the UVs won't be influenced and normal bilinear filtering is applied
// Otherwise, the UVs will tend more or less strongly toward one of the corners of the low-resolution pixel where values were sampled
//
// Explicit code would be :
// float2 uv_bias  = Weights.x * float2( -1.0, -1.0 ) // Bias toward top-left
//   + Weights.y * float2( +1.0, -1.0 ) // Bias toward top-right
//   + Weights.z * float2( +1.0, +1.0 ) // Bias toward bottom-right
//   + Weights.w * float2( -1.0, +1.0 ); // Bias toward bottom-left
float2 uv_bias  = float2( Weights.y + Weights.z - Weights.x - Weights.w, Weights.z + Weights.w - Weights.x - Weights.y );

// Now, we need to apply the actual UV bias.
//
// Explicit code would be :
//  uv.x = uv_bias.x < 0.0 ? lerp( uv.x, 0.0, -uv_bias.x ) : lerp( uv.x, 1.0, uv_bias.x );
//  uv.y = uv_bias.y < 0.0 ? lerp( uv.y, 0.0, -uv_bias.y ) : lerp( uv.y, 1.0, uv_bias.y );
//
// Unfortunately, using branching 1) is bad and 2) yields some infinite values for some obscure reason !
// So we need to remove the branching.
// The idea here is to perform biasing toward top-left & bottom-right independently then choose which bias direction
// is actually needed, based on the sign of the uv_bias vector
//
float2 uv_topleft = lerp( uv, 0.0, saturate(-uv_bias) ); // Bias toward top-left corner (works if uv_bias is negative)
float2 uv_bottomright = lerp( uv, 1.0, saturate(uv_bias) ); // Bias toward bottom-right corner (works if uv_bias is positive)
float2 ChooseDirection = saturate( 10000.0 * uv_bias ); // Isolate the sign of the uv_bias vector so negative gives 0 and positive gives 1
uv = lerp( uv_topleft, uv_bottomright, ChooseDirection ); // Final bias will choose the appropriate direction based on the sign of the bias

// Perform normal bilinear filtering with biased UV interpolants
float4 FinalValue = lerp(
lerp( V[0], V[1], uv.x ),
lerp( V[2], V[3], uv.x ),
uv.y );
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2012年09月25日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
流计算 Oceanus
流计算 Oceanus 是大数据产品生态体系的实时化分析利器,是基于 Apache Flink 构建的企业级实时大数据分析平台,具备一站开发、无缝连接、亚秒延时、低廉成本、安全稳定等特点。流计算 Oceanus 以实现企业数据价值最大化为目标,加速企业实时化数字化的建设进程。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档