分类 developer 下的文章

Cinemachine的Vcam在Origin shift后出现抖动

今天尝试给TPS挂接的VCam做OriginShifting。实现方式是在触发Shift的时候通过事件机制调用

OnTargetObjectWarped(_virtualCamera.Follow, offset); 

然后发现:

  • 在相机不进行任何旋转的时候状态正常
  • 在相机shift的瞬间如果正好相机在进行旋转的更新,那么shift后会抖动(jitter)一帧

参考 这个 帖子,查阅cinemachine相关文档,以及自己瞎摆弄了几次后,问题得到了解决

  1. 确保CinemachineBrain的Update Method使用SmartUpdate或LateUpdate,让Vcam的更新时机不早于触发Shift动作
  2. 将VCam中Aim部分的Look ahead Time 降为0。否则Shift后,其Target的位置出现了偏移,进而导致Look ahead对Target的Motion计算错误,从而导致抖动

关于shader中颜色的对比,rgb转lab颜色空间

shader中对比颜色的时候,不能直接使用rgb空间的值差来进行计算。因为这个空间并不能反映人眼对于颜色相近的定义。这个时候可以使用Lab*空间进行计算

But RGB is not "perceptually uniform", so your Euclidean RGB distance metric suggested by Vadim will not match the human-perceived distance between colors. For a start, Lab* is intended to be a perceptually uniform colorspace, and the deltaE metric is commonly used. But there are more refined colorspaces and more refined deltaE formulas that get closer to matching human perception.

转换后计算两个颜色值的deltaE来决定其近似程度

cie1.png

附相关计算代码

        float3 rgb2xyz( float3 c ) {
            float3 tmp;
            tmp.x = ( c.r > 0.04045 ) ? pow( ( c.r + 0.055 ) / 1.055, 2.4 ) : c.r / 12.92;
            tmp.y = ( c.g > 0.04045 ) ? pow( ( c.g + 0.055 ) / 1.055, 2.4 ) : c.g / 12.92,
            tmp.z = ( c.b > 0.04045 ) ? pow( ( c.b + 0.055 ) / 1.055, 2.4 ) : c.b / 12.92;
            const float3x3 mat = float3x3(
                0.4124, 0.3576, 0.1805,
                0.2126, 0.7152, 0.0722,
                0.0193, 0.1192, 0.9505 
            );
            return 100.0 * mul(tmp, mat);
        }

        float3 xyz2lab( float3 c ) {
            float3 n = c / float3(95.047, 100, 108.883);
            float3 v;
            v.x = ( n.x > 0.008856 ) ? pow( n.x, 1.0 / 3.0 ) : ( 7.787 * n.x ) + ( 16.0 / 116.0 );
            v.y = ( n.y > 0.008856 ) ? pow( n.y, 1.0 / 3.0 ) : ( 7.787 * n.y ) + ( 16.0 / 116.0 );
            v.z = ( n.z > 0.008856 ) ? pow( n.z, 1.0 / 3.0 ) : ( 7.787 * n.z ) + ( 16.0 / 116.0 );
            return float3(( 116.0 * v.y ) - 16.0, 500.0 * ( v.x - v.y ), 200.0 * ( v.y - v.z ));
        }

        float3 rgb2lab( float3 c ) {
            float3 lab = xyz2lab( rgb2xyz( c ) );
            return float3( lab.x / 100.0, 0.5 + 0.5 * ( lab.y / 127.0 ), 0.5 + 0.5 * ( lab.z / 127.0 ));
        }

        float getDeltaE(float3 a, float3 b)
        {
            return sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y) + (b.z - a.z) * (b.z - a.z));
        }

来源:
How to compare two colors for similarity/difference
How Is Color Measured? Calculating Delta E
Conversion between RGB and LAB colorspace shader for Unity.

Unity2019.3 URP7.1.8 环境下。Camera使用Opaque Texture的use pipeline settings选项无效

环境:Unity 2019.3,URP 7.1.8
Issue Tracker上并没有找到对应问题。也许是比较简单的bug所以没人在乎?

症状

本打算做个UI面板模糊效果,写shader的时候发现Unity在某个版本的SRP(HDRP / URP)中移除了原先通过GrabPass来拿_GrabTexture的方法,取而代之的是通过调整pipeline中的设置来获取
在pipeline settings中开启获取opaque texture,这样就可以在Shader中拿到一个名为_CameraOpaqueTexture的纹理数据,剩下的就按照原来_GrabTexture的方式来做就可以了
Unity_19Qs5EIpNw.png
Pipeline中这样设置之后,按理说相机上的Opaque Texture选项在使用Use Pipeline Settings的情况下,应该就能直接拿到这个纹理数据。tooltip上也是这么说的:
Unity_6M3dfiNyP4.png
但实际使用的时候,发现使用这个选项拿到的_CameraOpaqueTexture是一片纯灰色

解决

非常简单,在对应的相机上把Opaque Texture强制开启为On即可

一个主推的feature,在占据这么显著位置的选项居然不生效
虽然是个很小的问题,但给人感觉Unity官方无论在引擎大模块的重构方面还是在质量管理方面,很是混乱

UE4 3D Widget受后期影响问题的处理

UMG渲染时,若使用世界空间,则将使用Plane或Cylinder在场景中形成mesh的方式来处理。这样一来所有的Widget如同场景中的普通mesh,会出现在渲染管线中处理普通半透明物体的pass。此Pass位于所有后期pass之前。这样一来包括motion blur, tonemapping, TAA等均会影响Widget的显示

