unity灯光和自发光的哪个节省内存
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity灯光和自发光的哪个节省内存相关的知识,希望对你有一定的参考价值。
参考技术A 但这种模型有很多局限性。首先,有很多重要的物理现象无法用Blinn-Phong 模型表现出来,例如菲涅耳反射(Fresnel reflection)。其次,Blinn-Phong 模型是各项同性(isotropic)的,也就
是说,当我们固定视角和光源方向旋转这个表面时,反射不会发生任何改变。但有些表面是具有
各向异性(anisotropic)反射性质的,例如拉丝金属、毛发等。在第18 章中,我们将学习基于物
理的光照模型,这些光照模型更加复杂,同时也可以更加真实地反映光和物体的交互。
一、Unity 中的环境光和自发光
在标准光照模型中,环境光和自发光的计算
是最简单的。
在Unity 中,场景中的环境光可以在Window ->
Lighting -> Ambient Source/Ambient Color/Ambient
Intensity 中控制,如图6.5 所示。在Shader 中,我
们只需要通过Unity 的内置变量UNITY_LIGHTM
ODEL_AMBIENT 就可以得到环境光的颜色和强
度信息。
而大多数物体是没有自发光特性的,因此在
本书绝大部分的Shader 中都没有计算自发光部
分。如果要计算自发光也非常简单,我们只需要
在片元着色器输出最后的颜色之前,把材质的自
发光颜色添加到输出颜色上即可。
Unity 手写PBR补充:多光源 阴影 视差 自发光
写在前面
【Unity 手写PBR】Build-in管线:实现直接光部分
【Unity 手写PBR】Build-in管线:实现间接光部分
这里再快速补充一下剩下的部分,多光源、阴影、视差贴图应用和自发光。
1 多光源
环境光照和自发光都在Base Pass计算,Additonal Pass只计算直接光照,其中atten是光照衰减值:
float3 result = directLight * atten;
由于是在Unity固定管线下,所以还是采用老办法AdditionalPass,关于Unity前向渲染如何处理多光源的可以参考之前我写的一篇文章【技术美术图形部分】关于前向渲染和延迟渲染
实现的话,如果不去深究,直接拿Unity的内置宏,一句话解决:
// 光源衰减项
UNITY_LIGHT_ATTENUATION(atten,i, worldPos);
如果要自己实现的话,尤其注意光源衰减值,平行光、点光源、聚光灯都是有区别的,贴个自己写的涉及到衰减项的部分shader:
// 光源衰减项
#ifdef USING_DIRECTIONAL_LIGHT
float atten = 1.0;
#else
#if defined(POINT)
// 点光源从世界变到光源空间
float3 lightCoord = mul(unity_WorldToLight, float4(worldPos,1)).xyz;
float atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#elif defined(SPOT)
float4 lightCoord = mul(unity_WorldToLight, float4(worldPos,1));
float atten = (lightCoord.z>0)*tex2D(_LightTexture0, lightCoord.xy/lightCoord.w+0.5).w*tex2D(_LightTextureB0,dot(lightCoord,lightCoord).rr).UNITY_ATTEN_CHANNEL;
#else
float atten = 1.0;
#endif
#endif
2 阴影
阴影这里全调用Unity内置宏解决,需要保证物体能投射阴影,还要保证物体能接受阴影。需要注意的是,
BasePass中,对主要平行光的计算,要么
UNITY_LIGHT_ATTENUATION(atten,i, worldPos);
一下解决atten计算和采样纹理shadow值的问题;要么
float shadow = 1;
float atten = 1.0; // 仅平行光
shadow = SHADOW_ATTENUATION(i); // 使用_ShadowCoord对相关纹理采样,得到阴影信息
规定平行光的atten为1后,还要计算shadow值,最后result直接光部分也加上*atten*shadow,保证可以接受阴影。
其余情况,擅用宏就行,由于比较分散,这里就不一个一个贴出来了,,,之前写过一篇【Unity Shader】Unity中阴影映射标准制作流程,里面有写实现方法,需要的话可以去看看~
2 视差贴图
参考:2.5凹凸映射、视差映射、浮雕映射 - 知乎 (zhihu.com)
视差算法:关于视差算法的基本原理与拓展应用 - 哔哩哔哩 (bilibili.com)
Unity Standard Shader里还有Height Map的应用,为了让我的PBR Shader更加完整,加上!
2.1 简单解释
之前一直都分不清法线贴图、视差贴图这些,,后来发现视差贴图经常是与法线贴图一起使用。法线贴图改变了纹理的光照,视差贴图再叠加叠加,视差会移动纹理的可见项,实现表面的遮挡效果,感觉就是“更加真实”了。
随便搜了搜,拿这篇文章里的图举例:
中间是BaseColor+NormalMap,右边的是BaseColor+NormalMap+ParallaxMap
所以视差贴图解决的更多的是结构之间的遮挡问题。
2.2 实现
之所以是“视差”,其核心是改变纹理坐标,利用模型表面的高度信息对纹理进行偏移,低位置信息被高位置遮挡了,所以直接采样更高的信息。
fragment shader中要采样视差贴图得到Height值,再通过ParallaxOffset得到偏移量Offset,应用到i.uv上就行。
// 视差贴图
float height = tex2D(_ParallaxMap, i.uv).r;
float2 offset = ParallaxOffset(height, _ParallaxScale, i.objviewDir);
i.uv += offset;
这里的ParallaxOffset是UnityCG.cginc定义的函数,源码:
// Calculates UV offset for parallax bump mapping
inline float2 ParallaxOffset( half h, half height, half3 viewDir )
h = h * height - height/2.0;
float3 v = normalize(viewDir);
v.z += 0.42;
return h * (v.xy / v.z);
h为传入的采样值,height为我们定义的_ParallaxScale,用viewDir的x和y分量,反正就直接用这个源码就OK!
2.3 对比
加了一个点光源,对比明显一些:
然后是NormalMap拉到最大:
这个是只加上ParallaxMap,效果拉满:
我不太清楚这样对比是否合适,但能感觉到视差到底做了什么事,就是一个假的、凹凸的效果。
关于视差就到这。
3 自发光贴图
自发光虽然简单,但我的PBR shader必须什么功能都有!搞一下:
自发光感觉是不受到光照影响的,所以说传入的自发光贴图就是个黑白的通道而已,就针对区域上色,最后result+=就行了:
float3 emission = tex2D(_EmissionTex, i.uv);
emission = _EmissionColor * emission * _EmissionStrength;
后期bloom的话还需调整参数。
写的很仓促,目的仅仅是为了记录,后面会搭个场景,尽量把不同的材质都体现在场景中,也算是给这4、5天的PBR学习做一个收尾工作吧。
以上是关于unity灯光和自发光的哪个节省内存的主要内容,如果未能解决你的问题,请参考以下文章