├── CGIncludes.meta ├── CGIncludes ├── UnityStandardCoreForward_TexArray.cginc ├── UnityStandardCoreForward_TexArray.cginc.meta ├── UnityStandardCore_TexArray.cginc ├── UnityStandardCore_TexArray.cginc.meta ├── UnityStandardInput_TexArray.cginc ├── UnityStandardInput_TexArray.cginc.meta ├── UnityStandardMeta_TexArray.cginc └── UnityStandardMeta_TexArray.cginc.meta ├── DefaultResourcesExtra.meta ├── DefaultResourcesExtra ├── Standard_TexArray.shader └── Standard_TexArray.shader.meta ├── Editor.meta ├── Editor ├── MB_TexArrayStandardShaderGUI.cs └── MB_TexArrayStandardShaderGUI.cs.meta ├── license.txt └── license.txt.meta /CGIncludes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8ca1d03f470c69343bb92df3158fabf4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /CGIncludes/UnityStandardCoreForward_TexArray.cginc: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | #ifndef UNITY_STANDARD_CORE_FORWARD_INCLUDED 4 | #define UNITY_STANDARD_CORE_FORWARD_INCLUDED 5 | 6 | #if defined(UNITY_NO_FULL_STANDARD_SHADER) 7 | # define UNITY_STANDARD_SIMPLE 1 8 | #endif 9 | 10 | #include "UnityStandardConfig.cginc" 11 | 12 | #if UNITY_STANDARD_SIMPLE 13 | #include "UnityStandardCoreForwardSimple.cginc" 14 | VertexOutputBaseSimple vertBase (VertexInput v) { return vertForwardBaseSimple(v); } 15 | VertexOutputForwardAddSimple vertAdd (VertexInput v) { return vertForwardAddSimple(v); } 16 | half4 fragBase (VertexOutputBaseSimple i) : SV_Target { return fragForwardBaseSimpleInternal(i); } 17 | half4 fragAdd (VertexOutputForwardAddSimple i) : SV_Target { return fragForwardAddSimpleInternal(i); } 18 | #else 19 | #include "../CGIncludes/UnityStandardCore_TexArray.cginc" 20 | VertexOutputForwardBase vertBase (VertexInput v) { return vertForwardBase(v); } 21 | VertexOutputForwardAdd vertAdd (VertexInput v) { return vertForwardAdd(v); } 22 | half4 fragBase (VertexOutputForwardBase i) : SV_Target { return fragForwardBaseInternal(i); } 23 | half4 fragAdd (VertexOutputForwardAdd i) : SV_Target { return fragForwardAddInternal(i); } 24 | #endif 25 | 26 | #endif // UNITY_STANDARD_CORE_FORWARD_INCLUDED 27 | -------------------------------------------------------------------------------- /CGIncludes/UnityStandardCoreForward_TexArray.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 25b45d11eaf943f4bb1495c70bb3fbf1 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /CGIncludes/UnityStandardCore_TexArray.cginc: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | #ifndef UNITY_STANDARD_CORE_INCLUDED 4 | #define UNITY_STANDARD_CORE_INCLUDED 5 | 6 | #include "UnityCG.cginc" 7 | #include "UnityShaderVariables.cginc" 8 | #include "UnityStandardConfig.cginc" 9 | #include "UnityStandardInput_TexArray.cginc" 10 | #include "UnityPBSLighting.cginc" 11 | #include "UnityStandardUtils.cginc" 12 | #include "UnityGBuffer.cginc" 13 | #include "UnityStandardBRDF.cginc" 14 | 15 | #include "AutoLight.cginc" 16 | //------------------------------------------------------------------------------------- 17 | // counterpart for NormalizePerPixelNormal 18 | // skips normalization per-vertex and expects normalization to happen per-pixel 19 | half3 NormalizePerVertexNormal (float3 n) // takes float to avoid overflow 20 | { 21 | #if (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE 22 | return normalize(n); 23 | #else 24 | return n; // will normalize per-pixel instead 25 | #endif 26 | } 27 | 28 | float3 NormalizePerPixelNormal (float3 n) 29 | { 30 | #if (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE 31 | return n; 32 | #else 33 | return normalize((float3)n); // takes float to avoid overflow 34 | #endif 35 | } 36 | 37 | //------------------------------------------------------------------------------------- 38 | UnityLight MainLight () 39 | { 40 | UnityLight l; 41 | 42 | l.color = _LightColor0.rgb; 43 | l.dir = _WorldSpaceLightPos0.xyz; 44 | return l; 45 | } 46 | 47 | UnityLight AdditiveLight (half3 lightDir, half atten) 48 | { 49 | UnityLight l; 50 | 51 | l.color = _LightColor0.rgb; 52 | l.dir = lightDir; 53 | #ifndef USING_DIRECTIONAL_LIGHT 54 | l.dir = NormalizePerPixelNormal(l.dir); 55 | #endif 56 | 57 | // shadow the light 58 | l.color *= atten; 59 | return l; 60 | } 61 | 62 | UnityLight DummyLight () 63 | { 64 | UnityLight l; 65 | l.color = 0; 66 | l.dir = half3 (0,1,0); 67 | return l; 68 | } 69 | 70 | UnityIndirect ZeroIndirect () 71 | { 72 | UnityIndirect ind; 73 | ind.diffuse = 0; 74 | ind.specular = 0; 75 | return ind; 76 | } 77 | 78 | //------------------------------------------------------------------------------------- 79 | // Common fragment setup 80 | 81 | // deprecated 82 | half3 WorldNormal(half4 tan2world[3]) 83 | { 84 | return normalize(tan2world[2].xyz); 85 | } 86 | 87 | // deprecated 88 | #ifdef _TANGENT_TO_WORLD 89 | half3x3 ExtractTangentToWorldPerPixel(half4 tan2world[3]) 90 | { 91 | half3 t = tan2world[0].xyz; 92 | half3 b = tan2world[1].xyz; 93 | half3 n = tan2world[2].xyz; 94 | 95 | #if UNITY_TANGENT_ORTHONORMALIZE 96 | n = NormalizePerPixelNormal(n); 97 | 98 | // ortho-normalize Tangent 99 | t = normalize (t - n * dot(t, n)); 100 | 101 | // recalculate Binormal 102 | half3 newB = cross(n, t); 103 | b = newB * sign (dot (newB, b)); 104 | #endif 105 | 106 | return half3x3(t, b, n); 107 | } 108 | #else 109 | half3x3 ExtractTangentToWorldPerPixel(half4 tan2world[3]) 110 | { 111 | return half3x3(0,0,0,0,0,0,0,0,0); 112 | } 113 | #endif 114 | 115 | float3 PerPixelWorldNormal(float4 i_tex, float4 tangentToWorld[3]) 116 | { 117 | #ifdef _NORMALMAP 118 | half3 tangent = tangentToWorld[0].xyz; 119 | half3 binormal = tangentToWorld[1].xyz; 120 | half3 normal = tangentToWorld[2].xyz; 121 | 122 | #if UNITY_TANGENT_ORTHONORMALIZE 123 | normal = NormalizePerPixelNormal(normal); 124 | 125 | // ortho-normalize Tangent 126 | tangent = normalize (tangent - normal * dot(tangent, normal)); 127 | 128 | // recalculate Binormal 129 | half3 newB = cross(normal, tangent); 130 | binormal = newB * sign (dot (newB, binormal)); 131 | #endif 132 | 133 | half3 normalTangent = NormalInTangentSpace(i_tex); 134 | float3 normalWorld = NormalizePerPixelNormal(tangent * normalTangent.x + binormal * normalTangent.y + normal * normalTangent.z); // @TODO: see if we can squeeze this normalize on SM2.0 as well 135 | #else 136 | float3 normalWorld = normalize(tangentToWorld[2].xyz); 137 | #endif 138 | return normalWorld; 139 | } 140 | 141 | #ifdef _PARALLAXMAP 142 | #define IN_VIEWDIR4PARALLAX(i) NormalizePerPixelNormal(half3(i.tangentToWorldAndPackedData[0].w,i.tangentToWorldAndPackedData[1].w,i.tangentToWorldAndPackedData[2].w)) 143 | #define IN_VIEWDIR4PARALLAX_FWDADD(i) NormalizePerPixelNormal(i.viewDirForParallax.xyz) 144 | #else 145 | #define IN_VIEWDIR4PARALLAX(i) half3(0,0,0) 146 | #define IN_VIEWDIR4PARALLAX_FWDADD(i) half3(0,0,0) 147 | #endif 148 | 149 | #if UNITY_REQUIRE_FRAG_WORLDPOS 150 | #if UNITY_PACK_WORLDPOS_WITH_TANGENT 151 | #define IN_WORLDPOS(i) half3(i.tangentToWorldAndPackedData[0].w,i.tangentToWorldAndPackedData[1].w,i.tangentToWorldAndPackedData[2].w) 152 | #else 153 | #define IN_WORLDPOS(i) i.posWorld 154 | #endif 155 | #define IN_WORLDPOS_FWDADD(i) i.posWorld 156 | #else 157 | #define IN_WORLDPOS(i) half3(0,0,0) 158 | #define IN_WORLDPOS_FWDADD(i) half3(0,0,0) 159 | #endif 160 | 161 | #define IN_LIGHTDIR_FWDADD(i) half3(i.tangentToWorldAndLightDir[0].w, i.tangentToWorldAndLightDir[1].w, i.tangentToWorldAndLightDir[2].w) 162 | 163 | #define FRAGMENT_SETUP(x) FragmentCommonData x = \ 164 | FragmentSetup(i.tex, i.eyeVec.xyz, IN_VIEWDIR4PARALLAX(i), i.tangentToWorldAndPackedData, IN_WORLDPOS(i)); 165 | 166 | #define FRAGMENT_SETUP_FWDADD(x) FragmentCommonData x = \ 167 | FragmentSetup(i.tex, i.eyeVec.xyz, IN_VIEWDIR4PARALLAX_FWDADD(i), i.tangentToWorldAndLightDir, IN_WORLDPOS_FWDADD(i)); 168 | 169 | struct FragmentCommonData 170 | { 171 | half3 diffColor, specColor; 172 | // Note: smoothness & oneMinusReflectivity for optimization purposes, mostly for DX9 SM2.0 level. 173 | // Most of the math is being done on these (1-x) values, and that saves a few precious ALU slots. 174 | half oneMinusReflectivity, smoothness; 175 | float3 normalWorld; 176 | float3 eyeVec; 177 | half alpha; 178 | float3 posWorld; 179 | 180 | #if UNITY_STANDARD_SIMPLE 181 | half3 reflUVW; 182 | #endif 183 | 184 | #if UNITY_STANDARD_SIMPLE 185 | half3 tangentSpaceNormal; 186 | #endif 187 | }; 188 | 189 | #ifndef UNITY_SETUP_BRDF_INPUT 190 | #define UNITY_SETUP_BRDF_INPUT SpecularSetup 191 | #endif 192 | 193 | inline FragmentCommonData SpecularSetup (float4 i_tex) 194 | { 195 | half4 specGloss = SpecularGloss(i_tex.xyz); 196 | half3 specColor = specGloss.rgb; 197 | half smoothness = specGloss.a; 198 | 199 | half oneMinusReflectivity; 200 | half3 diffColor = EnergyConservationBetweenDiffuseAndSpecular (Albedo(i_tex), specColor, /*out*/ oneMinusReflectivity); 201 | 202 | FragmentCommonData o = (FragmentCommonData)0; 203 | o.diffColor = diffColor; 204 | o.specColor = specColor; 205 | o.oneMinusReflectivity = oneMinusReflectivity; 206 | o.smoothness = smoothness; 207 | return o; 208 | } 209 | 210 | inline FragmentCommonData RoughnessSetup(float4 i_tex) 211 | { 212 | half2 metallicGloss = MetallicRough(i_tex.xyz); 213 | half metallic = metallicGloss.x; 214 | half smoothness = metallicGloss.y; // this is 1 minus the square root of real roughness m. 215 | 216 | half oneMinusReflectivity; 217 | half3 specColor; 218 | half3 diffColor = DiffuseAndSpecularFromMetallic(Albedo(i_tex), metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity); 219 | 220 | FragmentCommonData o = (FragmentCommonData)0; 221 | o.diffColor = diffColor; 222 | o.specColor = specColor; 223 | o.oneMinusReflectivity = oneMinusReflectivity; 224 | o.smoothness = smoothness; 225 | return o; 226 | } 227 | 228 | inline FragmentCommonData MetallicSetup (float4 i_tex) 229 | { 230 | half2 metallicGloss = MetallicGloss(i_tex.xyz); 231 | half metallic = metallicGloss.x; 232 | half smoothness = metallicGloss.y; // this is 1 minus the square root of real roughness m. 233 | 234 | half oneMinusReflectivity; 235 | half3 specColor; 236 | half3 diffColor = DiffuseAndSpecularFromMetallic (Albedo(i_tex), metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity); 237 | 238 | FragmentCommonData o = (FragmentCommonData)0; 239 | o.diffColor = diffColor; 240 | o.specColor = specColor; 241 | o.oneMinusReflectivity = oneMinusReflectivity; 242 | o.smoothness = smoothness; 243 | return o; 244 | } 245 | 246 | // parallax transformed texcoord is used to sample occlusion 247 | inline FragmentCommonData FragmentSetup (inout float4 i_tex, float3 i_eyeVec, half3 i_viewDirForParallax, float4 tangentToWorld[3], float3 i_posWorld) 248 | { 249 | i_tex = Parallax(i_tex, i_viewDirForParallax); 250 | 251 | half alpha = Alpha(i_tex.xyz); 252 | #if defined(_ALPHATEST_ON) 253 | clip (alpha - _Cutoff); 254 | #endif 255 | 256 | FragmentCommonData o = UNITY_SETUP_BRDF_INPUT (i_tex); 257 | o.normalWorld = PerPixelWorldNormal(i_tex, tangentToWorld); 258 | o.eyeVec = NormalizePerPixelNormal(i_eyeVec); 259 | o.posWorld = i_posWorld; 260 | 261 | // NOTE: shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha) 262 | o.diffColor = PreMultiplyAlpha (o.diffColor, alpha, o.oneMinusReflectivity, /*out*/ o.alpha); 263 | return o; 264 | } 265 | 266 | inline UnityGI FragmentGI (FragmentCommonData s, half occlusion, half4 i_ambientOrLightmapUV, half atten, UnityLight light, bool reflections) 267 | { 268 | UnityGIInput d; 269 | d.light = light; 270 | d.worldPos = s.posWorld; 271 | d.worldViewDir = -s.eyeVec; 272 | d.atten = atten; 273 | #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON) 274 | d.ambient = 0; 275 | d.lightmapUV = i_ambientOrLightmapUV; 276 | #else 277 | d.ambient = i_ambientOrLightmapUV.rgb; 278 | d.lightmapUV = 0; 279 | #endif 280 | 281 | d.probeHDR[0] = unity_SpecCube0_HDR; 282 | d.probeHDR[1] = unity_SpecCube1_HDR; 283 | #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION) 284 | d.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending 285 | #endif 286 | #ifdef UNITY_SPECCUBE_BOX_PROJECTION 287 | d.boxMax[0] = unity_SpecCube0_BoxMax; 288 | d.probePosition[0] = unity_SpecCube0_ProbePosition; 289 | d.boxMax[1] = unity_SpecCube1_BoxMax; 290 | d.boxMin[1] = unity_SpecCube1_BoxMin; 291 | d.probePosition[1] = unity_SpecCube1_ProbePosition; 292 | #endif 293 | 294 | if(reflections) 295 | { 296 | Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(s.smoothness, -s.eyeVec, s.normalWorld, s.specColor); 297 | // Replace the reflUVW if it has been compute in Vertex shader. Note: the compiler will optimize the calcul in UnityGlossyEnvironmentSetup itself 298 | #if UNITY_STANDARD_SIMPLE 299 | g.reflUVW = s.reflUVW; 300 | #endif 301 | 302 | return UnityGlobalIllumination (d, occlusion, s.normalWorld, g); 303 | } 304 | else 305 | { 306 | return UnityGlobalIllumination (d, occlusion, s.normalWorld); 307 | } 308 | } 309 | 310 | inline UnityGI FragmentGI (FragmentCommonData s, half occlusion, half4 i_ambientOrLightmapUV, half atten, UnityLight light) 311 | { 312 | return FragmentGI(s, occlusion, i_ambientOrLightmapUV, atten, light, true); 313 | } 314 | 315 | 316 | //------------------------------------------------------------------------------------- 317 | half4 OutputForward (half4 output, half alphaFromSurface) 318 | { 319 | #if defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON) 320 | output.a = alphaFromSurface; 321 | #else 322 | UNITY_OPAQUE_ALPHA(output.a); 323 | #endif 324 | return output; 325 | } 326 | 327 | inline half4 VertexGIForward(VertexInput v, float3 posWorld, half3 normalWorld) 328 | { 329 | half4 ambientOrLightmapUV = 0; 330 | // Static lightmaps 331 | #ifdef LIGHTMAP_ON 332 | ambientOrLightmapUV.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw; 333 | ambientOrLightmapUV.zw = 0; 334 | // Sample light probe for Dynamic objects only (no static or dynamic lightmaps) 335 | #elif UNITY_SHOULD_SAMPLE_SH 336 | #ifdef VERTEXLIGHT_ON 337 | // Approximated illumination from non-important point lights 338 | ambientOrLightmapUV.rgb = Shade4PointLights ( 339 | unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, 340 | unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb, 341 | unity_4LightAtten0, posWorld, normalWorld); 342 | #endif 343 | 344 | ambientOrLightmapUV.rgb = ShadeSHPerVertex (normalWorld, ambientOrLightmapUV.rgb); 345 | #endif 346 | 347 | #ifdef DYNAMICLIGHTMAP_ON 348 | ambientOrLightmapUV.zw = v.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; 349 | #endif 350 | 351 | return ambientOrLightmapUV; 352 | } 353 | 354 | // ------------------------------------------------------------------ 355 | // Base forward pass (directional light, emission, lightmaps, ...) 356 | 357 | struct VertexOutputForwardBase 358 | { 359 | UNITY_POSITION(pos); 360 | float4 tex : TEXCOORD0; 361 | float4 eyeVec : TEXCOORD1; // eyeVec.xyz | fogCoord 362 | float4 tangentToWorldAndPackedData[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax or worldPos] 363 | half4 ambientOrLightmapUV : TEXCOORD5; // SH or Lightmap UV 364 | UNITY_LIGHTING_COORDS(6,7) 365 | 366 | // next ones would not fit into SM2.0 limits, but they are always for SM3.0+ 367 | #if UNITY_REQUIRE_FRAG_WORLDPOS && !UNITY_PACK_WORLDPOS_WITH_TANGENT 368 | float3 posWorld : TEXCOORD8; 369 | #endif 370 | 371 | UNITY_VERTEX_INPUT_INSTANCE_ID 372 | UNITY_VERTEX_OUTPUT_STEREO 373 | }; 374 | 375 | VertexOutputForwardBase vertForwardBase (VertexInput v) 376 | { 377 | UNITY_SETUP_INSTANCE_ID(v); 378 | VertexOutputForwardBase o; 379 | UNITY_INITIALIZE_OUTPUT(VertexOutputForwardBase, o); 380 | UNITY_TRANSFER_INSTANCE_ID(v, o); 381 | UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); 382 | 383 | float4 posWorld = mul(unity_ObjectToWorld, v.vertex); 384 | #if UNITY_REQUIRE_FRAG_WORLDPOS 385 | #if UNITY_PACK_WORLDPOS_WITH_TANGENT 386 | o.tangentToWorldAndPackedData[0].w = posWorld.x; 387 | o.tangentToWorldAndPackedData[1].w = posWorld.y; 388 | o.tangentToWorldAndPackedData[2].w = posWorld.z; 389 | #else 390 | o.posWorld = posWorld.xyz; 391 | #endif 392 | #endif 393 | o.pos = UnityObjectToClipPos(v.vertex); 394 | 395 | o.tex = TexCoords(v); 396 | o.eyeVec.xyz = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos); 397 | float3 normalWorld = UnityObjectToWorldNormal(v.normal); 398 | #ifdef _TANGENT_TO_WORLD 399 | float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); 400 | 401 | float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w); 402 | o.tangentToWorldAndPackedData[0].xyz = tangentToWorld[0]; 403 | o.tangentToWorldAndPackedData[1].xyz = tangentToWorld[1]; 404 | o.tangentToWorldAndPackedData[2].xyz = tangentToWorld[2]; 405 | #else 406 | o.tangentToWorldAndPackedData[0].xyz = 0; 407 | o.tangentToWorldAndPackedData[1].xyz = 0; 408 | o.tangentToWorldAndPackedData[2].xyz = normalWorld; 409 | #endif 410 | 411 | //We need this for shadow receving 412 | UNITY_TRANSFER_LIGHTING(o, v.uv1); 413 | 414 | o.ambientOrLightmapUV = VertexGIForward(v, posWorld, normalWorld); 415 | 416 | #ifdef _PARALLAXMAP 417 | TANGENT_SPACE_ROTATION; 418 | half3 viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex)); 419 | o.tangentToWorldAndPackedData[0].w = viewDirForParallax.x; 420 | o.tangentToWorldAndPackedData[1].w = viewDirForParallax.y; 421 | o.tangentToWorldAndPackedData[2].w = viewDirForParallax.z; 422 | #endif 423 | 424 | UNITY_TRANSFER_FOG_COMBINED_WITH_EYE_VEC(o,o.pos); 425 | return o; 426 | } 427 | 428 | half4 fragForwardBaseInternal (VertexOutputForwardBase i) 429 | { 430 | UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy); 431 | 432 | FRAGMENT_SETUP(s) 433 | 434 | UNITY_SETUP_INSTANCE_ID(i); 435 | UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); 436 | 437 | UnityLight mainLight = MainLight (); 438 | UNITY_LIGHT_ATTENUATION(atten, i, s.posWorld); 439 | 440 | half occlusion = Occlusion(i.tex.xyz); 441 | 442 | UnityGI gi = FragmentGI (s, occlusion, i.ambientOrLightmapUV, atten, mainLight); 443 | 444 | half4 c = UNITY_BRDF_PBS (s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, gi.light, gi.indirect); 445 | c.rgb += Emission(i.tex.xyz); 446 | 447 | UNITY_EXTRACT_FOG_FROM_EYE_VEC(i); 448 | UNITY_APPLY_FOG(_unity_fogCoord, c.rgb); 449 | return OutputForward (c, s.alpha); 450 | } 451 | 452 | half4 fragForwardBase (VertexOutputForwardBase i) : SV_Target // backward compatibility (this used to be the fragment entry function) 453 | { 454 | return fragForwardBaseInternal(i); 455 | } 456 | 457 | // ------------------------------------------------------------------ 458 | // Additive forward pass (one light per pass) 459 | 460 | struct VertexOutputForwardAdd 461 | { 462 | UNITY_POSITION(pos); 463 | float4 tex : TEXCOORD0; 464 | float4 eyeVec : TEXCOORD1; // eyeVec.xyz | fogCoord 465 | float4 tangentToWorldAndLightDir[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:lightDir] 466 | float3 posWorld : TEXCOORD5; 467 | UNITY_LIGHTING_COORDS(6, 7) 468 | 469 | // next ones would not fit into SM2.0 limits, but they are always for SM3.0+ 470 | #if defined(_PARALLAXMAP) 471 | half3 viewDirForParallax : TEXCOORD8; 472 | #endif 473 | 474 | UNITY_VERTEX_OUTPUT_STEREO 475 | }; 476 | 477 | VertexOutputForwardAdd vertForwardAdd (VertexInput v) 478 | { 479 | UNITY_SETUP_INSTANCE_ID(v); 480 | VertexOutputForwardAdd o; 481 | UNITY_INITIALIZE_OUTPUT(VertexOutputForwardAdd, o); 482 | UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); 483 | 484 | float4 posWorld = mul(unity_ObjectToWorld, v.vertex); 485 | o.pos = UnityObjectToClipPos(v.vertex); 486 | 487 | o.tex = TexCoords(v); 488 | o.eyeVec.xyz = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos); 489 | o.posWorld = posWorld.xyz; 490 | float3 normalWorld = UnityObjectToWorldNormal(v.normal); 491 | #ifdef _TANGENT_TO_WORLD 492 | float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); 493 | 494 | float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w); 495 | o.tangentToWorldAndLightDir[0].xyz = tangentToWorld[0]; 496 | o.tangentToWorldAndLightDir[1].xyz = tangentToWorld[1]; 497 | o.tangentToWorldAndLightDir[2].xyz = tangentToWorld[2]; 498 | #else 499 | o.tangentToWorldAndLightDir[0].xyz = 0; 500 | o.tangentToWorldAndLightDir[1].xyz = 0; 501 | o.tangentToWorldAndLightDir[2].xyz = normalWorld; 502 | #endif 503 | //We need this for shadow receiving and lighting 504 | UNITY_TRANSFER_LIGHTING(o, v.uv1); 505 | 506 | float3 lightDir = _WorldSpaceLightPos0.xyz - posWorld.xyz * _WorldSpaceLightPos0.w; 507 | #ifndef USING_DIRECTIONAL_LIGHT 508 | lightDir = NormalizePerVertexNormal(lightDir); 509 | #endif 510 | o.tangentToWorldAndLightDir[0].w = lightDir.x; 511 | o.tangentToWorldAndLightDir[1].w = lightDir.y; 512 | o.tangentToWorldAndLightDir[2].w = lightDir.z; 513 | 514 | #ifdef _PARALLAXMAP 515 | TANGENT_SPACE_ROTATION; 516 | o.viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex)); 517 | #endif 518 | 519 | UNITY_TRANSFER_FOG_COMBINED_WITH_EYE_VEC(o, o.pos); 520 | return o; 521 | } 522 | 523 | half4 fragForwardAddInternal (VertexOutputForwardAdd i) 524 | { 525 | UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy); 526 | 527 | UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); 528 | 529 | FRAGMENT_SETUP_FWDADD(s) 530 | 531 | UNITY_LIGHT_ATTENUATION(atten, i, s.posWorld) 532 | UnityLight light = AdditiveLight (IN_LIGHTDIR_FWDADD(i), atten); 533 | UnityIndirect noIndirect = ZeroIndirect (); 534 | 535 | half4 c = UNITY_BRDF_PBS (s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, light, noIndirect); 536 | 537 | UNITY_EXTRACT_FOG_FROM_EYE_VEC(i); 538 | UNITY_APPLY_FOG_COLOR(_unity_fogCoord, c.rgb, half4(0,0,0,0)); // fog towards black in additive pass 539 | return OutputForward (c, s.alpha); 540 | } 541 | 542 | half4 fragForwardAdd (VertexOutputForwardAdd i) : SV_Target // backward compatibility (this used to be the fragment entry function) 543 | { 544 | return fragForwardAddInternal(i); 545 | } 546 | 547 | // ------------------------------------------------------------------ 548 | // Deferred pass 549 | 550 | struct VertexOutputDeferred 551 | { 552 | UNITY_POSITION(pos); 553 | float4 tex : TEXCOORD0; 554 | float3 eyeVec : TEXCOORD1; 555 | float4 tangentToWorldAndPackedData[3] : TEXCOORD2; // [3x3:tangentToWorld | 1x3:viewDirForParallax or worldPos] 556 | half4 ambientOrLightmapUV : TEXCOORD5; // SH or Lightmap UVs 557 | 558 | #if UNITY_REQUIRE_FRAG_WORLDPOS && !UNITY_PACK_WORLDPOS_WITH_TANGENT 559 | float3 posWorld : TEXCOORD6; 560 | #endif 561 | 562 | UNITY_VERTEX_INPUT_INSTANCE_ID 563 | UNITY_VERTEX_OUTPUT_STEREO 564 | }; 565 | 566 | 567 | VertexOutputDeferred vertDeferred (VertexInput v) 568 | { 569 | UNITY_SETUP_INSTANCE_ID(v); 570 | VertexOutputDeferred o; 571 | UNITY_INITIALIZE_OUTPUT(VertexOutputDeferred, o); 572 | UNITY_TRANSFER_INSTANCE_ID(v, o); 573 | UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); 574 | 575 | float4 posWorld = mul(unity_ObjectToWorld, v.vertex); 576 | #if UNITY_REQUIRE_FRAG_WORLDPOS 577 | #if UNITY_PACK_WORLDPOS_WITH_TANGENT 578 | o.tangentToWorldAndPackedData[0].w = posWorld.x; 579 | o.tangentToWorldAndPackedData[1].w = posWorld.y; 580 | o.tangentToWorldAndPackedData[2].w = posWorld.z; 581 | #else 582 | o.posWorld = posWorld.xyz; 583 | #endif 584 | #endif 585 | o.pos = UnityObjectToClipPos(v.vertex); 586 | 587 | o.tex = TexCoords(v); 588 | o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos); 589 | float3 normalWorld = UnityObjectToWorldNormal(v.normal); 590 | #ifdef _TANGENT_TO_WORLD 591 | float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); 592 | 593 | float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w); 594 | o.tangentToWorldAndPackedData[0].xyz = tangentToWorld[0]; 595 | o.tangentToWorldAndPackedData[1].xyz = tangentToWorld[1]; 596 | o.tangentToWorldAndPackedData[2].xyz = tangentToWorld[2]; 597 | #else 598 | o.tangentToWorldAndPackedData[0].xyz = 0; 599 | o.tangentToWorldAndPackedData[1].xyz = 0; 600 | o.tangentToWorldAndPackedData[2].xyz = normalWorld; 601 | #endif 602 | 603 | o.ambientOrLightmapUV = 0; 604 | #ifdef LIGHTMAP_ON 605 | o.ambientOrLightmapUV.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw; 606 | #elif UNITY_SHOULD_SAMPLE_SH 607 | o.ambientOrLightmapUV.rgb = ShadeSHPerVertex (normalWorld, o.ambientOrLightmapUV.rgb); 608 | #endif 609 | #ifdef DYNAMICLIGHTMAP_ON 610 | o.ambientOrLightmapUV.zw = v.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; 611 | #endif 612 | 613 | #ifdef _PARALLAXMAP 614 | TANGENT_SPACE_ROTATION; 615 | half3 viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex)); 616 | o.tangentToWorldAndPackedData[0].w = viewDirForParallax.x; 617 | o.tangentToWorldAndPackedData[1].w = viewDirForParallax.y; 618 | o.tangentToWorldAndPackedData[2].w = viewDirForParallax.z; 619 | #endif 620 | 621 | return o; 622 | } 623 | 624 | void fragDeferred ( 625 | VertexOutputDeferred i, 626 | out half4 outGBuffer0 : SV_Target0, 627 | out half4 outGBuffer1 : SV_Target1, 628 | out half4 outGBuffer2 : SV_Target2, 629 | out half4 outEmission : SV_Target3 // RT3: emission (rgb), --unused-- (a) 630 | #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4) 631 | ,out half4 outShadowMask : SV_Target4 // RT4: shadowmask (rgba) 632 | #endif 633 | ) 634 | { 635 | #if (SHADER_TARGET < 30) 636 | outGBuffer0 = 1; 637 | outGBuffer1 = 1; 638 | outGBuffer2 = 0; 639 | outEmission = 0; 640 | #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4) 641 | outShadowMask = 1; 642 | #endif 643 | return; 644 | #endif 645 | 646 | UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy); 647 | 648 | FRAGMENT_SETUP(s) 649 | UNITY_SETUP_INSTANCE_ID(i); 650 | 651 | // no analytic lights in this pass 652 | UnityLight dummyLight = DummyLight (); 653 | half atten = 1; 654 | 655 | // only GI 656 | half occlusion = Occlusion(i.tex.xyz); 657 | #if UNITY_ENABLE_REFLECTION_BUFFERS 658 | bool sampleReflectionsInDeferred = false; 659 | #else 660 | bool sampleReflectionsInDeferred = true; 661 | #endif 662 | 663 | UnityGI gi = FragmentGI (s, occlusion, i.ambientOrLightmapUV, atten, dummyLight, sampleReflectionsInDeferred); 664 | 665 | half3 emissiveColor = UNITY_BRDF_PBS (s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, gi.light, gi.indirect).rgb; 666 | 667 | #ifdef _EMISSION 668 | emissiveColor += Emission (i.tex.xyz); 669 | #endif 670 | 671 | #ifndef UNITY_HDR_ON 672 | emissiveColor.rgb = exp2(-emissiveColor.rgb); 673 | #endif 674 | 675 | UnityStandardData data; 676 | data.diffuseColor = s.diffColor; 677 | data.occlusion = occlusion; 678 | data.specularColor = s.specColor; 679 | data.smoothness = s.smoothness; 680 | data.normalWorld = s.normalWorld; 681 | 682 | UnityStandardDataToGbuffer(data, outGBuffer0, outGBuffer1, outGBuffer2); 683 | 684 | // Emissive lighting buffer 685 | outEmission = half4(emissiveColor, 1); 686 | 687 | // Baked direct lighting occlusion if any 688 | #if defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4) 689 | outShadowMask = UnityGetRawBakedOcclusions(i.ambientOrLightmapUV.xy, IN_WORLDPOS(i)); 690 | #endif 691 | } 692 | 693 | 694 | // 695 | // Old FragmentGI signature. Kept only for backward compatibility and will be removed soon 696 | // 697 | 698 | inline UnityGI FragmentGI( 699 | float3 posWorld, 700 | half occlusion, half4 i_ambientOrLightmapUV, half atten, half smoothness, half3 normalWorld, half3 eyeVec, 701 | UnityLight light, 702 | bool reflections) 703 | { 704 | // we init only fields actually used 705 | FragmentCommonData s = (FragmentCommonData)0; 706 | s.smoothness = smoothness; 707 | s.normalWorld = normalWorld; 708 | s.eyeVec = eyeVec; 709 | s.posWorld = posWorld; 710 | return FragmentGI(s, occlusion, i_ambientOrLightmapUV, atten, light, reflections); 711 | } 712 | inline UnityGI FragmentGI ( 713 | float3 posWorld, 714 | half occlusion, half4 i_ambientOrLightmapUV, half atten, half smoothness, half3 normalWorld, half3 eyeVec, 715 | UnityLight light) 716 | { 717 | return FragmentGI (posWorld, occlusion, i_ambientOrLightmapUV, atten, smoothness, normalWorld, eyeVec, light, true); 718 | } 719 | 720 | #endif // UNITY_STANDARD_CORE_INCLUDED 721 | -------------------------------------------------------------------------------- /CGIncludes/UnityStandardCore_TexArray.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 89041522cc672684b885d6de4f32aca7 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /CGIncludes/UnityStandardInput_TexArray.cginc: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | #ifndef UNITY_STANDARD_INPUT_INCLUDED 4 | #define UNITY_STANDARD_INPUT_INCLUDED 5 | 6 | #include "UnityCG.cginc" 7 | #include "UnityStandardConfig.cginc" 8 | #include "UnityPBSLighting.cginc" // TBD: remove 9 | #include "UnityStandardUtils.cginc" 10 | 11 | //--------------------------------------- 12 | // Directional lightmaps & Parallax require tangent space too 13 | #if (_NORMALMAP || DIRLIGHTMAP_COMBINED || _PARALLAXMAP) 14 | #define _TANGENT_TO_WORLD 1 15 | #endif 16 | 17 | #if (_DETAIL_MULX2 || _DETAIL_MUL || _DETAIL_ADD || _DETAIL_LERP) 18 | #define _DETAIL 1 19 | #endif 20 | 21 | //--------------------------------------- 22 | half4 _Color; 23 | half _Cutoff; 24 | 25 | UNITY_DECLARE_TEX2DARRAY(_MainTex); 26 | float4 _MainTex_ST; 27 | 28 | sampler2D _DetailAlbedoMap; 29 | float4 _DetailAlbedoMap_ST; 30 | 31 | UNITY_DECLARE_TEX2DARRAY(_BumpMap); 32 | half _BumpScale; 33 | 34 | sampler2D _DetailMask; 35 | sampler2D _DetailNormalMap; 36 | half _DetailNormalMapScale; 37 | 38 | sampler2D _SpecGlossMap; 39 | UNITY_DECLARE_TEX2DARRAY(_MetallicGlossMap); 40 | half _Metallic; 41 | float _Glossiness; 42 | float _GlossMapScale; 43 | 44 | UNITY_DECLARE_TEX2DARRAY(_OcclusionMap); 45 | half _OcclusionStrength; 46 | 47 | UNITY_DECLARE_TEX2DARRAY(_ParallaxMap); 48 | half _Parallax; 49 | half _UVSec; 50 | 51 | half4 _EmissionColor; 52 | UNITY_DECLARE_TEX2DARRAY(_EmissionMap); 53 | 54 | //------------------------------------------------------------------------------------- 55 | // Input functions 56 | 57 | struct VertexInput 58 | { 59 | float4 vertex : POSITION; 60 | half3 normal : NORMAL; 61 | float3 uv0 : TEXCOORD0; 62 | float2 uv1 : TEXCOORD1; 63 | #if defined(DYNAMICLIGHTMAP_ON) || defined(UNITY_PASS_META) 64 | float2 uv2 : TEXCOORD2; 65 | #endif 66 | #ifdef _TANGENT_TO_WORLD 67 | half4 tangent : TANGENT; 68 | #endif 69 | UNITY_VERTEX_INPUT_INSTANCE_ID 70 | }; 71 | 72 | float4 TexCoords(VertexInput v) 73 | { 74 | float4 texcoord; 75 | texcoord.xy = TRANSFORM_TEX(v.uv0, _MainTex); // Always source from uv0 76 | texcoord.z = v.uv0.z; 77 | // TODO need another way to deal with _DetailAlbedoMap since we can't use it for texcoord. 78 | //texcoord.zw = TRANSFORM_TEX(((_UVSec == 0) ? v.uv0 : v.uv1), _DetailAlbedoMap); 79 | return texcoord; 80 | } 81 | 82 | half DetailMask(float2 uv) 83 | { 84 | return tex2D (_DetailMask, uv).a; 85 | } 86 | 87 | half3 Albedo(float4 texcoords) 88 | { 89 | half3 tmp = UNITY_SAMPLE_TEX2DARRAY(_MainTex, texcoords.xyz).rgb; 90 | half3 albedo = _Color.rgb * tmp.rgb; 91 | #if _DETAIL 92 | #if (SHADER_TARGET < 30) 93 | // SM20: instruction count limitation 94 | // SM20: no detail mask 95 | half mask = 1; 96 | #else 97 | half mask = DetailMask(texcoords.xy); 98 | #endif 99 | half3 detailAlbedo = tex2D (_DetailAlbedoMap, texcoords.zw).rgb; 100 | #if _DETAIL_MULX2 101 | albedo *= LerpWhiteTo (detailAlbedo * unity_ColorSpaceDouble.rgb, mask); 102 | #elif _DETAIL_MUL 103 | albedo *= LerpWhiteTo (detailAlbedo, mask); 104 | #elif _DETAIL_ADD 105 | albedo += detailAlbedo * mask; 106 | #elif _DETAIL_LERP 107 | albedo = lerp (albedo, detailAlbedo, mask); 108 | #endif 109 | #endif 110 | return albedo; 111 | } 112 | 113 | half Alpha(float3 uv) 114 | { 115 | #if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A) 116 | return _Color.a; 117 | #else 118 | return UNITY_SAMPLE_TEX2DARRAY(_MainTex, uv).a * _Color.a; 119 | #endif 120 | } 121 | 122 | half Occlusion(float3 uv) 123 | { 124 | #if (SHADER_TARGET < 30) 125 | // SM20: instruction count limitation 126 | // SM20: simpler occlusion 127 | return UNITY_SAMPLE_TEX2DARRAY(_OcclusionMap, uv).g; 128 | #else 129 | // This check is neccessary because tex arrays don't support default textures (white, black, grey..) empty texture slots return .5. 130 | // Doesn't lightmap properly if no occlusion map. We need to return occlusion of 1 in this case. 131 | #if (_HAS_OCCLUSION_MAP) 132 | half occ = UNITY_SAMPLE_TEX2DARRAY(_OcclusionMap, uv).g; 133 | #else 134 | half occ = 1; 135 | #endif 136 | return LerpOneTo (occ, _OcclusionStrength); 137 | #endif 138 | } 139 | 140 | half4 SpecularGloss(float3 uv) 141 | { 142 | half4 sg; 143 | #ifdef _SPECGLOSSMAP 144 | #if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A) 145 | sg.rgb = tex2D(_SpecGlossMap, uv).rgb; 146 | sg.a = UNITY_SAMPLE_TEX2DARRAY(_MainTex, uv).a; 147 | #else 148 | sg = tex2D(_SpecGlossMap, uv); 149 | #endif 150 | sg.a *= _GlossMapScale; 151 | #else 152 | sg.rgb = _SpecColor.rgb; 153 | #ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 154 | sg.a = UNITY_SAMPLE_TEX2DARRAY(_MainTex, uv).a * _GlossMapScale; 155 | #else 156 | sg.a = _Glossiness; 157 | #endif 158 | #endif 159 | return sg; 160 | } 161 | 162 | half2 MetallicGloss(float3 uv) 163 | { 164 | half2 mg; 165 | 166 | #ifdef _METALLICGLOSSMAP 167 | #ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 168 | mg.r = UNITY_SAMPLE_TEX2DARRAY(_MetallicGlossMap, uv).r; 169 | mg.g = UNITY_SAMPLE_TEX2DARRAY(_MainTex, uv).a; 170 | #else 171 | mg = UNITY_SAMPLE_TEX2DARRAY(_MetallicGlossMap, uv).ra; 172 | #endif 173 | mg.g *= _GlossMapScale; 174 | #else 175 | mg.r = _Metallic; 176 | #ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 177 | mg.g = UNITY_SAMPLE_TEX2DARRAY(_MainTex, uv).a * _GlossMapScale; 178 | #else 179 | mg.g = _Glossiness; 180 | #endif 181 | #endif 182 | return mg; 183 | } 184 | 185 | half2 MetallicRough(float3 uv) 186 | { 187 | half2 mg; 188 | #ifdef _METALLICGLOSSMAP 189 | mg.r = UNITY_SAMPLE_TEX2DARRAY(_MetallicGlossMap, uv).r; 190 | #else 191 | mg.r = _Metallic; 192 | #endif 193 | 194 | #ifdef _SPECGLOSSMAP 195 | mg.g = 1.0f - tex2D(_SpecGlossMap, uv).r; 196 | #else 197 | mg.g = 1.0f - _Glossiness; 198 | #endif 199 | return mg; 200 | } 201 | 202 | half3 Emission(float3 uv) 203 | { 204 | #ifndef _EMISSION 205 | return 0; 206 | #else 207 | return UNITY_SAMPLE_TEX2DARRAY(_EmissionMap, uv).rgb * _EmissionColor.rgb; 208 | #endif 209 | } 210 | 211 | #ifdef _NORMALMAP 212 | half3 NormalInTangentSpace(float4 texcoords) 213 | { 214 | half3 normalTangent = UnpackScaleNormal(UNITY_SAMPLE_TEX2DARRAY(_BumpMap, texcoords.xyz), _BumpScale); 215 | 216 | #if _DETAIL && defined(UNITY_ENABLE_DETAIL_NORMALMAP) 217 | half mask = DetailMask(texcoords.xy); 218 | half3 detailNormalTangent = UnpackScaleNormal(tex2D (_DetailNormalMap, texcoords.zw), _DetailNormalMapScale); 219 | #if _DETAIL_LERP 220 | normalTangent = lerp( 221 | normalTangent, 222 | detailNormalTangent, 223 | mask); 224 | #else 225 | normalTangent = lerp( 226 | normalTangent, 227 | BlendNormals(normalTangent, detailNormalTangent), 228 | mask); 229 | #endif 230 | #endif 231 | 232 | return normalTangent; 233 | } 234 | #endif 235 | 236 | float4 Parallax (float4 texcoords, half3 viewDir) 237 | { 238 | #if !defined(_PARALLAXMAP) || (SHADER_TARGET < 30) 239 | // Disable parallax on pre-SM3.0 shader target models 240 | return texcoords; 241 | #else 242 | half h = UNITY_SAMPLE_TEX2DARRAY(_ParallaxMap, texcoords.xyz).g; 243 | float2 offset = ParallaxOffset1Step (h, _Parallax, viewDir); 244 | return float4(texcoords.xy + offset, texcoords.zw + offset); 245 | #endif 246 | 247 | } 248 | 249 | #endif // UNITY_STANDARD_INPUT_INCLUDED 250 | -------------------------------------------------------------------------------- /CGIncludes/UnityStandardInput_TexArray.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a11dab4a66ad20b49a138d30fd4487c8 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /CGIncludes/UnityStandardMeta_TexArray.cginc: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | #ifndef UNITY_STANDARD_META_INCLUDED 4 | #define UNITY_STANDARD_META_INCLUDED 5 | 6 | // Functionality for Standard shader "meta" pass 7 | // (extracts albedo/emission for lightmapper etc.) 8 | 9 | #include "UnityCG.cginc" 10 | #include "UnityStandardInput_TexArray.cginc" 11 | #include "UnityMetaPass.cginc" 12 | #include "UnityStandardCore_TexArray.cginc" 13 | 14 | struct v2f_meta 15 | { 16 | float4 pos : SV_POSITION; 17 | float4 uv : TEXCOORD0; 18 | #ifdef EDITOR_VISUALIZATION 19 | float2 vizUV : TEXCOORD1; 20 | float4 lightCoord : TEXCOORD2; 21 | #endif 22 | }; 23 | 24 | v2f_meta vert_meta (VertexInput v) 25 | { 26 | v2f_meta o; 27 | o.pos = UnityMetaVertexPosition(v.vertex, v.uv1.xy, v.uv2.xy, unity_LightmapST, unity_DynamicLightmapST); 28 | o.uv = TexCoords(v); 29 | #ifdef EDITOR_VISUALIZATION 30 | o.vizUV = 0; 31 | o.lightCoord = 0; 32 | if (unity_VisualizationMode == EDITORVIZ_TEXTURE) 33 | o.vizUV = UnityMetaVizUV(unity_EditorViz_UVIndex, v.uv0.xy, v.uv1.xy, v.uv2.xy, unity_EditorViz_Texture_ST); 34 | else if (unity_VisualizationMode == EDITORVIZ_SHOWLIGHTMASK) 35 | { 36 | o.vizUV = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw; 37 | o.lightCoord = mul(unity_EditorViz_WorldToLight, mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1))); 38 | } 39 | #endif 40 | return o; 41 | } 42 | 43 | // Albedo for lightmapping should basically be diffuse color. 44 | // But rough metals (black diffuse) still scatter quite a lot of light around, so 45 | // we want to take some of that into account too. 46 | half3 UnityLightmappingAlbedo (half3 diffuse, half3 specular, half smoothness) 47 | { 48 | half roughness = SmoothnessToRoughness(smoothness); 49 | half3 res = diffuse; 50 | res += specular * roughness * 0.5; 51 | return res; 52 | } 53 | 54 | float4 frag_meta (v2f_meta i) : SV_Target 55 | { 56 | // we're interested in diffuse & specular colors, 57 | // and surface roughness to produce final albedo. 58 | FragmentCommonData data = UNITY_SETUP_BRDF_INPUT (i.uv); 59 | 60 | UnityMetaInput o; 61 | UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o); 62 | 63 | #ifdef EDITOR_VISUALIZATION 64 | o.Albedo = data.diffColor; 65 | o.VizUV = i.vizUV; 66 | o.LightCoord = i.lightCoord; 67 | #else 68 | o.Albedo = UnityLightmappingAlbedo (data.diffColor, data.specColor, data.smoothness); 69 | #endif 70 | o.SpecularColor = data.specColor; 71 | o.Emission = Emission(i.uv.xyz); 72 | 73 | return UnityMetaFragment(o); 74 | } 75 | 76 | #endif // UNITY_STANDARD_META_INCLUDED 77 | -------------------------------------------------------------------------------- /CGIncludes/UnityStandardMeta_TexArray.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 15972343c1f18654fbd5ec1653844c36 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | preprocessorOverride: 0 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /DefaultResourcesExtra.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1238ebdd22253fa4783e1b548a7c9b72 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /DefaultResourcesExtra/Standard_TexArray.shader: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | Shader "MeshBaker/StandardTextureArray" 4 | { 5 | Properties 6 | { 7 | _Color("Color", Color) = (1,1,1,1) 8 | _MainTex("Albedo", 2DArray) = "" {} 9 | 10 | _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 11 | 12 | _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5 13 | _GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0 14 | [Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0 15 | 16 | [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0 17 | _MetallicGlossMap("Metallic", 2DArray) = "" {} 18 | 19 | [ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 20 | [ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0 21 | 22 | _BumpScale("Scale", Float) = 1.0 23 | _BumpMap("Normal Map", 2DArray) = "" {} 24 | 25 | _Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02 26 | _ParallaxMap ("Height Map", 2DArray) = "" {} 27 | 28 | _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0 29 | _OcclusionMap("Occlusion", 2DArray) = "white" {} 30 | 31 | _EmissionColor("Color", Color) = (0,0,0) 32 | _EmissionMap("Emission", 2DArray) = "" {} 33 | 34 | _DetailMask("Detail Mask", 2D) = "" {} 35 | 36 | _DetailAlbedoMap("Detail Albedo x2", 2D) = "" {} 37 | _DetailNormalMapScale("Scale", Float) = 1.0 38 | _DetailNormalMap("Normal Map", 2D) = "bump" {} 39 | 40 | [Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0 41 | 42 | 43 | // Blending state 44 | [HideInInspector] _Mode ("__mode", Float) = 0.0 45 | [HideInInspector] _SrcBlend ("__src", Float) = 1.0 46 | [HideInInspector] _DstBlend ("__dst", Float) = 0.0 47 | [HideInInspector] _ZWrite ("__zw", Float) = 1.0 48 | } 49 | 50 | CGINCLUDE 51 | #define UNITY_SETUP_BRDF_INPUT MetallicSetup 52 | ENDCG 53 | 54 | SubShader 55 | { 56 | Tags { "RenderType"="Opaque" "PerformanceChecks"="False" } 57 | LOD 300 58 | 59 | 60 | // ------------------------------------------------------------------ 61 | // Base forward pass (directional light, emission, lightmaps, ...) 62 | Pass 63 | { 64 | Name "FORWARD" 65 | Tags { "LightMode" = "ForwardBase" } 66 | 67 | Blend [_SrcBlend] [_DstBlend] 68 | ZWrite [_ZWrite] 69 | 70 | CGPROGRAM 71 | #pragma target 3.0 72 | 73 | // ------------------------------------- 74 | 75 | #pragma shader_feature _NORMALMAP 76 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 77 | #pragma shader_feature _EMISSION 78 | #pragma shader_feature _METALLICGLOSSMAP 79 | #pragma shader_feature ___ _DETAIL_MULX2 80 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 81 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 82 | #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF 83 | #pragma shader_feature _PARALLAXMAP 84 | 85 | #pragma multi_compile_fwdbase 86 | #pragma multi_compile_fog 87 | #pragma multi_compile_instancing 88 | // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes. 89 | //#pragma multi_compile _ LOD_FADE_CROSSFADE 90 | 91 | #pragma vertex vertBase 92 | #pragma fragment fragBase 93 | #include "../CGIncludes/UnityStandardCoreForward_TexArray.cginc" 94 | 95 | ENDCG 96 | } 97 | // ------------------------------------------------------------------ 98 | // Additive forward pass (one light per pass) 99 | Pass 100 | { 101 | Name "FORWARD_DELTA" 102 | Tags { "LightMode" = "ForwardAdd" } 103 | Blend [_SrcBlend] One 104 | Fog { Color (0,0,0,0) } // in additive pass fog should be black 105 | ZWrite Off 106 | ZTest LEqual 107 | 108 | CGPROGRAM 109 | #pragma target 3.0 110 | 111 | // ------------------------------------- 112 | 113 | 114 | #pragma shader_feature _NORMALMAP 115 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 116 | #pragma shader_feature _METALLICGLOSSMAP 117 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 118 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 119 | #pragma shader_feature ___ _DETAIL_MULX2 120 | #pragma shader_feature _PARALLAXMAP 121 | 122 | #pragma multi_compile_fwdadd_fullshadows 123 | #pragma multi_compile_fog 124 | // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes. 125 | //#pragma multi_compile _ LOD_FADE_CROSSFADE 126 | 127 | #pragma vertex vertAdd 128 | #pragma fragment fragAdd 129 | #include "../CGIncludes/UnityStandardCoreForward_TexArray.cginc" 130 | 131 | ENDCG 132 | } 133 | // ------------------------------------------------------------------ 134 | // Shadow rendering pass 135 | Pass { 136 | Name "ShadowCaster" 137 | Tags { "LightMode" = "ShadowCaster" } 138 | 139 | ZWrite On ZTest LEqual 140 | 141 | CGPROGRAM 142 | #pragma target 3.0 143 | 144 | // ------------------------------------- 145 | 146 | 147 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 148 | #pragma shader_feature _METALLICGLOSSMAP 149 | #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 150 | #pragma shader_feature _PARALLAXMAP 151 | #pragma multi_compile_shadowcaster 152 | #pragma multi_compile_instancing 153 | // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes. 154 | //#pragma multi_compile _ LOD_FADE_CROSSFADE 155 | 156 | #pragma vertex vertShadowCaster 157 | #pragma fragment fragShadowCaster 158 | 159 | #include "UnityStandardShadow.cginc" 160 | 161 | ENDCG 162 | } 163 | // ------------------------------------------------------------------ 164 | // Deferred pass 165 | Pass 166 | { 167 | Name "DEFERRED" 168 | Tags { "LightMode" = "Deferred" } 169 | 170 | CGPROGRAM 171 | #pragma target 3.0 172 | #pragma exclude_renderers nomrt 173 | 174 | 175 | // ------------------------------------- 176 | 177 | #pragma shader_feature _NORMALMAP 178 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 179 | #pragma shader_feature _EMISSION 180 | #pragma shader_feature _METALLICGLOSSMAP 181 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 182 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 183 | #pragma shader_feature ___ _DETAIL_MULX2 184 | #pragma shader_feature _PARALLAXMAP 185 | 186 | #pragma multi_compile_prepassfinal 187 | #pragma multi_compile_instancing 188 | // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes. 189 | //#pragma multi_compile _ LOD_FADE_CROSSFADE 190 | 191 | #pragma vertex vertDeferred 192 | #pragma fragment fragDeferred 193 | 194 | #include "../CGIncludes/UnityStandardCore_TexArray.cginc" 195 | 196 | ENDCG 197 | } 198 | 199 | // ------------------------------------------------------------------ 200 | // Extracts information for lightmapping, GI (emission, albedo, ...) 201 | // This pass it not used during regular rendering. 202 | Pass 203 | { 204 | Name "META" 205 | Tags { "LightMode"="Meta" } 206 | 207 | Cull Off 208 | 209 | CGPROGRAM 210 | #pragma vertex vert_meta 211 | #pragma fragment frag_meta 212 | 213 | #pragma shader_feature _EMISSION 214 | #pragma shader_feature _METALLICGLOSSMAP 215 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 216 | #pragma shader_feature ___ _DETAIL_MULX2 217 | #pragma shader_feature EDITOR_VISUALIZATION 218 | 219 | #include "../CGIncludes/UnityStandardMeta_TexArray.cginc" 220 | ENDCG 221 | } 222 | } 223 | 224 | SubShader 225 | { 226 | Tags { "RenderType"="Opaque" "PerformanceChecks"="False" } 227 | LOD 150 228 | 229 | // ------------------------------------------------------------------ 230 | // Base forward pass (directional light, emission, lightmaps, ...) 231 | Pass 232 | { 233 | Name "FORWARD" 234 | Tags { "LightMode" = "ForwardBase" } 235 | 236 | Blend [_SrcBlend] [_DstBlend] 237 | ZWrite [_ZWrite] 238 | 239 | CGPROGRAM 240 | #pragma target 2.0 241 | 242 | #pragma shader_feature _NORMALMAP 243 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 244 | #pragma shader_feature _EMISSION 245 | #pragma shader_feature _METALLICGLOSSMAP 246 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 247 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 248 | #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF 249 | // SM2.0: NOT SUPPORTED shader_feature ___ _DETAIL_MULX2 250 | // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP 251 | 252 | #pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED 253 | 254 | #pragma multi_compile_fwdbase 255 | #pragma multi_compile_fog 256 | 257 | #pragma vertex vertBase 258 | #pragma fragment fragBase 259 | #include "../CGIncludes/UnityStandardCoreForward_TexArray.cginc" 260 | 261 | ENDCG 262 | } 263 | // ------------------------------------------------------------------ 264 | // Additive forward pass (one light per pass) 265 | Pass 266 | { 267 | Name "FORWARD_DELTA" 268 | Tags { "LightMode" = "ForwardAdd" } 269 | Blend [_SrcBlend] One 270 | Fog { Color (0,0,0,0) } // in additive pass fog should be black 271 | ZWrite Off 272 | ZTest LEqual 273 | 274 | CGPROGRAM 275 | #pragma target 2.0 276 | 277 | #pragma shader_feature _NORMALMAP 278 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 279 | #pragma shader_feature _METALLICGLOSSMAP 280 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 281 | #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 282 | #pragma shader_feature ___ _DETAIL_MULX2 283 | // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP 284 | #pragma skip_variants SHADOWS_SOFT 285 | 286 | #pragma multi_compile_fwdadd_fullshadows 287 | #pragma multi_compile_fog 288 | 289 | #pragma vertex vertAdd 290 | #pragma fragment fragAdd 291 | #include "../CGIncludes/UnityStandardCoreForward_TexArray.cginc" 292 | 293 | ENDCG 294 | } 295 | // ------------------------------------------------------------------ 296 | // Shadow rendering pass 297 | Pass { 298 | Name "ShadowCaster" 299 | Tags { "LightMode" = "ShadowCaster" } 300 | 301 | ZWrite On ZTest LEqual 302 | 303 | CGPROGRAM 304 | #pragma target 2.0 305 | 306 | #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 307 | #pragma shader_feature _METALLICGLOSSMAP 308 | #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 309 | #pragma skip_variants SHADOWS_SOFT 310 | #pragma multi_compile_shadowcaster 311 | 312 | #pragma vertex vertShadowCaster 313 | #pragma fragment fragShadowCaster 314 | 315 | #include "UnityStandardShadow.cginc" 316 | 317 | ENDCG 318 | } 319 | 320 | // ------------------------------------------------------------------ 321 | // Extracts information for lightmapping, GI (emission, albedo, ...) 322 | // This pass it not used during regular rendering. 323 | Pass 324 | { 325 | Name "META" 326 | Tags { "LightMode"="Meta" } 327 | 328 | Cull Off 329 | 330 | CGPROGRAM 331 | #pragma vertex vert_meta 332 | #pragma fragment frag_meta 333 | 334 | #pragma shader_feature _EMISSION 335 | #pragma shader_feature _METALLICGLOSSMAP 336 | #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 337 | #pragma shader_feature ___ _DETAIL_MULX2 338 | #pragma shader_feature EDITOR_VISUALIZATION 339 | 340 | #include "../CGIncludes/UnityStandardMeta_TexArray.cginc" 341 | ENDCG 342 | } 343 | } 344 | 345 | 346 | FallBack "VertexLit" 347 | CustomEditor "MB_TexArrayStandardShaderGUI" 348 | } 349 | -------------------------------------------------------------------------------- /DefaultResourcesExtra/Standard_TexArray.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ab15c5a9109848d4ab18a7657b9ca9ca 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a73cbeb28219c114daf371006add39d3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/MB_TexArrayStandardShaderGUI.cs: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | using System; 4 | using UnityEngine; 5 | //using TargetAttributes = UnityEditor.BuildTargetDiscovery.TargetAttributes; // inaccessible 6 | 7 | namespace UnityEditor 8 | { 9 | internal class MB_TexArrayStandardShaderGUI : ShaderGUI 10 | { 11 | private enum WorkflowMode 12 | { 13 | Specular, 14 | Metallic, 15 | Dielectric 16 | } 17 | 18 | public enum BlendMode 19 | { 20 | Opaque, 21 | Cutout, 22 | Fade, // Old school alpha-blending mode, fresnel does not affect amount of transparency 23 | Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply 24 | } 25 | 26 | public enum SmoothnessMapChannel 27 | { 28 | SpecularMetallicAlpha, 29 | AlbedoAlpha, 30 | } 31 | 32 | private static class Styles 33 | { 34 | public static GUIContent uvSetLabel = EditorGUIUtility.TrTextContent("UV Set"); 35 | 36 | public static GUIContent albedoText = EditorGUIUtility.TrTextContent("Albedo", "Albedo (RGB) and Transparency (A)"); 37 | public static GUIContent alphaCutoffText = EditorGUIUtility.TrTextContent("Alpha Cutoff", "Threshold for alpha cutoff"); 38 | public static GUIContent specularMapText = EditorGUIUtility.TrTextContent("Specular", "Specular (RGB) and Smoothness (A)"); 39 | public static GUIContent metallicMapText = EditorGUIUtility.TrTextContent("Metallic", "Metallic (R) and Smoothness (A)"); 40 | public static GUIContent smoothnessText = EditorGUIUtility.TrTextContent("Smoothness", "Smoothness value"); 41 | public static GUIContent smoothnessScaleText = EditorGUIUtility.TrTextContent("Smoothness", "Smoothness scale factor"); 42 | public static GUIContent smoothnessMapChannelText = EditorGUIUtility.TrTextContent("Source", "Smoothness texture and channel"); 43 | public static GUIContent highlightsText = EditorGUIUtility.TrTextContent("Specular Highlights", "Specular Highlights"); 44 | public static GUIContent reflectionsText = EditorGUIUtility.TrTextContent("Reflections", "Glossy Reflections"); 45 | public static GUIContent normalMapText = EditorGUIUtility.TrTextContent("Normal Map", "Normal Map"); 46 | public static GUIContent heightMapText = EditorGUIUtility.TrTextContent("Height Map", "Height Map (G)"); 47 | public static GUIContent occlusionText = EditorGUIUtility.TrTextContent("Occlusion", "Occlusion (G)"); 48 | public static GUIContent emissionText = EditorGUIUtility.TrTextContent("Color", "Emission (RGB)"); 49 | public static GUIContent detailMaskText = EditorGUIUtility.TrTextContent("Detail Mask", "Mask for Secondary Maps (A)"); 50 | public static GUIContent detailAlbedoText = EditorGUIUtility.TrTextContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2"); 51 | public static GUIContent detailNormalMapText = EditorGUIUtility.TrTextContent("Normal Map", "Normal Map"); 52 | 53 | public static string primaryMapsText = "Main Maps"; 54 | public static string secondaryMapsText = "Secondary Maps"; 55 | public static string forwardText = "Forward Rendering Options"; 56 | public static string renderingMode = "Rendering Mode"; 57 | public static string advancedText = "Advanced Options"; 58 | public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode)); 59 | } 60 | 61 | MaterialProperty blendMode = null; 62 | MaterialProperty albedoMap = null; 63 | MaterialProperty albedoColor = null; 64 | MaterialProperty alphaCutoff = null; 65 | MaterialProperty specularMap = null; 66 | MaterialProperty specularColor = null; 67 | MaterialProperty metallicMap = null; 68 | MaterialProperty metallic = null; 69 | MaterialProperty smoothness = null; 70 | MaterialProperty smoothnessScale = null; 71 | MaterialProperty smoothnessMapChannel = null; 72 | MaterialProperty highlights = null; 73 | MaterialProperty reflections = null; 74 | MaterialProperty bumpScale = null; 75 | MaterialProperty bumpMap = null; 76 | MaterialProperty occlusionStrength = null; 77 | MaterialProperty occlusionMap = null; 78 | MaterialProperty heigtMapScale = null; 79 | MaterialProperty heightMap = null; 80 | MaterialProperty emissionColorForRendering = null; 81 | MaterialProperty emissionMap = null; 82 | MaterialProperty detailMask = null; 83 | MaterialProperty detailAlbedoMap = null; 84 | MaterialProperty detailNormalMapScale = null; 85 | MaterialProperty detailNormalMap = null; 86 | MaterialProperty uvSetSecondary = null; 87 | 88 | MaterialEditor m_MaterialEditor; 89 | WorkflowMode m_WorkflowMode = WorkflowMode.Specular; 90 | 91 | bool m_FirstTimeApply = true; 92 | 93 | public void FindProperties(MaterialProperty[] props) 94 | { 95 | blendMode = FindProperty("_Mode", props); 96 | albedoMap = FindProperty("_MainTex", props); 97 | albedoColor = FindProperty("_Color", props); 98 | alphaCutoff = FindProperty("_Cutoff", props); 99 | specularMap = FindProperty("_SpecGlossMap", props, false); 100 | specularColor = FindProperty("_SpecColor", props, false); 101 | metallicMap = FindProperty("_MetallicGlossMap", props, false); 102 | metallic = FindProperty("_Metallic", props, false); 103 | if (specularMap != null && specularColor != null) 104 | m_WorkflowMode = WorkflowMode.Specular; 105 | else if (metallicMap != null && metallic != null) 106 | m_WorkflowMode = WorkflowMode.Metallic; 107 | else 108 | m_WorkflowMode = WorkflowMode.Dielectric; 109 | smoothness = FindProperty("_Glossiness", props); 110 | smoothnessScale = FindProperty("_GlossMapScale", props, false); 111 | smoothnessMapChannel = FindProperty("_SmoothnessTextureChannel", props, false); 112 | highlights = FindProperty("_SpecularHighlights", props, false); 113 | reflections = FindProperty("_GlossyReflections", props, false); 114 | bumpScale = FindProperty("_BumpScale", props); 115 | bumpMap = FindProperty("_BumpMap", props); 116 | heigtMapScale = FindProperty("_Parallax", props); 117 | heightMap = FindProperty("_ParallaxMap", props); 118 | occlusionStrength = FindProperty("_OcclusionStrength", props); 119 | occlusionMap = FindProperty("_OcclusionMap", props); 120 | emissionColorForRendering = FindProperty("_EmissionColor", props); 121 | emissionMap = FindProperty("_EmissionMap", props); 122 | detailMask = FindProperty("_DetailMask", props); 123 | detailAlbedoMap = FindProperty("_DetailAlbedoMap", props); 124 | detailNormalMapScale = FindProperty("_DetailNormalMapScale", props); 125 | detailNormalMap = FindProperty("_DetailNormalMap", props); 126 | uvSetSecondary = FindProperty("_UVSec", props); 127 | } 128 | 129 | public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) 130 | { 131 | FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly 132 | m_MaterialEditor = materialEditor; 133 | Material material = materialEditor.target as Material; 134 | 135 | // Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing 136 | // material to a standard shader. 137 | // Do this before any GUI code has been issued to prevent layout issues in subsequent GUILayout statements (case 780071) 138 | if (m_FirstTimeApply) 139 | { 140 | MaterialChanged(material, m_WorkflowMode); 141 | m_FirstTimeApply = false; 142 | } 143 | 144 | ShaderPropertiesGUI(material); 145 | } 146 | 147 | public void ShaderPropertiesGUI(Material material) 148 | { 149 | // Use default labelWidth 150 | EditorGUIUtility.labelWidth = 0f; 151 | 152 | // Detect any changes to the material 153 | EditorGUI.BeginChangeCheck(); 154 | { 155 | BlendModePopup(); 156 | 157 | // Primary properties 158 | GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel); 159 | DoAlbedoArea(material); 160 | DoSpecularMetallicArea(); 161 | DoNormalArea(); 162 | m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null); 163 | m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null); 164 | m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask); 165 | DoEmissionArea(material); 166 | EditorGUI.BeginChangeCheck(); 167 | m_MaterialEditor.TextureScaleOffsetProperty(albedoMap); 168 | if (EditorGUI.EndChangeCheck()) 169 | emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake 170 | 171 | EditorGUILayout.Space(); 172 | 173 | // Secondary properties 174 | GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel); 175 | m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap); 176 | m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale); 177 | m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap); 178 | m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text); 179 | 180 | // Third properties 181 | GUILayout.Label(Styles.forwardText, EditorStyles.boldLabel); 182 | if (highlights != null) 183 | m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText); 184 | if (reflections != null) 185 | m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText); 186 | } 187 | if (EditorGUI.EndChangeCheck()) 188 | { 189 | foreach (var obj in blendMode.targets) 190 | MaterialChanged((Material)obj, m_WorkflowMode); 191 | } 192 | 193 | EditorGUILayout.Space(); 194 | 195 | // NB renderqueue editor is not shown on purpose: we want to override it based on blend mode 196 | GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel); 197 | m_MaterialEditor.EnableInstancingField(); 198 | m_MaterialEditor.DoubleSidedGIField(); 199 | } 200 | 201 | internal void DetermineWorkflow(MaterialProperty[] props) 202 | { 203 | if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null) 204 | m_WorkflowMode = WorkflowMode.Specular; 205 | else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null) 206 | m_WorkflowMode = WorkflowMode.Metallic; 207 | else 208 | m_WorkflowMode = WorkflowMode.Dielectric; 209 | } 210 | 211 | public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) 212 | { 213 | // _Emission property is lost after assigning Standard shader to the material 214 | // thus transfer it before assigning the new shader 215 | if (material.HasProperty("_Emission")) 216 | { 217 | material.SetColor("_EmissionColor", material.GetColor("_Emission")); 218 | } 219 | 220 | base.AssignNewShaderToMaterial(material, oldShader, newShader); 221 | 222 | if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/")) 223 | { 224 | SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode")); 225 | return; 226 | } 227 | 228 | BlendMode blendMode = BlendMode.Opaque; 229 | if (oldShader.name.Contains("/Transparent/Cutout/")) 230 | { 231 | blendMode = BlendMode.Cutout; 232 | } 233 | else if (oldShader.name.Contains("/Transparent/")) 234 | { 235 | // NOTE: legacy shaders did not provide physically based transparency 236 | // therefore Fade mode 237 | blendMode = BlendMode.Fade; 238 | } 239 | material.SetFloat("_Mode", (float)blendMode); 240 | 241 | DetermineWorkflow(MaterialEditor.GetMaterialProperties(new Material[] { material })); 242 | MaterialChanged(material, m_WorkflowMode); 243 | } 244 | 245 | void BlendModePopup() 246 | { 247 | EditorGUI.showMixedValue = blendMode.hasMixedValue; 248 | var mode = (BlendMode)blendMode.floatValue; 249 | 250 | EditorGUI.BeginChangeCheck(); 251 | mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames); 252 | if (EditorGUI.EndChangeCheck()) 253 | { 254 | m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode"); 255 | blendMode.floatValue = (float)mode; 256 | } 257 | 258 | EditorGUI.showMixedValue = false; 259 | } 260 | 261 | void DoNormalArea() 262 | { 263 | m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null); 264 | /* 265 | // BuildTargetDiscovery is an inaccessible internal class. 266 | if (bumpScale.floatValue != 1 267 | && BuildTargetDiscovery.PlatformHasFlag(EditorUserBuildSettings.activeBuildTarget, TargetAttributes.HasIntegratedGPU) 268 | ) 269 | if (m_MaterialEditor.HelpBoxWithButton( 270 | EditorGUIUtility.TrTextContent("Bump scale is not supported on mobile platforms"), 271 | EditorGUIUtility.TrTextContent("Fix Now"))) 272 | { 273 | bumpScale.floatValue = 1; 274 | } 275 | */ 276 | } 277 | 278 | void DoAlbedoArea(Material material) 279 | { 280 | m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor); 281 | if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout)) 282 | { 283 | m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1); 284 | } 285 | } 286 | 287 | void DoEmissionArea(Material material) 288 | { 289 | // Emission for GI? 290 | if (m_MaterialEditor.EmissionEnabledProperty()) 291 | { 292 | bool hadEmissionTexture = emissionMap.textureValue != null; 293 | 294 | // Texture and HDR color controls 295 | m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, false); 296 | 297 | // If texture was assigned and color was black set color to white 298 | float brightness = emissionColorForRendering.colorValue.maxColorComponent; 299 | if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f) 300 | emissionColorForRendering.colorValue = Color.white; 301 | 302 | // change the GI flag and fix it up with emissive as black if necessary 303 | m_MaterialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true); 304 | } 305 | } 306 | 307 | void DoSpecularMetallicArea() 308 | { 309 | bool hasGlossMap = false; 310 | if (m_WorkflowMode == WorkflowMode.Specular) 311 | { 312 | hasGlossMap = specularMap.textureValue != null; 313 | m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap, hasGlossMap ? null : specularColor); 314 | } 315 | else if (m_WorkflowMode == WorkflowMode.Metallic) 316 | { 317 | hasGlossMap = metallicMap.textureValue != null; 318 | m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, hasGlossMap ? null : metallic); 319 | } 320 | 321 | bool showSmoothnessScale = hasGlossMap; 322 | if (smoothnessMapChannel != null) 323 | { 324 | int smoothnessChannel = (int)smoothnessMapChannel.floatValue; 325 | if (smoothnessChannel == (int)SmoothnessMapChannel.AlbedoAlpha) 326 | showSmoothnessScale = true; 327 | } 328 | 329 | int indentation = 2; // align with labels of texture properties 330 | m_MaterialEditor.ShaderProperty(showSmoothnessScale ? smoothnessScale : smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation); 331 | 332 | ++indentation; 333 | if (smoothnessMapChannel != null) 334 | m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText, indentation); 335 | } 336 | 337 | public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode) 338 | { 339 | switch (blendMode) 340 | { 341 | case BlendMode.Opaque: 342 | material.SetOverrideTag("RenderType", ""); 343 | material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); 344 | material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); 345 | material.SetInt("_ZWrite", 1); 346 | material.DisableKeyword("_ALPHATEST_ON"); 347 | material.DisableKeyword("_ALPHABLEND_ON"); 348 | material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); 349 | material.renderQueue = -1; 350 | break; 351 | case BlendMode.Cutout: 352 | material.SetOverrideTag("RenderType", "TransparentCutout"); 353 | material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); 354 | material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); 355 | material.SetInt("_ZWrite", 1); 356 | material.EnableKeyword("_ALPHATEST_ON"); 357 | material.DisableKeyword("_ALPHABLEND_ON"); 358 | material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); 359 | material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest; 360 | break; 361 | case BlendMode.Fade: 362 | material.SetOverrideTag("RenderType", "Transparent"); 363 | material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); 364 | material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); 365 | material.SetInt("_ZWrite", 0); 366 | material.DisableKeyword("_ALPHATEST_ON"); 367 | material.EnableKeyword("_ALPHABLEND_ON"); 368 | material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); 369 | material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; 370 | break; 371 | case BlendMode.Transparent: 372 | material.SetOverrideTag("RenderType", "Transparent"); 373 | material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); 374 | material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); 375 | material.SetInt("_ZWrite", 0); 376 | material.DisableKeyword("_ALPHATEST_ON"); 377 | material.DisableKeyword("_ALPHABLEND_ON"); 378 | material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); 379 | material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; 380 | break; 381 | } 382 | } 383 | 384 | static SmoothnessMapChannel GetSmoothnessMapChannel(Material material) 385 | { 386 | int ch = (int)material.GetFloat("_SmoothnessTextureChannel"); 387 | if (ch == (int)SmoothnessMapChannel.AlbedoAlpha) 388 | return SmoothnessMapChannel.AlbedoAlpha; 389 | else 390 | return SmoothnessMapChannel.SpecularMetallicAlpha; 391 | } 392 | 393 | static void SetMaterialKeywords(Material material, WorkflowMode workflowMode) 394 | { 395 | // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation 396 | // (MaterialProperty value might come from renderer material property block) 397 | SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap") || material.GetTexture("_DetailNormalMap")); 398 | if (workflowMode == WorkflowMode.Specular) 399 | SetKeyword(material, "_SPECGLOSSMAP", material.GetTexture("_SpecGlossMap")); 400 | else if (workflowMode == WorkflowMode.Metallic) 401 | SetKeyword(material, "_METALLICGLOSSMAP", material.GetTexture("_MetallicGlossMap")); 402 | SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap")); 403 | SetKeyword(material, "_DETAIL_MULX2", material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap")); 404 | 405 | // We need to know if an occlusion map is assigned or not. 406 | SetKeyword(material, "_HAS_OCCLUSION_MAP", material.GetTexture("_OcclusionMap")); 407 | 408 | // A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect 409 | // or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color. 410 | // The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color. 411 | MaterialEditor.FixupEmissiveFlag(material); 412 | bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0; 413 | SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled); 414 | 415 | if (material.HasProperty("_SmoothnessTextureChannel")) 416 | { 417 | SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha); 418 | } 419 | } 420 | 421 | static void MaterialChanged(Material material, WorkflowMode workflowMode) 422 | { 423 | SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode")); 424 | 425 | SetMaterialKeywords(material, workflowMode); 426 | } 427 | 428 | static void SetKeyword(Material m, string keyword, bool state) 429 | { 430 | if (state) 431 | m.EnableKeyword(keyword); 432 | else 433 | m.DisableKeyword(keyword); 434 | } 435 | } 436 | } // namespace UnityEditor 437 | -------------------------------------------------------------------------------- /Editor/MB_TexArrayStandardShaderGUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 02af6bf7ebcd4774093ec0b05fd85d80 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Unity Technologies 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /license.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e7ac26883a659fe4b95f9186497bf6b1 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------