最为明显的症状是在相机移动时POI Widget上面的字出现严重模糊。Widget面板的颜色偏黄(Tonemapping)等

使用屏幕空间渲染则会被UE4以特殊的pass来handle(出现在后期之后,无法用renderDoc捕获),不会出现此问题

思路

让渲染3D Widget的pass出现在后期pass之后

做法

把Widget pass放到单独一个RT上

创建一个Render Target。注意将分辨率设置为与最终主相机输出的分辨率一致

使用sceneCapture2D component,与主相机同步。设置ShowOnlyComponet限制为只渲染场景中的3D Widget,并将结果输出到某个RT。注意bConsiderUnrenderedOpaquePixelAsFullyTranslucent需要为True

1571969089808.png

准备用于输出RT的pp

创建一个post processing类型的材质球。将blend location设置为After tonemapping。给此材质球设置一个Texture parameter

1571969746372.png

将给hack用的bp再增加一个单独的post processing component。用上一步创建的材质球初始化一份Dynamic Material Instance并喂给后期设置

1571969855165.png

1571969883633.png

让3D Widget材质使用User Interface 与 Trancelucent Blend的时候也能输出深度信息

这里可能涉及个trick

当Blend Mode为Trancelucent的时候,Widget Component开启Render CustomDepth Pass并不会生效(v4.23)。似乎需要在所用材质球中开启Allow Custom Depth Writes

但当材质球类型为User Interface的时候,其选项中是没有Allow Custom Depth Writes的。将材质球切换为surface后,该选项出现并勾选,再切换回User Interface,配合Widget Component上的选项,就能正常输出CustomDepth了

最后让Widget Component使用这个定制的材质球

更新sceneCapture2D的Transform和传递RT

1571971224113.png

后期材质球

思路是让Widget深度信息起效,处理遮挡

然后让传入的RT与常规pass做blend出最终结果

1571971031070.png

调整BP的更新时机

让Tick的更新时机处于物理更新后。否则RT会与主Pass结果差一帧,导致相机在快速移动时能看到明显的重影

1571971357444.png

最终结果

1571971537542.png

YouCompleteMe在Windows环境下安装折腾记录

YCM以安装设置繁琐出名
但最近的版本对于这方面已经有了相当的提升
只要确保环境配置满足需求,安装步骤相对以往会顺利很多
这里记录下在Win8.1系统环境下安装的流程和遇到的问题

通过Vundle安装应该是最方便的了

在vimrc中加上

Plugin 'valloric/youcompleteme'

保存后,执行

:source ~/_vimrc
:VundleInstall

来安装YCM在Vim部分的插件

接着开始配置环境

首先是Vim

Vim 7.4.1578 with Python 2 or Python 3 support
确保使用不低于7.4的带有python支持的vim版本
确保vim为utf8编码,确保在vimrc中有相关设置:

set encoding=utf-8

下一个,Python。Python2 或 Python3均可

x86还是x86-64看清楚
注意所用版本要与系统一致

安装CMake

安装Visual Studio Community

以前用了很久的2013。后来发现开发很多东西都要求高于此版本的VS了
干脆装个2017

安装VisualStudio 2015或更高版本。免费的社区版就行
并确保已包含下列组件:(这里的选择是我几次编译失败试出来的,不确保没有冗余)
Image.png

环境变量

需要注意的是,上文中提到组件中,无论是CMake还是python还是pip还是VS,确保其相关执行文件在系统的环境变量中
可以在命令行使用

echo %PATH%

检查一下

环境就绪,进入安装步骤

在cmd下进入ycm的目录。在我电脑上的路径如下:

cd %USERPROFILE%\.vim\bundle\youcompleteme\

执行官方推荐的方法:

python install.py --clang-completer

如果安装的VS不是2019版本,则会遇到以下错误:
Image2.png

可以通过参数(--msvc)更改所用VS版本
修改安装方法如下,2017为15,2015为14,依此类推

python install.py --clang-completer --msvc 15

等待打包编译和部分组件下载

这个步骤涉及下载,耗时可能会较久
中间也可能出现异常,并报出hash不一致的错误。这是由于网络状态不好或中断导致的
重来一遍即可

ycmd安装完成

完成后,重新打开Vim
有可能Vim里会直接提示YCMD server shutdown。YCM服务直接崩了
尝试查看错误log,发现对应的崩溃log是空的

经查发现
log空是因为ycmd在进入可记录log的状态之前就停掉了

通过手动启动ycmd的方法可以排查:

cd ~/.vim/bundle/YouCompleteMe/third_party/ycmd
cp ycmd/default_settings.json .
python ycmd --options_file default_settings.json

一般来说这一步会报python的错误,提示缺某个库。例如:

AttributeError: 'module' object has no attribute 'frozendict'

配置好pip,用pip安装对应的库。同时安装了python2和3的话要留意下对应的是哪个库
装好后再次尝试手动启动,很可能还会出现类似的错误,仍然是缺库
重复上述步骤直到执行后服务顺利启动(命令行状态下没有任何报错或者提示)
手动中止服务

根据YCM官网README的用法
将ycm目录\third_party\ycmd目录下的.ycm_extra_conf.py复制到对应的工程根目录

就绪

在vim中使用YcmRestartServer重启服务
若一切正常,vim会定位到刚才复制的.ycm_extra_conf.py,根据配置文件调整ycmd的启动
并出现如下提示:
Image3.png

OK即可