Shader "Test/XTex" { Properties { [MainColor] _BaseColor("Color", Color) = (1,1,1,1) [MainTexture] _MainTex("Albedo", 2D) = "white" {} [Toggle(_MIXTEX_ON)] _UseMixTex("Use Mix Map", Float) = 0 [MixTexture] _MixTex("MixTex", 2D) = "white" {} _BumpScale("BumpScale", Range(0.0, 10)) = 5 _Roughness("Roughness", Range(0.0, 2.0)) = 0.4 _Metallic("Metallic", Range(0.0, 2.0)) = 0.3 _AO("AO", Range(0.0, 3.0)) = 1.0 _EmissiveIntensity("EmissiveIntensity", Range(0.0, 2.0)) = 0.3 } SubShader { // Universal Pipeline tag is required. If Universal render pipeline is not set in the graphics settings // this Subshader will fail. One can add a subshader below or fallback to Standard built-in to make this // material work with both Universal Render Pipeline and Builtin Unity Pipeline Tags{ "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "IgnoreProjector" = "True" } Pass { // Lightmode matches the ShaderPassName set in UniversalRenderPipeline.cs. SRPDefaultUnlit and passes with // no LightMode tag are also rendered by Universal Render Pipeline Name "ForwardLit" Tags{ "LightMode" = "UniversalForward" } ZWrite on HLSLPROGRAM // Required to compile gles 2.0 with standard SRP library // All shaders must be compiled with HLSLcc and currently only gles is not using HLSLcc by default #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma target 2.0 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile _ LIGHTMAP_ON #pragma multi_compile _ DYNAMICLIGHTMAP_ON #pragma multi_compile _ _MIXTEX_ON #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH #pragma vertex vert #pragma fragment frag #include "XTex_Base.hlsl" struct AttData { float3 normal; float ao;//获得夹角越狭窄越强 float roughness;//周围高度差越多,越粗糙;颜色越相同越低; float metallic;//使用平均亮度值 }; Varyings vert(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz); // normalWS and tangentWS already normalize. // this is required to avoid skewing the direction during interpolation // also required for per-vertex lighting and SH evaluation VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS); half3 vertexLight = VertexLighting(vertexInput.positionWS, normalInput.normalWS); half fogFactor = 0; #if !defined(_FOG_FRAGMENT) fogFactor = ComputeFogFactor(vertexInput.positionCS.z); #endif // already normalized from normal transform to WS. // half3 viewDirWS = GetWorldSpaceNormalizeViewDir(vertexInput.positionWS); // output.normalWS = half4(normalInput.normalWS, viewDirWS.x);//normalInput.normalWS;// //#if defined(REQUIRES_WORLD_SPACE_TANGENT_INTERPOLATOR) || defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR) // real sign = input.tangentOS.w * GetOddNegativeScale(); // half4 tangentWS = half4(normalInput.tangentWS.xyz, sign); //#endif //#if defined(REQUIRES_WORLD_SPACE_TANGENT_INTERPOLATOR) // output.tangentWS = tangentWS; //#endif half3 viewDirWS = GetCameraPositionWS() - vertexInput.positionWS; output.normalWS = half4(normalInput.normalWS, viewDirWS.x); output.tangentWS = half4(normalInput.tangentWS, viewDirWS.y); output.bitangentWS = half4(normalInput.bitangentWS, viewDirWS.z); #if defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR) half3 viewDirTS = GetViewDirectionTangentSpace(tangentWS, output.normalWS, viewDirWS); output.viewDirTS = viewDirTS; #endif OUTPUT_LIGHTMAP_UV(input.staticLightmapUV, unity_LightmapST, output.staticLightmapUV); #ifdef DYNAMICLIGHTMAP_ON output.dynamicLightmapUV = input.dynamicLightmapUV.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; #endif OUTPUT_SH(output.normalWS.xyz, output.vertexSH); #ifdef _ADDITIONAL_LIGHTS_VERTEX output.fogFactorAndVertexLight = half4(fogFactor, vertexLight); #else output.fogFactor = fogFactor; #endif output.positionWS = vertexInput.positionWS; #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) output.shadowCoord = GetShadowCoord(vertexInput); #endif output.positionCS = vertexInput.positionCS; output.uv = TRANSFORM_TEX(input.texcoord, _MainTex); return output; } //生成灰度图(高度) float GetGrayColor(half3 color) { //return color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722; //return color.r * 0.3 + color.g * 0.59 + color.b * 0.11; return 0.299f * color.r + 0.587f * color.g + 0.114f * color.b; } //生成法线 ao 粗糙度,金属度 AttData GetNormalByGray(float2 uv, half4 col4) { AttData ad; half bumpscale = _BumpScale * _MainTex_TexelSize.x; float2 deltaU = float2(_MainTex_TexelSize.x, 0); float h0 = GetGrayColor(col4.xyz); float h1_u = GetGrayColor(SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv - deltaU).rgb); float h2_u = GetGrayColor(SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + deltaU).rgb); //float3 tangent_u = float3(deltaU.x, 0, (h2_u - h0) * bumpscale); float3 tangent_u = float3(deltaU.x, 0, (h2_u - h1_u) * bumpscale); float2 deltaV = float2(0, _MainTex_TexelSize.y); float h1_v = GetGrayColor(SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv - deltaV).rgb); float h2_v = GetGrayColor(SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + deltaV).rgb); //float3 tangent_v = float3(0, deltaV.y, (h2_v - h0) * bumpscale); float3 tangent_v = float3(0, deltaV.y, (h2_v - h1_v) * bumpscale); //算ao. 两个向量夹角《 float ao;// = 0; //ad.ao = 0; ad.normal = normalize(cross(tangent_v, tangent_u)); ad.normal.z *= -1; float3 vVA = float3(0, deltaV.y, (h2_v - h0) * bumpscale); float3 vVB = float3(0, deltaV.y, (h1_v - h0) * bumpscale); float3 VecV = cross(vVA, vVB); //if (VecV.y > 0) {//锐角,判断根据锐角度得到夹角深度 ao = saturate(acos(dot(normalize(vVA), normalize(vVB)))); } float3 vUA = float3(deltaU.x, 0, (h2_u - h0) * bumpscale); float3 vUB = float3(deltaU.x, 0, (h1_u - h0) * bumpscale); float3 VecU = cross(vUA, vUB); //if (VecU.y > 0) {//锐角,判断根据锐角度得到夹角深度 ad.ao = saturate(acos(dot(normalize(vUA), normalize(vUB)))); } ad.ao = saturate(1.0f - max(ao, ad.ao) * _AO); // //粗糙度 ad.roughness = saturate((abs(h1_u - h0) + abs(h2_u - h0) + abs(h1_v - h0) + abs(h2_v - h0)) + _Roughness); //金属度 ad.metallic = saturate((h0 + h1_u + h2_u + h1_v + h2_v) / 5 * _Metallic); return ad; } half4 frag(Varyings input) : SV_Target { UNITY_SETUP_INSTANCE_ID(input); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); #if defined(_PARALLAXMAP) #if defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR) half3 viewDirTS = input.viewDirTS; #else half3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS); half3 viewDirTS = GetViewDirectionTangentSpace(input.tangentWS, input.normalWS, viewDirWS); #endif ApplyPerPixelDisplacement(viewDirTS, input.uv); #endif SurfaceData surfaceData; //InitializeStandardLitSurfaceData(input.uv, surfaceData); half4 albedoAlpha = SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_MainTex, sampler_MainTex)); half3 albedo = albedoAlpha.rgb * _BaseColor.rgb; //Light mainLight = GetMainLight(); #ifdef _MIXTEX_ON half4 mixTex = SAMPLE_TEXTURE2D(_MixTex, sampler_MixTex, input.uv); AttData ad;// = GetNormalByGray(input.uv, albedoAlpha);; ad.normal.rgb = DecodeSphereMap(mixTex.rg); ad.ao = saturate(1.0 - (1.0 - mixTex.a) * _AO); ad.roughness = mixTex.a * _Roughness; ad.metallic = mixTex.b * _Metallic; #else //得到法线 AttData ad = GetNormalByGray(input.uv, albedoAlpha); //half gray = GetGrayColor(albedoAlpha.xyz); //ad.normal.rgb = half3(gray,gray,gray); #endif //half3 viewDirWS = half3(input.normalWS.w, input.tangentWS.w, input.bitangentWS.w); half3 normalWS = TransformTangentToWorld(ad.normal, half3x3(input.tangentWS.xyz, input.bitangentWS.xyz, input.normalWS.xyz)); surfaceData.specular = half3(0.0, 0.0, 0.0); surfaceData.albedo = albedo; surfaceData.metallic = ad.metallic; surfaceData.smoothness = 1.0 - ad.roughness; // 新版URP中smoothness直接控制高光 surfaceData.alpha = albedoAlpha.a; surfaceData.normalTS = ad.normal;//input.tangentWS;// //surfaceData.specular = 0; surfaceData.emission = half3(0.0, 0.0, 0.0); surfaceData.occlusion = ad.ao; surfaceData.clearCoatMask = half(0.0); surfaceData.clearCoatSmoothness = half(0.0); InputData inputData; input.normalWS.rgb = normalWS;//ad.normal;//法线需要传入 InitializeInputData(input, surfaceData.normalTS, inputData); //SETUP_DEBUG_TEXTURE_DATA(inputData, input.uv, _BaseMap); //#ifdef _DBUFFER // ApplyDecalToSurfaceData(input.positionCS, surfaceData, inputData); //#endif half4 color = UniversalFragmentPBR(inputData, surfaceData); color.rgb = MixFog(color.rgb, inputData.fogCoord); //color.a = OutputAlpha(color.a, _Surface); //color.rgb = input.tangentWS;//normalWS;//surfaceData.normalTS;// return color; } ENDHLSL } Pass { Name "ShadowCaster" Tags{ "LightMode" = "ShadowCaster" } ZWrite On ZTest LEqual Cull[_Cull] HLSLPROGRAM // Required to compile gles 2.0 with standard srp library #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma target 2.0 // ------------------------------------- // Material Keywords #pragma shader_feature_local_fragment _ALPHATEST_ON //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma vertex vert #pragma fragment frag #include "XTex_Base.hlsl" Varyings vert(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); float3 positionWS = TransformObjectToWorld(input.positionOS.xyz); float3 normalWS = TransformObjectToWorldNormal(input.normalOS); float4 positionCS = TransformWorldToHClip(positionWS); #if UNITY_REVERSED_Z positionCS.z = min(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE); #else positionCS.z = max(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE); #endif output.positionCS = positionCS; output.uv = TRANSFORM_TEX(input.texcoord, _MainTex); return output; } half4 frag(Varyings input) : SV_TARGET { return SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a; //return 0; } ENDHLSL } //UsePass "Universal Render Pipeline/Lit/ShadowCaster" } FallBack Off }