关于纹理勾选sRGB的疑惑

1)关于纹理勾选sRGB的疑惑
​2)开启光照导致面片数增加
3)UGUI的Image修改材质属性疑问
4)UniWebView界面如何显示到Unity界面之后
5)Timeline的Internal_CreatePlayable开销很大


这是第254篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)

Rendering

Q:在UWA上搜到一个问答:https://answer.uwa4d.com/question/5bd1724fae74300ab0497bed,结论是:
linear space + gamma texture,勾sRGB
linear space + no gamma texture,不勾sRGB
好像Gamma Space下面这个sRGB勾不勾没有影响?

Player Setting里面的color space设置标识导入的图片是在Gamma Space中还是Linear Space中创建的,文档里面没有说清楚,希望大佬可以解释下。

根据这里的讨论:https://forum.unity.com/threads/confusion-about-gamma-vs-linear.496053,如果勾了sRGB之后Unity是做了gamma反矫正,即tex2D出来的value应该是pow(origin_color_value, 2.2),这里假设gamma值是2.2,那么在frag中,R通道的值应该就是反矫正过的,那么在heatmap的u的中间值应该是0.5左右,也就是上面那个讨论帖里面第一个headmap所示,但实际上却是第二个heatmap所示。

里面说是因为用color值做data而不是color的原因,这个解释太困惑了,因为不管做data还是做color,他们都是数字,数字的比较是不会出错的。

A1:Gamma Space下面这个sRGB 勾不勾确实没有影响。
在Linear Space下,如果勾了sRGB 之后,Unity是做了Remove Gamma Correction。那么图中值为0.5灰度,即u=0.5的那一列的灰度,经过Remove Gamma Correction,得到的值是0.25,如下图所示:


X轴代表光照强度,Y轴代表灰度值

 

蓝色线的Y值代表人眼的灰度值,视觉灰度值;红色线代表物理空间的实际灰度值,与光照强度成正比。

Photo渐变图中u=0.5的那一列的灰度值为0.5,是视觉灰度值,经过Remove Gamma Correction之后,得到实际灰度值0.25。在Fragment Shader中参与计算。所以显示的是第二张heat map。

感谢June@UWA问答社区提供了回答

A2:可以参考这篇文章:https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-24-importance-being-linear

说下我的理解:一般情况下,我们看到的图片是在“显示器空间”,在显示器中看到的图片颜色是正常的,是因为这个图片本身是经过GammaCorrection的,就是原始的数值经过1/2.2次幂操作,对于这样的图片,我们可以理解为是非线性的。在Unity选择了Linear空间后,对于这样的非线性的图片,需要将其勾选sRGB才能正确地渲染。图片勾选sRGB后,在内存中的格式会变成ETC2_EAC_RGBA8_SRGB的格式(假设图片选择ETC2 8bits的压缩格式),如下图:

 

不勾选sRGB,是ETC2_RGB8_UNORM格式,如下图:

 

对于这种_SRGB后缀的格式,GPU在进行纹理采样的时候,会自动将其移除GamaCorrection,即将数值做2.2次幂操作,但是不会对原始数据做修改。在Gamma空间中,不论勾选还是不勾选sRGB,格式都是ETC2_RGB8_UNORM。

说回题主的问题:在Gamma空间中,渲染出的结果是均等的4种颜色,因为在Gamma空间中,是不会做移除GammaCorrection操作的,这说明,这个“非线性图片”在u=0.5的时候(u是纹理uv坐标),纹理中的data value=0.5,当变成了Linear空间后,data没有发生变化,还是在u=0.5的时候data=0.5,勾选了sRGB后,在进行纹理采样的时候,GPU将值做了2.2次幂操作,就变成了0.25左右,因此当u<=0.5的时候,color.r<=0.25,根据Shader计算color.r<0.25时都是红色,即u<=0.5时,都是红色,于是就有一半颜色都是红色了。

感谢Xuan@UWA问答社区提供了回答


Rendering

Q:Unity显示的面数,应该是这一帧上传到GPU的所有顶点数据所决定的,那为什么GPU不会对这部分做个缓存呢?因为开启光照时,面数增加,相当于多次上传了模型的顶点数据,这部分如果缓存下来,不是可以提升很大性能吗?如果GPU不能做这个缓存,是不是说GPU的缓存太小,没有这个空间,或者是GPU并不能确认哪些要缓存?如果是改引擎代码,可以针对项目去做缓存。

A:光照本身着色不会影响DrawCall和面数。实时阴影需要在渲染一张阴影用深度图,相当于换了个视角进行渲染,数据有别于当前相机。可以开FrameDebugger看一下整个渲染过程。

感谢StriteR@UWA问答社区提供了回答


UGUI

Q:UGUI的Image能通过设置MaterialPropertyBlock来修改材质属性吗?怎么设置?

A:UGUI用不了材质块,可以参考:
https://forum.unity.com/threads/big-problem-with-lacking-materialpropertyblock-for-ui-image.506941

感谢范世青@UWA问答社区提供了回答


UGUI

Q:有一个安卓端显示网页的插件UniWebView,默认会显示到Unity界面的上层,挡住Unity所有的显示。请问怎么让安卓的原生界面成为背景,让Unity的UI成为前景,Unity的背景本身也要透明。

A:要让UniWebView跑到Unity界面后面去,官方文档上说是不行的。
https://docs.uniwebview.com/guide/faq.html

 

关于Unity背景透明度保持,在Player Settings里面有个勾选项应该可以达到目的。

 

感谢Xuan@UWA问答社区提供了回答


Playable

Q:我们的特效是使用Timeline进行制作的,最近进行性能测试的时候发现,Internal_CreatePlayable方法的开销很大,但是只有一个轨道,所以很迷惑这个开销跟什么有关?

 

 

我在PC上加载了同样的一个对象,Internal_CreatePlayable需要18.55ms,然后我在PC上创建了Cube加了一个Timeline效果,Internal_CreatePlayable就需要4ms左右。

A:Timline首次CreatePlayable就是比较耗时,我这边一个简单的Timeline资源首次耗时500+ms。

 

不过可以通过把CreatePlayable的步骤放在场景加载时进行来避免游戏过程中的卡顿。加载Timeline资源后,调用PlayableDirector.RebuildGraph就会进行CreatePlayable,相当于Prewarm。此后,再调用Play(),就不会进行CreatePlayable。再调用RebuildGraph,由于有了缓存,也不会有高耗时。

 

下图为首次调用RebuildGraph的耗时。

 

下图为第二次调用RebuildGraph的耗时。

 

感谢Prin@UWA问答社区提供了回答

 

封面图来源于:URP Learn
一个用于学习Unity Universal Render Pipeline的项目。
https://lab.uwa4d.com/lab/6010aca80f247485d9c39878


今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官方技术QQ群:793972859(原群已满员)

posted @ 2021-06-16 12:36  UWATech  阅读(194)  评论(0编辑  收藏  举报