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 way
        vertex.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 way
        vertex.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 position
    bool4 unity_MetaVertexControl;

    // x = return albedo
    // y = return normal
    bool4 unity_MetaFragmentControl;

    // Control which VisualizationMode we will
    // display in the editor
    int 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的值不能过大。

猜你喜欢

转载自blog.csdn.net/u012871784/article/details/81179432