本文主要是介绍UnityShader源码2017---学习笔记与自我拓展039,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
源自 Illumin-Bumped,Illumin-BumpSpec,Illumin-Diffuse,Illumin-Glossy,Illumin-Parallax,Illumin-ParallaxSpec,Illumin-VertexLit
记得很久很久以前。。。。long long ago
那还是4.x的年底,shader中如果这么写
Shader "Self-Illumin/New Unlit NoFog"
是的,只有shader的一级文件夹是Self-Illumin,那么shader的自发光部分就可以bake到lightmap中
时过境迁,unity迎来的PBR的时代。之前的套路已经没有了效果。
先搁置下Illumin-VertexLit这个shader,看其他的
其他shader中能说的之前都说了,只有一处,这一处也是这些shader的共同点
#if defined (UNITY_PASS_META)o.Emission *= _Emission.rrr;
#endif
也就是说如果定义了UNITY_PASS_META这个宏,就会让自发光的强度与_Emission做倍率乘法。
而META是unity用来做GI等的。
所以就是说,可以bake到lightmap中。
我为了减少变量的影响,注释掉了fallback
//FallBack "Legacy Shaders/Self-Illumin/VertexLit"
然后bake,效果如下。
也就是说,lightmap的bake不是fallback里的meta的pass做的。可能是surface shader的一些魔法吧
后来我测试了直接只有一个pass,然后fallback到vertexlit里的meta 的pass似乎找不到meta,不知为何,表现的结果就是lightmap烘焙结果没有预期。
然后返回shader中,定睛一看。。。
CustomEditor "LegacyIlluminShaderGUI"
然后我有开始扒拉源码中,并没有发现这个Editor的cs源码。
unity真是爸爸。。。
算了,看一眼mat里的吧
也就是说,这个是这个editor的关键之处。
可惜找不到出处。。。。。(这个留给之后看PBR时再说吧。。。)
想了想还是这里一下子说完这一块吧。。。
using UnityEngine;namespace UnityEditor
{internal class LegacyIlluminShaderGUI : ShaderGUI{public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props){base.OnGUI(materialEditor, props);materialEditor.LightmapEmissionProperty(0);foreach (Material target in materialEditor.targets)target.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;}}
}
这个问题先导此位置。
看一眼Illumin-VertexLit,
直接定位meta(vertex mode下没有什么可说的)
先说一个疑似bug的部分。
metaIN.Emission = c.rgb * tex2D(_Illum, i.uvIllum).a;
#if defined (UNITY_PASS_META)o.Emission *= _Emission.rrr;
#endif
o从何而来。。。。应该是这样
metaIN.Emission = c.rgb * tex2D(_Illum, i.uvIllum).a;
#if defined (UNITY_PASS_META)metaIN.Emission *= _Emission.rrr;
#endif
个人觉得是个bug
然后去看了下builtin_shaders-2018.1.6f1中的发现
这里已经修复。。。删除了#if的判断,直接保留了语句变成了这样
metaIN.Emission = c.rgb * tex2D(_Illum, i.uvIllum).a;
但是同样的。发现_Emission的使用却消失了。。。。官方还是留了个bug?
纵使如此,fallback的问题(后来我测试了直接只有一个pass,然后fallback到vertexlit里的meta 的pass似乎找不到meta,不知为何,表现的结果就是lightmap烘焙结果没有预期。)还是遗留下来了,随着2018版本的一次又一次更迭,我觉定放弃这部分的问题。或许官方就是这么想的。。。。
关于lightmap的研究下面还有实验。
回归正题,把vert部分的UnityMetaVertexPosition()说完这一部分就结束了
o.pos = UnityMetaVertexPosition(v.vertex, v.texcoord1.xy, v.texcoord2.xy, unity_LightmapST, unity_DynamicLightmapST);
float4 UnityMetaVertexPosition (float4 vertex, float2 uv1, float2 uv2, float4 lightmapST, float4 dynlightmapST)
{if (unity_MetaVertexControl.x){vertex.xy = uv1 * lightmapST.xy + lightmapST.zw;// OpenGL right now needs to actually use incoming vertex position,// so use it in a very dummy wayvertex.z = vertex.z > 0 ? 1.0e-4f : 0.0f;}if (unity_MetaVertexControl.y){vertex.xy = uv2 * dynlightmapST.xy + dynlightmapST.zw;// OpenGL right now needs to actually use incoming vertex position,// so use it in a very dummy wayvertex.z = vertex.z > 0 ? 1.0e-4f : 0.0f;}return mul(UNITY_MATRIX_VP, float4(vertex.xyz, 1.0));
}
先看unity_MetaVertexControl,在UnityMetaPass.cginc里
CBUFFER_START(UnityMetaPass)// x = use uv1 as raster position// y = use uv2 as raster positionbool4 unity_MetaVertexControl;// x = return albedo// y = return normalbool4 unity_MetaFragmentControl;// Control which VisualizationMode we will// display in the editorint unity_VisualizationMode;
CBUFFER_END
unity_MetaVertexControl的x分量是个布尔值(在C的语法里,0为false,非零为true):是否使用uv1作为光栅化的坐标
y分量:是否使用uv2作为光栅化的坐标
下面的码很明显的,就是做了TRNASFOMR_TEX这个函数做的,只不过把判断Z,如果大于零z=0.0001,否则就是0
带来的疑问是什么时候会用uv1做光栅化的坐标呢?
不明白这里是用做干什么的,或许unity还有一些未发觉的技能。下面是一个简单的测试
下面是lightmap的一点实验性的操作(这里不测试_Emission为负值时带来的反色的lightmap的效果)
这里就意思一下,具体含义不细说,详情看手册吧
效果如上。
4.x年代的手法已经失效,那么在新版unity里如何做的,手册里也说了meta的pass管这个。
于是,就有了meta的pass
Pass
{Tags { "LightMode"="Meta" }CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;};struct v2f{float4 vertex : SV_POSITION;};fixed4 _Color;float _Emission;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);return o;}fixed4 frag (v2f i) : SV_Target{fixed4 col = _Color*_Emission;return col;}ENDCG
}
这里简单的写的meta,或许不会符合unity的规范,这里先简单的测试。
我们把_Emission调到0.1,然后bake(使用这个shader的材质在light explorer的static emissives页签下并没有记录)
效果如下图
这里有个问题就是,自己写的meta中的_Emission的值竟然影响旁边红色的材质(自带的standard shader的mat)。可以调_Emission成1试试,整个都是爆掉的,然后红色的部分用来黄绿色。
说明了什么,只能说明我的操作不规范。
然后我用了自带的过来时的shader bake一下
也是有问题的。
然后两个standard。
看来Emission的值不能过大。
这篇关于UnityShader源码2017---学习笔记与自我拓展039的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!