float4 TexCoords(VertexInput v)
{
float4 texcoord;
texcoord.xy = TRANSFORM_TEX(v.uv0, _MainTex); // Always source from uv0
texcoord.zw = TRANSFORM_TEX(((_UVSec == 0) ? v.uv0 : v.uv1), _DetailAlbedoMap);
return texcoord;
}
v2f_meta vert_meta (VertexInput v)
{
v2f_meta o;
o.pos = UnityMetaVertexPosition(v.vertex, v.uv1.xy, v.uv2.xy, unity_LightmapST, unity_DynamicLightmapST);
o.uv = TexCoords(v);
#ifdef EDITOR_VISUALIZATION
o.vizUV = 0;
o.lightCoord = 0;
if (unity_VisualizationMode == EDITORVIZ_TEXTURE)
o.vizUV = UnityMetaVizUV(unity_EditorViz_UVIndex, v.uv0.xy, v.uv1.xy, v.uv2.xy, unity_EditorViz_Texture_ST);
else if (unity_VisualizationMode == EDITORVIZ_SHOWLIGHTMASK)
{
o.vizUV = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
o.lightCoord = mul(unity_EditorViz_WorldToLight, mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1)));
}
#endif
return o;
}
float4 frag_meta (v2f_meta i) : SV_Target
{
// we're interested in diffuse & specular colors,
// and surface roughness to produce final albedo.
FragmentCommonData data = UNITY_SETUP_BRDF_INPUT (i.uv);
UnityMetaInput o;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o);
#ifdef EDITOR_VISUALIZATION
o.Albedo = data.diffColor;
o.VizUV = i.vizUV;
o.LightCoord = i.lightCoord;
#else
o.Albedo = UnityLightmappingAlbedo (data.diffColor, data.specColor, data.smoothness);
#endif
o.SpecularColor = data.specColor;
o.Emission = Emission(i.uv.xy);
return UnityMetaFragment(o);
}
UNITY_SETUP_BRDF_INPUT
#ifndef UNITY_SETUP_BRDF_INPUT
#define UNITY_SETUP_BRDF_INPUT SpecularSetup
#endif
inline FragmentCommonData SpecularSetup (float4 i_tex) //i_tex
{
half4 specGloss = SpecularGloss(i_tex.xy);
half3 specColor = specGloss.rgb;
half smoothness = specGloss.a;
half oneMinusReflectivity;
half3 diffColor = EnergyConservationBetweenDiffuseAndSpecular (Albedo(i_tex), specColor, /*out*/ oneMinusReflectivity);
FragmentCommonData o = (FragmentCommonData)0;
o.diffColor = diffColor;
o.specColor = specColor;
o.oneMinusReflectivity = oneMinusReflectivity;
o.smoothness = smoothness;
return o;
}
half4 SpecularGloss(float2 uv)
{
half4 sg;
#ifdef _SPECGLOSSMAP
#if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
sg.rgb = tex2D(_SpecGlossMap, uv).rgb;
sg.a = tex2D(_MainTex, uv).a;
#else
sg = tex2D(_SpecGlossMap, uv);
#endif
sg.a *= _GlossMapScale;
#else
sg.rgb = _SpecColor.rgb;
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
sg.a = tex2D(_MainTex, uv).a * _GlossMapScale;
#else
sg.a = _Glossiness;
#endif
#endif
return sg;
}
half3 Albedo(float4 texcoords)
{
half3 albedo = _Color.rgb * tex2D (_MainTex, texcoords.xy).rgb;
#if _DETAIL
#if (SHADER_TARGET < 30)
// SM20: instruction count limitation
// SM20: no detail mask
half mask = 1;
#else
half mask = DetailMask(texcoords.xy);
#endif
half3 detailAlbedo = tex2D (_DetailAlbedoMap, texcoords.zw).rgb;
#if _DETAIL_MULX2
albedo *= LerpWhiteTo (detailAlbedo * unity_ColorSpaceDouble.rgb, mask);
#elif _DETAIL_MUL
albedo *= LerpWhiteTo (detailAlbedo, mask);
#elif _DETAIL_ADD
albedo += detailAlbedo * mask;
#elif _DETAIL_LERP
albedo = lerp (albedo, detailAlbedo, mask);
#endif
#endif
return albedo;
}
half SpecularStrength(half3 specular)
{
#if (SHADER_TARGET < 30)
// SM2.0: instruction count limitation
// SM2.0: simplified SpecularStrength
return specular.r; // Red channel - because most metals are either monocrhome or with redish/yellowish tint
#else
return max (max (specular.r, specular.g), specular.b);
#endif
}
// Diffuse/Spec Energy conservation
inline half3 EnergyConservationBetweenDiffuseAndSpecular (half3 albedo, half3 specColor, out half oneMinusReflectivity)
{
oneMinusReflectivity = 1 - SpecularStrength(specColor);
#if !UNITY_CONSERVE_ENERGY
return albedo;
#elif UNITY_CONSERVE_ENERGY_MONOCHROME
return albedo * oneMinusReflectivity;
#else
return albedo * (half3(1,1,1) - specColor);
#endif
}
half4 UnityMetaFragment (UnityMetaInput IN)
{
half4 res = 0;
#if !defined(EDITOR_VISUALIZATION)
if (unity_MetaFragmentControl.x)
{
res = half4(IN.Albedo,1);
// d3d9 shader compiler doesn't like NaNs and infinity.
unity_OneOverOutputBoost = saturate(unity_OneOverOutputBoost);
// Apply Albedo Boost from LightmapSettings.
res.rgb = clamp(pow(res.rgb, unity_OneOverOutputBoost), 0, unity_MaxOutputValue);
}
if (unity_MetaFragmentControl.y)
{
half3 emission;
if (unity_UseLinearSpace)
emission = IN.Emission;
else
emission = GammaToLinearSpace(IN.Emission);
res = half4(emission, 1.0);
}
#else
if ( unity_VisualizationMode == EDITORVIZ_PBR_VALIDATION_ALBEDO)
{
res = UnityMeta_pbrAlbedo(IN);
}
else if (unity_VisualizationMode == EDITORVIZ_PBR_VALIDATION_METALSPECULAR)
{
res = UnityMeta_pbrMetalspec(IN);
}
else if (unity_VisualizationMode == EDITORVIZ_TEXTURE)
{
res = tex2D(unity_EditorViz_Texture, IN.VizUV);
if (unity_EditorViz_Decode_HDR.x > 0)
res = half4(DecodeHDR(res, unity_EditorViz_Decode_HDR), 1);
if (unity_EditorViz_ConvertToLinearSpace)
res.rgb = LinearToGammaSpace(res.rgb);
res *= unity_EditorViz_ColorMul;
res += unity_EditorViz_ColorAdd;
}
else if (unity_VisualizationMode == EDITORVIZ_SHOWLIGHTMASK)
{
float result = dot(unity_EditorViz_ChannelSelect, tex2D(unity_EditorViz_Texture, IN.VizUV).rgba);
if (result == 0)
discard;
float atten = 1;
if (unity_EditorViz_LightType == 0)
{
// directional: no attenuation
}
else if (unity_EditorViz_LightType == 1)
{
// point
atten = tex2D(unity_EditorViz_LightTexture, dot(IN.LightCoord.xyz, IN.LightCoord.xyz).xx).r;
}
else if (unity_EditorViz_LightType == 2)
{
// spot
atten = tex2D(unity_EditorViz_LightTexture, dot(IN.LightCoord.xyz, IN.LightCoord.xyz).xx).r;
float cookie = tex2D(unity_EditorViz_LightTextureB, IN.LightCoord.xy / IN.LightCoord.w + 0.5).w;
atten *= (IN.LightCoord.z > 0) * cookie;
}
clip(atten - 0.001f);
res = float4(unity_EditorViz_Color.xyz * result, unity_EditorViz_Color.w);
}
#endif // EDITOR_VISUALIZATION
return res;
}
unity_MetaFragmentControl不知道哪里设置的。