Écriture de shaders avec du code dans Unity LWRP

Présentation


Bonjour, Habr. Aujourd'hui, je veux parler un peu de la façon dont vous pouvez commencer rapidement et sans douleur (presque) à écrire des ombrages de texte classiques dans Unity en utilisant le pipeline de rendu léger (LWRP) - l'un des exemples du pipeline Scriptable Rendering Pipeline (SRP) .

Mais qu'en est-il du graphique Shader?


Shader Graph est un outil pratique et rapide pour le prototypage ou l'écriture d'effets simples. Cependant, parfois, il est nécessaire d'écrire quelque chose de compliqué et complexe, puis - le nombre de nœuds, de fonctions personnalisées, de sous-graphiques augmente incroyablement, c'est pourquoi même le programmeur graphique le plus expérimenté commence à se perdre dans tout ce bordel. Nous comprenons tous que le code généré automatiquement a priori ne peut pas être meilleur qu'écrit manuellement - vous n'avez pas besoin d'aller loin pour des exemples, car toute erreur dans la disposition des nœuds peut conduire au fait que le résultat de calcul déjà connu dans le vertex shader sera compté à plusieurs reprises dans le fragment. Il y a des gens qui sont tout simplement plus à l'aise avec le code qu'avec les nœuds. Les raisons peuvent être différentes, mais l'essence est la même - avec les nœuds, vive le code!

2020-01-19-17-07-35

Problème


Alors, quel est le problème de s'asseoir et d'écrire un shader de texte normal sous LWRP? Et le problème est que les Shaders de surface standard préférés de tout le monde ne sont pas pris en charge dans LWRP.
Lorsque vous essayez de l'utiliser, nous obtenons ce qui suit:

2020-01-19-17-16-16

Code de shader
Shader "Custom/NewSurfaceShader" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; fixed4 _Color; // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader. // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing. // #pragma instancing_options assumeuniformscaling UNITY_INSTANCING_BUFFER_START(Props) // put more per-instance properties here UNITY_INSTANCING_BUFFER_END(Props) void surf (Input IN, inout SurfaceOutputStandard o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // Metallic and smoothness come from slider variables o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = ca; } ENDCG } FallBack "Diffuse" } 


Ensuite, il vient à l'esprit pour essayer d'écrire un shader anlite régulier avec une partie vertex et fragment. Et heureusement, tout fonctionne:

2020-01-19-17-22-46

Code de shader
 Shader "Unlit/NewUnlitShader" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } } 


Cependant, comment pouvez-vous ne pas être triste - nous semblions être laissés nus sur la touche sans lumière, ombres, cartes lumineuses et PBR bien-aimé, sans lesquels la vie n'était pas douce.
Bien sûr, vous pouvez tout écrire à la main:
Que la lumière soit!

2020-01-19-17-55-56

Code de shader
 Shader "TheProxor/Simple Lit" { Properties { _MainTex("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType" = "Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" #include "UnityLightingCommon.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal : NORMAL; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; fixed4 diffuse : COLOR0; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); half3 worldNormal = UnityObjectToWorldNormal(v.normal); half nl = max(0, dot(worldNormal, _WorldSpaceLightPos0.xyz)); o.diffuse = nl * _LightColor0; return o; } fixed4 frag(v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); col *= i.diffuse; return col; } ENDCG } } } 


Tout semble fonctionner, mais ce n'est qu'un éclairage diffus. Que faire ensuite? Vous pouvez continuer à tout renvoyer à la main, mais c'est long et morne, et PBR ne peut en aucun cas être retourné, et nous perdons toutes les puces LWRP. Par conséquent, nous n'avons pas d'autre choix que de choisir LWRP afin de tout retourner d'un seul coup magique.

Solution


Donc, comme vous le savez, LWRP est construit sur la base du moteur de rendu direct , ce qui signifie qu'il a son propre LitForwardPass, qui devrait être décrit quelque part. De toute évidence, quelque part il y a un CGInclude dans lequel tout cela est décrit. C'est là que nous avons commencé une aventure amusante à:
% localappdata% \ Unity \ cache \ packages \ packages.unity.com \ com.unity.render-pipelines.lightweight @ (version LWRP) \

En fait, étant arrivé à l'adresse spécifiée et entré dans le dossier Shaders , nous pouvons trouver un shader intéressant appelé Lit.shader . En fait, nous pouvons dire que notre recherche est terminée, le voici - le shader convoité. Entrer à l'intérieur - nous trouvons le contenu suivant:

Lit.shader
 Shader "Lightweight Render Pipeline/Lit" { Properties { // Specular vs Metallic workflow [HideInInspector] _WorkflowMode("WorkflowMode", Float) = 1.0 [MainColor] _BaseColor("Color", Color) = (0.5,0.5,0.5,1) [MainTexture] _BaseMap("Albedo", 2D) = "white" {} _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 _Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5 _GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0 _SmoothnessTextureChannel("Smoothness texture channel", Float) = 0 [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0 _MetallicGlossMap("Metallic", 2D) = "white" {} _SpecColor("Specular", Color) = (0.2, 0.2, 0.2) _SpecGlossMap("Specular", 2D) = "white" {} [ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 [ToggleOff] _EnvironmentReflections("Environment Reflections", Float) = 1.0 _BumpScale("Scale", Float) = 1.0 _BumpMap("Normal Map", 2D) = "bump" {} _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0 _OcclusionMap("Occlusion", 2D) = "white" {} _EmissionColor("Color", Color) = (0,0,0) _EmissionMap("Emission", 2D) = "white" {} // Blending state [HideInInspector] _Surface("__surface", Float) = 0.0 [HideInInspector] _Blend("__blend", Float) = 0.0 [HideInInspector] _AlphaClip("__clip", Float) = 0.0 [HideInInspector] _SrcBlend("__src", Float) = 1.0 [HideInInspector] _DstBlend("__dst", Float) = 0.0 [HideInInspector] _ZWrite("__zw", Float) = 1.0 [HideInInspector] _Cull("__cull", Float) = 2.0 _ReceiveShadows("Receive Shadows", Float) = 1.0 // Editmode props [HideInInspector] _QueueOffset("Queue offset", Float) = 0.0 // ObsoleteProperties [HideInInspector] _MainTex("BaseMap", 2D) = "white" {} [HideInInspector] _Color("Base Color", Color) = (0.5, 0.5, 0.5, 1) [HideInInspector] _GlossMapScale("Smoothness", Float) = 0.0 [HideInInspector] _Glossiness("Smoothness", Float) = 0.0 [HideInInspector] _GlossyReflections("EnvironmentReflections", Float) = 0.0 } SubShader { // Lightweight Pipeline tag is required. If Lightweight 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 Lightweight Render Pipeline and Builtin Unity Pipeline Tags{"RenderType" = "Opaque" "RenderPipeline" = "LightweightPipeline" "IgnoreProjector" = "True"} LOD 300 // ------------------------------------------------------------------ // Forward pass. Shades all light in a single pass. GI + emission + Fog Pass { // Lightmode matches the ShaderPassName set in LightweightRenderPipeline.cs. SRPDefaultUnlit and passes with // no LightMode tag are also rendered by Lightweight Render Pipeline Name "ForwardLit" Tags{"LightMode" = "LightweightForward"} Blend[_SrcBlend][_DstBlend] ZWrite[_ZWrite] Cull[_Cull] 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 // ------------------------------------- // Material Keywords #pragma shader_feature _NORMALMAP #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _ALPHAPREMULTIPLY_ON #pragma shader_feature _EMISSION #pragma shader_feature _METALLICSPECGLOSSMAP #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _OCCLUSIONMAP #pragma shader_feature _SPECULARHIGHLIGHTS_OFF #pragma shader_feature _ENVIRONMENTREFLECTIONS_OFF #pragma shader_feature _SPECULAR_SETUP #pragma shader_feature _RECEIVE_SHADOWS_OFF // ------------------------------------- // Lightweight Pipeline keywords #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile _ _SHADOWS_SOFT #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE // ------------------------------------- // Unity defined keywords #pragma multi_compile _ DIRLIGHTMAP_COMBINED #pragma multi_compile _ LIGHTMAP_ON #pragma multi_compile_fog //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma vertex LitPassVertex #pragma fragment LitPassFragment #include "LitInput.hlsl" #include "LitForwardPass.hlsl" 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 _ALPHATEST_ON //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma vertex ShadowPassVertex #pragma fragment ShadowPassFragment #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/Shaders/ShadowCasterPass.hlsl" ENDHLSL } Pass { Name "DepthOnly" Tags{"LightMode" = "DepthOnly"} ZWrite On ColorMask 0 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 #pragma vertex DepthOnlyVertex #pragma fragment DepthOnlyFragment // ------------------------------------- // Material Keywords #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/Shaders/DepthOnlyPass.hlsl" ENDHLSL } // This pass it not used during regular rendering, only for lightmap baking. Pass { Name "Meta" Tags{"LightMode" = "Meta"} Cull Off HLSLPROGRAM // Required to compile gles 2.0 with standard srp library #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma vertex LightweightVertexMeta #pragma fragment LightweightFragmentMeta #pragma shader_feature _SPECULAR_SETUP #pragma shader_feature _EMISSION #pragma shader_feature _METALLICSPECGLOSSMAP #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _SPECGLOSSMAP #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitMetaPass.hlsl" ENDHLSL } Pass { Name "Lightweight2D" Tags{ "LightMode" = "Lightweight2D" } Blend[_SrcBlend][_DstBlend] ZWrite[_ZWrite] Cull[_Cull] HLSLPROGRAM // Required to compile gles 2.0 with standard srp library #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma vertex vert #pragma fragment frag #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _ALPHAPREMULTIPLY_ON #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/Shaders/Utils/Lightweight2D.hlsl" ENDHLSL } } FallBack "Hidden/InternalErrorShader" CustomEditor "UnityEditor.Rendering.LWRP.ShaderGUI.LitShader" } 



Il ne reste plus qu'à l'étendre pour faciliter l'édition, en supprimant les inclusions. Eh bien, modifiez un peu à votre façon.

Nous obtenons quelque chose comme ça:

2020-01-19-18-28-13

Ombrage final
 Shader "TheProxor/LWRP/Dissolve + Vertex Offset" { Properties { // Specular vs Metallic workflow [HideInInspector] _WorkflowMode("WorkflowMode", Float) = 1.0 [MainColor][HideInInspector] _BaseColor("Color", Color) = (0.5,0.5,0.5,1) [MainTexture][HideInInspector] _BaseMap("Albedo", 2D) = "white" {} [HideInInspector]_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 [HideInInspector]_Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5 [HideInInspector]_GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0 [HideInInspector]_SmoothnessTextureChannel("Smoothness texture channel", Float) = 0 [Gamma][HideInInspector] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0 [HideInInspector]_MetallicGlossMap("Metallic", 2D) = "white" {} [HideInInspector]_SpecColor("Specular", Color) = (0.2, 0.2, 0.2) [HideInInspector]_SpecGlossMap("Specular", 2D) = "white" {} [HideInInspector][ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 [HideInInspector][ToggleOff] _EnvironmentReflections("Environment Reflections", Float) = 1.0 [HideInInspector]_BumpScale("Scale", Float) = 1.0 [HideInInspector]_BumpMap("Normal Map", 2D) = "bump" {} [HideInInspector]_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0 [HideInInspector]_OcclusionMap("Occlusion", 2D) = "white" {} [HDR][HideInInspector]_EmissionColor("Color", Color) = (0,0,0) [HideInInspector]_EmissionMap("Emission", 2D) = "white" {} // Blending state [HideInInspector] _Surface("__surface", Float) = 0.0 [HideInInspector] _Blend("__blend", Float) = 0.0 [HideInInspector] _AlphaClip("__clip", Float) = 0.0 [HideInInspector] _SrcBlend("__src", Float) = 1.0 [HideInInspector] _DstBlend("__dst", Float) = 0.0 [HideInInspector] _ZWrite("__zw", Float) = 1.0 [HideInInspector] _Cull("__cull", Float) = 2.0 [HideInInspector]_ReceiveShadows("Receive Shadows", Float) = 1.0 // Editmode props [HideInInspector] _QueueOffset("Queue offset", Float) = 0.0 // ObsoleteProperties [HideInInspector] _MainTex("BaseMap", 2D) = "white" {} [HideInInspector] _Color("Base Color", Color) = (0.5, 0.5, 0.5, 1) [HideInInspector] _GlossMapScale("Smoothness", Float) = 0.0 [HideInInspector] _Glossiness("Smoothness", Float) = 0.0 [HideInInspector] _GlossyReflections("EnvironmentReflections", Float) = 0.0 //    _DissolveMap("Dissolve Map", 2D) = "white" {} _DissolveFactor("Dissolve Factor", Range(0, 1)) = 0.0 _DissolveWidth("Dissolve Width", Range(0, 1)) = 0.0 [HDR]_DissolveColor("Color", Color) = (1,1,0) } SubShader { // Lightweight Pipeline tag is required. If Lightweight 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 Lightweight Render Pipeline and Builtin Unity Pipeline Tags{"RenderType" = "Opaque" "RenderPipeline" = "LightweightPipeline" "IgnoreProjector" = "True"} LOD 300 // ------------------------------------------------------------------ // Forward pass. Shades all light in a single pass. GI + emission + Fog Pass { // Lightmode matches the ShaderPassName set in LightweightRenderPipeline.cs. SRPDefaultUnlit and passes with // no LightMode tag are also rendered by Lightweight Render Pipeline Name "ForwardLit" Tags{"LightMode" = "LightweightForward"} Blend[_SrcBlend][_DstBlend] ZWrite[_ZWrite] Cull[_Cull] 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 // ------------------------------------- // Material Keywords #pragma shader_feature _NORMALMAP #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _ALPHAPREMULTIPLY_ON #pragma shader_feature _EMISSION #pragma shader_feature _METALLICSPECGLOSSMAP #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _OCCLUSIONMAP #pragma shader_feature _SPECULARHIGHLIGHTS_OFF #pragma shader_feature _ENVIRONMENTREFLECTIONS_OFF #pragma shader_feature _SPECULAR_SETUP #pragma shader_feature _RECEIVE_SHADOWS_OFF // ------------------------------------- // Lightweight Pipeline keywords #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile _ _SHADOWS_SOFT #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE // ------------------------------------- // Unity defined keywords #pragma multi_compile _ DIRLIGHTMAP_COMBINED #pragma multi_compile _ LIGHTMAP_ON #pragma multi_compile_fog //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma vertex LitPassVertex #pragma fragment LitPassFragment #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Lighting.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/SurfaceInput.hlsl" #ifdef _SPECULAR_SETUP #define SAMPLE_METALLICSPECULAR(uv) SAMPLE_TEXTURE2D(_SpecGlossMap, sampler_SpecGlossMap, uv) #else #define SAMPLE_METALLICSPECULAR(uv) SAMPLE_TEXTURE2D(_MetallicGlossMap, sampler_MetallicGlossMap, uv) #endif struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; float4 tangentOS : TANGENT; float2 texcoord : TEXCOORD0; float2 lightmapUV : TEXCOORD1; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float2 uv : TEXCOORD0; DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 1); #ifdef _ADDITIONAL_LIGHTS float3 positionWS : TEXCOORD2; #endif #ifdef _NORMALMAP half4 normalWS : TEXCOORD3; // xyz: normal, w: viewDir.x half4 tangentWS : TEXCOORD4; // xyz: tangent, w: viewDir.y half4 bitangentWS : TEXCOORD5; // xyz: bitangent, w: viewDir.z #else half3 normalWS : TEXCOORD3; half3 viewDirWS : TEXCOORD4; #endif half4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light #ifdef _MAIN_LIGHT_SHADOWS float4 shadowCoord : TEXCOORD7; #endif float4 positionCS : SV_POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO float3 uvDissolve : TEXCOORD8; }; CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; half4 _BaseColor; half4 _SpecColor; half4 _EmissionColor; half _Cutoff; half _Smoothness; half _Metallic; half _BumpScale; half _OcclusionStrength; float4 _DissolveMap_ST; //    _DissolveMap float _DissolveFactor; float _DissolveWidth; float4 _DissolveColor; CBUFFER_END TEXTURE2D(_OcclusionMap); SAMPLER(sampler_OcclusionMap); TEXTURE2D(_MetallicGlossMap); SAMPLER(sampler_MetallicGlossMap); TEXTURE2D(_SpecGlossMap); SAMPLER(sampler_SpecGlossMap); TEXTURE2D(_DissolveMap); SAMPLER(sampler_DissolveMap); half4 SampleMetallicSpecGloss(float2 uv, half albedoAlpha) { half4 specGloss; #ifdef _METALLICSPECGLOSSMAP specGloss = SAMPLE_METALLICSPECULAR(uv); #ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A specGloss.a = albedoAlpha * _Smoothness; #else specGloss.a *= _Smoothness; #endif #else // _METALLICSPECGLOSSMAP #if _SPECULAR_SETUP specGloss.rgb = _SpecColor.rgb; #else specGloss.rgb = _Metallic.rrr; #endif #ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A specGloss.a = albedoAlpha * _Smoothness; #else specGloss.a = _Smoothness; #endif #endif return specGloss; } half SampleOcclusion(float2 uv) { #ifdef _OCCLUSIONMAP // TODO: Controls things like these by exposing SHADER_QUALITY levels (low, medium, high) #if defined(SHADER_API_GLES) return SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, uv).g; #else half occ = SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, uv).g; return LerpWhiteTo(occ, _OcclusionStrength); #endif #else return 1.0; #endif } inline void InitializeStandardLitSurfaceData(float2 uv, out SurfaceData outSurfaceData) { half4 albedoAlpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv); // half4 albedoAlpha = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)); outSurfaceData.alpha = Alpha(albedoAlpha.a, _BaseColor, _Cutoff); half4 specGloss = SampleMetallicSpecGloss(uv, albedoAlpha.a); outSurfaceData.albedo = albedoAlpha.rgb * _BaseColor.rgb; #if _SPECULAR_SETUP outSurfaceData.metallic = 1.0h; outSurfaceData.specular = specGloss.rgb; #else outSurfaceData.metallic = specGloss.r; outSurfaceData.specular = half3(0.0h, 0.0h, 0.0h); #endif outSurfaceData.smoothness = specGloss.a; outSurfaceData.normalTS = SampleNormal(uv, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap), _BumpScale); outSurfaceData.occlusion = SampleOcclusion(uv); outSurfaceData.emission = SampleEmission(uv, _EmissionColor.rgb, TEXTURE2D_ARGS(_EmissionMap, sampler_EmissionMap)); // outSurfaceData.emission = _EmissionColor.rgb * SAMPLE_TEXTURE2D(_EmissionMap, sampler_EmissionMap, uv); } void InitializeInputData(Varyings input, half3 normalTS, out InputData inputData) { inputData = (InputData)0; #ifdef _ADDITIONAL_LIGHTS inputData.positionWS = input.positionWS; #endif #ifdef _NORMALMAP half3 viewDirWS = half3(input.normalWS.w, input.tangentWS.w, input.bitangentWS.w); inputData.normalWS = TransformTangentToWorld(normalTS, half3x3(input.tangentWS.xyz, input.bitangentWS.xyz, input.normalWS.xyz)); #else half3 viewDirWS = input.viewDirWS; inputData.normalWS = input.normalWS; #endif inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS); viewDirWS = SafeNormalize(viewDirWS); inputData.viewDirectionWS = viewDirWS; #if defined(_MAIN_LIGHT_SHADOWS) && !defined(_RECEIVE_SHADOWS_OFF) inputData.shadowCoord = input.shadowCoord; #else inputData.shadowCoord = float4(0, 0, 0, 0); #endif inputData.fogCoord = input.fogFactorAndVertexLight.x; inputData.vertexLighting = input.fogFactorAndVertexLight.yzw; inputData.bakedGI = SAMPLE_GI(input.lightmapUV, input.vertexSH, inputData.normalWS); } /////////////////////////////////////////////////////////////////////////////// // Vertex and Fragment functions // /////////////////////////////////////////////////////////////////////////////// //Standard (Physically Based) shader Varyings LitPassVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); input.positionOS.xyz += normalize(input.positionOS.xyz) * sin(input.positionOS.x) * sin(_Time.x * 100); VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz); VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS); half3 viewDirWS = GetCameraPositionWS() - vertexInput.positionWS; half3 vertexLight = VertexLighting(vertexInput.positionWS, normalInput.normalWS); half fogFactor = ComputeFogFactor(vertexInput.positionCS.z); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); #ifdef _NORMALMAP output.normalWS = half4(normalInput.normalWS, viewDirWS.x); output.tangentWS = half4(normalInput.tangentWS, viewDirWS.y); output.bitangentWS = half4(normalInput.bitangentWS, viewDirWS.z); #else output.normalWS = NormalizeNormalPerVertex(normalInput.normalWS); output.viewDirWS = viewDirWS; #endif OUTPUT_LIGHTMAP_UV(input.lightmapUV, unity_LightmapST, output.lightmapUV); OUTPUT_SH(output.normalWS.xyz, output.vertexSH); output.fogFactorAndVertexLight = half4(fogFactor, vertexLight); #ifdef _ADDITIONAL_LIGHTS output.positionWS = vertexInput.positionWS; #endif #if defined(_MAIN_LIGHT_SHADOWS) && !defined(_RECEIVE_SHADOWS_OFF) output.shadowCoord = GetShadowCoord(vertexInput); #endif output.positionCS = vertexInput.positionCS; return output; } // Used in Standard (Physically Based) shader half4 LitPassFragment(Varyings input) : SV_Target { input.uv += _Time.x * 10; UNITY_SETUP_INSTANCE_ID(input); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); SurfaceData surfaceData; InitializeStandardLitSurfaceData(input.uv, surfaceData); InputData inputData; InitializeInputData(input, surfaceData.normalTS, inputData); float4 mask = SAMPLE_TEXTURE2D(_DissolveMap, sampler_DissolveMap, input.uv); if (mask.r > _DissolveFactor) discard; bool outline = mask.r > _DissolveFactor - _DissolveWidth; surfaceData.emission *= outline * _DissolveColor; half4 color = LightweightFragmentPBR(inputData, surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.occlusion, surfaceData.emission, surfaceData.alpha); color *= lerp(1, _DissolveColor, outline); color.rgb = MixFog(color.rgb, inputData.fogCoord); 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 _ALPHATEST_ON //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma vertex ShadowPassVertex #pragma fragment ShadowPassFragment #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Shadows.hlsl" float3 _LightDirection; struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; float2 texcoord : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float2 uv : TEXCOORD0; float4 positionCS : SV_POSITION; }; CBUFFER_START(UnityPerMaterial) float4 _DissolveMap_ST; //    _DissolveMap float _DissolveFactor; CBUFFER_END TEXTURE2D(_DissolveMap); SAMPLER(sampler_DissolveMap); float4 GetShadowPositionHClip(Attributes input) { float3 positionWS = TransformObjectToWorld(input.positionOS.xyz); float3 normalWS = TransformObjectToWorldNormal(input.normalOS); float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection)); #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 return positionCS; } Varyings ShadowPassVertex(Attributes input) { Varyings output; input.positionOS.xyz += normalize(input.positionOS.xyz) * sin(input.positionOS.x) * sin(_Time.x * 100); UNITY_SETUP_INSTANCE_ID(input); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); output.positionCS = GetShadowPositionHClip(input); return output; } half4 ShadowPassFragment(Varyings input) : SV_TARGET { float4 mask = SAMPLE_TEXTURE2D(_DissolveMap, sampler_DissolveMap, input.uv); if (mask.r > _DissolveFactor) discard; Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff); return 0; } ENDHLSL } Pass { Name "DepthOnly" Tags{"LightMode" = "DepthOnly"} ZWrite On ColorMask 0 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 #pragma vertex DepthOnlyVertex #pragma fragment DepthOnlyFragment // ------------------------------------- // Material Keywords #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl" #ifndef LIGHTWEIGHT_DEPTH_ONLY_PASS_INCLUDED #define LIGHTWEIGHT_DEPTH_ONLY_PASS_INCLUDED struct Attributes { float4 position : POSITION; float2 texcoord : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float2 uv : TEXCOORD0; float4 positionCS : SV_POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO }; Varyings DepthOnlyVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); input.position.xyz += normalize(input.position.xyz) * sin(input.position.x) * sin(_Time.x * 100); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); output.positionCS = TransformObjectToHClip(input.position.xyz); return output; } half4 DepthOnlyFragment(Varyings input) : SV_TARGET { UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff); return 0; } #endif ENDHLSL } // Pass { Name "Meta" Tags{"LightMode" = "Meta"} Cull Off HLSLPROGRAM // Required to compile gles 2.0 with standard srp library #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma vertex LightweightVertexMeta #pragma fragment LightweightFragmentMeta #pragma shader_feature _SPECULAR_SETUP #pragma shader_feature _EMISSION #pragma shader_feature _METALLICSPECGLOSSMAP #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _SPECGLOSSMAP #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/MetaInput.hlsl" #ifndef LIGHTWEIGHT_LIT_META_PASS_INCLUDED #define LIGHTWEIGHT_LIT_META_PASS_INCLUDED Varyings LightweightVertexMeta(Attributes input) { Varyings output; output.positionCS = MetaVertexPosition(input.positionOS, input.uv1, input.uv2, unity_LightmapST, unity_DynamicLightmapST); output.uv = TRANSFORM_TEX(input.uv0, _BaseMap); return output; } half4 LightweightFragmentMeta(Varyings input) : SV_Target { SurfaceData surfaceData; InitializeStandardLitSurfaceData(input.uv, surfaceData); BRDFData brdfData; InitializeBRDFData(surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.alpha, brdfData); MetaInput metaInput; metaInput.Albedo = brdfData.diffuse + brdfData.specular * brdfData.roughness * 0.5; metaInput.SpecularColor = surfaceData.specular; metaInput.Emission = surfaceData.emission; return MetaFragment(metaInput); } #endif ENDHLSL } Pass { Name "Lightweight2D" Tags{ "LightMode" = "Lightweight2D" } Blend[_SrcBlend][_DstBlend] ZWrite[_ZWrite] Cull[_Cull] HLSLPROGRAM // Required to compile gles 2.0 with standard srp library #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma vertex vert #pragma fragment frag #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _ALPHAPREMULTIPLY_ON #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/Shaders/Utils/Lightweight2D.hlsl" ENDHLSL } } FallBack "Hidden/InternalErrorShader" CustomEditor "UnityEditor.Rendering.LWRP.ShaderGUI.LitShaderEditor" } 


Tout d'abord, vous devez savoir ce que contient le shader résultant. Tout d'abord, nous nous intéressons à la ligne:

 CustomEditor "UnityEditor.Rendering.LWRP.ShaderGUI.LitShaderEditor" 

Ce qui, comme nous nous en souvenons, dans l'original était le suivant:

 CustomEditor "UnityEditor.Rendering.LWRP.ShaderGUI.LitShader" 

Alors qu'est-ce que c'est et pourquoi est-ce? La réponse à cette question est assez simple - si vous regardez de près, le shader a un grand nombre de types différents de définitions, qui, curieusement, doivent être activées et désactivées, et cela, pour un moment, doit être fait à partir du code, c'est pourquoi nous avons besoin d'un inspecteur personnalisé. De plus, notre inspecteur personnalisé devrait nous donner la possibilité de modifier non seulement les propriétés intégrées, mais aussi celles dont nous pourrions avoir besoin dans nos shaders. Le shader d'origine a déjà un inspecteur personnalisé, donc nous le piétinons sûrement en le recherchant le long du chemin suivant:
% localappdata% \ Unity \ cache \ packages \ packages.unity.com \ com.unity.render-pipelines.lightweight@6.9.2 \ Editor \ ShaderGUI \ Shaders \
En fait, nous sommes intéressés par le fichier LitShader.cs, qui est hérité de BaseShaderGUI:

 internal class LitShader : BaseShaderGUI { ... } 

Le lot principal se déroule exactement dans BaseShaderGUI.cs, qui se trouve dans le dossier un niveau plus haut:

 public abstract class BaseShaderGUI : ShaderGUI { ... } 

Nous prenons ces scripts et les jetons dans le dossier Editor (s'il n'y en a pas, créez-les, sinon des erreurs apparaîtront naturellement lors de la construction du projet, car l'espace de noms UnityEditor n'est pas inclus dans la construction). Bien sûr, sur notre tête tombe mille et une erreur, qui sont associés à type internel SavedBool , qui est un éditeur de variable bool type de fenêtre sérialisé. Ceci est fait pour maintenir l'état des sections de pliage du matériau. En fait, pour la correction, nous effectuons une manipulation simple.

Changement:

 SavedBool m_SurfaceOptionsFoldout; SavedBool m_SurfaceInputsFoldout; SavedBool m_AdvancedFoldout; 

Le:

 AnimatedValues.AnimBool m_SurfaceOptionsFoldout; AnimatedValues.AnimBool m_SurfaceInputsFoldout; AnimatedValues.AnimBool m_AdvancedFoldout; 

Et ajoutez une autre variable pour des propriétés personnalisées supplémentaires:

 AnimatedValues.AnimBool m_OtherFoldout; 

Vous devez également ajouter le nom et la description de la section avec nos paramètres personnalisés, en respectant les traditions établies à l'intérieur du script:

 protected class Styles { // Catergories ... public static readonly GUIContent OtherOptions = new GUIContent("Your own options", "You own custom options"); } 

Eh bien, maintenant, faisons un petit tour. Comme vous pouvez le voir, pour toutes les propriétés standard, j'ai défini l'attribut HideInInspector , qui indique directement que cette propriété sera masquée dans l'inspecteur. Cependant, cela ne concerne que l'inspecteur standard des matériaux, mais lequel? C'est vrai, personnalisé! Cela signifie que toutes nos propriétés intégrées sont rendues de quelque manière que ce soit. Alors cachons-les:

 ... [MainColor][HideInInspector] _BaseColor("Color", Color) = (0.5,0.5,0.5,1) [MainTexture][HideInInspector] _BaseMap("Albedo", 2D) = "white" {} [HideInInspector]_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 [HideInInspector]_Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5 [HideInInspector]_GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0 [HideInInspector]_SmoothnessTextureChannel("Smoothness texture channel", Float) = 0 ... 

Et à l'intérieur du code de l'éditeur personnalisé, nous appelons simplement le rendu de l'inspecteur standard:

 public override void OnGUI(...) { ... m_OtherFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_OtherFoldout.value, Styles.OtherOptions); if (m_OtherFoldout.value) { base.OnGUI(materialEditorIn, properties); EditorGUILayout.Space(); } EditorGUILayout.EndFoldoutHeaderGroup(); ... } 

Le résultat est évident: et voici le code des deux scripts:

2020-01-19-22-58-23



BaseShaderEditor.cs
 using System; using UnityEngine; using UnityEngine.Rendering; using UnityEditor.Rendering; namespace UnityEditor { public abstract class BaseShaderEditor : ShaderGUI { #region EnumsAndClasses public enum SurfaceType { Opaque, Transparent } public enum BlendMode { Alpha, // Old school alpha-blending mode, fresnel does not affect amount of transparency Premultiply, // Physically plausible transparency mode, implemented as alpha pre-multiply Additive, Multiply } public enum SmoothnessSource { BaseAlpha, SpecularAlpha } public enum RenderFace { Front = 2, Back = 1, Both = 0 } protected class Styles { // Catergories public static readonly GUIContent SurfaceOptions = new GUIContent("Surface Options", "Controls how LWRP renders the Material on a screen."); public static readonly GUIContent SurfaceInputs = new GUIContent("Surface Inputs", "These settings describe the look and feel of the surface itself."); public static readonly GUIContent AdvancedLabel = new GUIContent("Advanced", "These settings affect behind-the-scenes rendering and underlying calculations."); public static readonly GUIContent surfaceType = new GUIContent("Surface Type", "Select a surface type for your texture. Choose between Opaque or Transparent."); public static readonly GUIContent blendingMode = new GUIContent("Blending Mode", "Controls how the color of the Transparent surface blends with the Material color in the background."); public static readonly GUIContent cullingText = new GUIContent("Render Face", "Specifies which faces to cull from your geometry. Front culls front faces. Back culls backfaces. None means that both sides are rendered."); public static readonly GUIContent alphaClipText = new GUIContent("Alpha Clipping", "Makes your Material act like a Cutout shader. Use this to create a transparent effect with hard edges between opaque and transparent areas."); public static readonly GUIContent alphaClipThresholdText = new GUIContent("Threshold", "Sets where the Alpha Clipping starts. The higher the value is, the brighter the effect is when clipping starts."); public static readonly GUIContent receiveShadowText = new GUIContent("Receive Shadows", "When enabled, other GameObjects can cast shadows onto this GameObject."); public static readonly GUIContent baseMap = new GUIContent("Base Map", "Specifies the base Material and/or Color of the surface. If you've selected Transparent or Alpha Clipping under Surface Options, your Material uses the Texture's alpha channel or color."); public static readonly GUIContent emissionMap = new GUIContent("Emission Map", "Sets a Texture map to use for emission. You can also select a color with the color picker. Colors are multiplied over the Texture."); public static readonly GUIContent normalMapText = new GUIContent("Normal Map", "Assigns a tangent-space normal map."); public static readonly GUIContent bumpScaleNotSupported = new GUIContent("Bump scale is not supported on mobile platforms"); public static readonly GUIContent fixNormalNow = new GUIContent("Fix now", "Converts the assigned texture to be a normal map format."); public static readonly GUIContent queueSlider = new GUIContent("Priority", "Determines the chronological rendering order for a Material. High values are rendered first."); public static readonly GUIContent OtherOptions = new GUIContent("Your own options", "You own custom options"); } #endregion #region Variables protected MaterialEditor materialEditor { get; set; } protected MaterialProperty surfaceTypeProp { get; set; } protected MaterialProperty blendModeProp { get; set; } protected MaterialProperty cullingProp { get; set; } protected MaterialProperty alphaClipProp { get; set; } protected MaterialProperty alphaCutoffProp { get; set; } protected MaterialProperty receiveShadowsProp { get; set; } // Common Surface Input properties protected MaterialProperty baseMapProp { get; set; } protected MaterialProperty baseColorProp { get; set; } protected MaterialProperty emissionMapProp { get; set; } protected MaterialProperty emissionColorProp { get; set; } protected MaterialProperty queueOffsetProp { get; set; } public bool m_FirstTimeApply = true; private const string k_KeyPrefix = "LightweightRP:Material:UI_State:"; private string m_HeaderStateKey = null; // Header foldout states AnimatedValues.AnimBool m_SurfaceOptionsFoldout; AnimatedValues.AnimBool m_SurfaceInputsFoldout; AnimatedValues.AnimBool m_AdvancedFoldout; AnimatedValues.AnimBool m_OtherFoldout; #endregion private const int queueOffsetRange = 50; //////////////////////////////////// // General Functions // //////////////////////////////////// #region GeneralFunctions public abstract void MaterialChanged(Material material); public virtual void FindProperties(MaterialProperty[] properties) { surfaceTypeProp = FindProperty("_Surface", properties); blendModeProp = FindProperty("_Blend", properties); cullingProp = FindProperty("_Cull", properties); alphaClipProp = FindProperty("_AlphaClip", properties); alphaCutoffProp = FindProperty("_Cutoff", properties); receiveShadowsProp = FindProperty("_ReceiveShadows", properties, false); baseMapProp = FindProperty("_BaseMap", properties, false); baseColorProp = FindProperty("_BaseColor", properties, false); emissionMapProp = FindProperty("_EmissionMap", properties, false); emissionColorProp = FindProperty("_EmissionColor", properties, false); queueOffsetProp = FindProperty("_QueueOffset", properties, false); } public override void OnGUI(MaterialEditor materialEditorIn, MaterialProperty[] properties) { if (materialEditorIn == null) throw new ArgumentNullException("materialEditorIn"); FindProperties(properties); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly materialEditor = materialEditorIn; Material material = materialEditor.target as Material; // Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing // material to a lightweight shader. if (m_FirstTimeApply) { OnOpenGUI(material, materialEditorIn); m_FirstTimeApply = false; } ShaderPropertiesGUI(material); m_OtherFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_OtherFoldout.value, Styles.OtherOptions); if (m_OtherFoldout.value) { base.OnGUI(materialEditorIn, properties); EditorGUILayout.Space(); } EditorGUILayout.EndFoldoutHeaderGroup(); foreach (var obj in materialEditor.targets) MaterialChanged((Material)obj); } public virtual void OnOpenGUI(Material material, MaterialEditor materialEditor) { // Foldout states m_HeaderStateKey = k_KeyPrefix + material.shader.name; // Create key string for editor prefs m_SurfaceOptionsFoldout = new AnimatedValues.AnimBool(true); m_SurfaceInputsFoldout = new AnimatedValues.AnimBool(true); m_AdvancedFoldout = new AnimatedValues.AnimBool(true); m_OtherFoldout = new AnimatedValues.AnimBool(true); foreach (var obj in materialEditor.targets) MaterialChanged((Material)obj); } public void ShaderPropertiesGUI(Material material) { if (material == null) throw new ArgumentNullException("material"); EditorGUI.BeginChangeCheck(); m_SurfaceOptionsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SurfaceOptionsFoldout.value, Styles.SurfaceOptions); if (m_SurfaceOptionsFoldout.value) { DrawSurfaceOptions(material); EditorGUILayout.Space(); } EditorGUILayout.EndFoldoutHeaderGroup(); m_SurfaceInputsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SurfaceInputsFoldout.value, Styles.SurfaceInputs); if (m_SurfaceInputsFoldout.value) { DrawSurfaceInputs(material); EditorGUILayout.Space(); } EditorGUILayout.EndFoldoutHeaderGroup(); m_AdvancedFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_AdvancedFoldout.value, Styles.AdvancedLabel); if (m_AdvancedFoldout.value) { DrawAdvancedOptions(material); EditorGUILayout.Space(); } EditorGUILayout.EndFoldoutHeaderGroup(); DrawAdditionalFoldouts(material); if (EditorGUI.EndChangeCheck()) { foreach (var obj in materialEditor.targets) MaterialChanged((Material)obj); } } #endregion //////////////////////////////////// // Drawing Functions // //////////////////////////////////// #region DrawingFunctions public virtual void DrawSurfaceOptions(Material material) { DoPopup(Styles.surfaceType, surfaceTypeProp, Enum.GetNames(typeof(SurfaceType))); if ((SurfaceType)material.GetFloat("_Surface") == SurfaceType.Transparent) DoPopup(Styles.blendingMode, blendModeProp, Enum.GetNames(typeof(BlendMode))); EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = cullingProp.hasMixedValue; var culling = (RenderFace)cullingProp.floatValue; culling = (RenderFace)EditorGUILayout.EnumPopup(Styles.cullingText, culling); if (EditorGUI.EndChangeCheck()) { materialEditor.RegisterPropertyChangeUndo(Styles.cullingText.text); cullingProp.floatValue = (float)culling; material.doubleSidedGI = (RenderFace)cullingProp.floatValue != RenderFace.Front; } EditorGUI.showMixedValue = false; EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = alphaClipProp.hasMixedValue; var alphaClipEnabled = EditorGUILayout.Toggle(Styles.alphaClipText, alphaClipProp.floatValue == 1); if (EditorGUI.EndChangeCheck()) alphaClipProp.floatValue = alphaClipEnabled ? 1 : 0; EditorGUI.showMixedValue = false; if (alphaClipProp.floatValue == 1) materialEditor.ShaderProperty(alphaCutoffProp, Styles.alphaClipThresholdText, 1); if (receiveShadowsProp != null) { EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = receiveShadowsProp.hasMixedValue; var receiveShadows = EditorGUILayout.Toggle(Styles.receiveShadowText, receiveShadowsProp.floatValue == 1.0f); if (EditorGUI.EndChangeCheck()) receiveShadowsProp.floatValue = receiveShadows ? 1.0f : 0.0f; EditorGUI.showMixedValue = false; } } public virtual void DrawSurfaceInputs(Material material) { DrawBaseProperties(material); } public virtual void DrawAdvancedOptions(Material material) { materialEditor.EnableInstancingField(); if (queueOffsetProp != null) { EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = queueOffsetProp.hasMixedValue; var queue = EditorGUILayout.IntSlider(Styles.queueSlider, (int)queueOffsetProp.floatValue, -queueOffsetRange, queueOffsetRange); if (EditorGUI.EndChangeCheck()) queueOffsetProp.floatValue = queue; EditorGUI.showMixedValue = false; } } public virtual void DrawAdditionalFoldouts(Material material) { } public virtual void DrawBaseProperties(Material material) { if (baseMapProp != null && baseColorProp != null) // Draw the baseMap, most shader will have at least a baseMap { materialEditor.TexturePropertySingleLine(Styles.baseMap, baseMapProp, baseColorProp); // TODO Temporary fix for lightmapping, to be replaced with attribute tag. if (material.HasProperty("_MainTex")) { material.SetTexture("_MainTex", baseMapProp.textureValue); var baseMapTiling = baseMapProp.textureScaleAndOffset; material.SetTextureScale("_MainTex", new Vector2(baseMapTiling.x, baseMapTiling.y)); material.SetTextureOffset("_MainTex", new Vector2(baseMapTiling.z, baseMapTiling.w)); } } } protected virtual void DrawEmissionProperties(Material material, bool keyword) { var emissive = true; var hadEmissionTexture = emissionMapProp.textureValue != null; if (!keyword) { materialEditor.TexturePropertyWithHDRColor(Styles.emissionMap, emissionMapProp, emissionColorProp, false); } else { // Emission for GI? emissive = materialEditor.EmissionEnabledProperty(); EditorGUI.BeginDisabledGroup(!emissive); { // Texture and HDR color controls materialEditor.TexturePropertyWithHDRColor(Styles.emissionMap, emissionMapProp, emissionColorProp, false); } EditorGUI.EndDisabledGroup(); } // If texture was assigned and color was black set color to white var brightness = emissionColorProp.colorValue.maxColorComponent; if (emissionMapProp.textureValue != null && !hadEmissionTexture && brightness <= 0f) emissionColorProp.colorValue = Color.white; // LW does not support RealtimeEmissive. We set it to bake emissive and handle the emissive is black right. if (emissive) { material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive; if (brightness <= 0f) material.globalIlluminationFlags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack; } } public static void DrawNormalArea(MaterialEditor materialEditor, MaterialProperty bumpMap, MaterialProperty bumpMapScale = null) { if (bumpMapScale != null) { materialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpMapScale : null); if (bumpMapScale.floatValue != 1 && UnityEditorInternal.InternalEditorUtility.IsMobilePlatform( EditorUserBuildSettings.activeBuildTarget)) if (materialEditor.HelpBoxWithButton(Styles.bumpScaleNotSupported, Styles.fixNormalNow)) bumpMapScale.floatValue = 1; } else { materialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap); } } protected static void DrawTileOffset(MaterialEditor materialEditor, MaterialProperty textureProp) { materialEditor.TextureScaleOffsetProperty(textureProp); } #endregion //////////////////////////////////// // Material Data Functions // //////////////////////////////////// #region MaterialDataFunctions public static void SetMaterialKeywords(Material material, Action<Material> shadingModelFunc = null, Action<Material> shaderFunc = null) { // Clear all keywords for fresh start material.shaderKeywords = null; // Setup blending - consistent across all LWRP shaders SetupMaterialBlendMode(material); // Receive Shadows if (material.HasProperty("_ReceiveShadows")) CoreUtils.SetKeyword(material, "_RECEIVE_SHADOWS_OFF", material.GetFloat("_ReceiveShadows") == 0.0f); // Emission if (material.HasProperty("_EmissionColor")) MaterialEditor.FixupEmissiveFlag(material); bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0; if (material.HasProperty("_EmissionEnabled") && !shouldEmissionBeEnabled) shouldEmissionBeEnabled = material.GetFloat("_EmissionEnabled") >= 0.5f; CoreUtils.SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled); // Normal Map if (material.HasProperty("_BumpMap")) CoreUtils.SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap")); // Shader specific keyword functions shadingModelFunc?.Invoke(material); shaderFunc?.Invoke(material); } public static void SetupMaterialBlendMode(Material material) { if (material == null) throw new ArgumentNullException("material"); bool alphaClip = material.GetFloat("_AlphaClip") == 1; if (alphaClip) { material.EnableKeyword("_ALPHATEST_ON"); } else { material.DisableKeyword("_ALPHATEST_ON"); } var queueOffset = 0; // queueOffsetRange; if (material.HasProperty("_QueueOffset")) queueOffset = queueOffsetRange - (int)material.GetFloat("_QueueOffset"); SurfaceType surfaceType = (SurfaceType)material.GetFloat("_Surface"); if (surfaceType == SurfaceType.Opaque) { if (alphaClip) { material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest; material.SetOverrideTag("RenderType", "TransparentCutout"); } else { material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry; material.SetOverrideTag("RenderType", "Opaque"); } material.renderQueue += queueOffset; material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_ZWrite", 1); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.SetShaderPassEnabled("ShadowCaster", true); } else { BlendMode blendMode = (BlendMode)material.GetFloat("_Blend"); var queue = (int)UnityEngine.Rendering.RenderQueue.Transparent; // Specific Transparent Mode Settings switch (blendMode) { case BlendMode.Alpha: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); break; case BlendMode.Premultiply: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); break; case BlendMode.Additive: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); break; case BlendMode.Multiply: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.EnableKeyword("_ALPHAMODULATE_ON"); break; } // General Transparent Material Settings material.SetOverrideTag("RenderType", "Transparent"); material.SetInt("_ZWrite", 0); material.renderQueue = queue + queueOffset; material.SetShaderPassEnabled("ShadowCaster", false); } } #endregion //////////////////////////////////// // Helper Functions // //////////////////////////////////// #region HelperFunctions public static void TwoFloatSingleLine(GUIContent title, MaterialProperty prop1, GUIContent prop1Label, MaterialProperty prop2, GUIContent prop2Label, MaterialEditor materialEditor, float labelWidth = 30f) { EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = prop1.hasMixedValue || prop2.hasMixedValue; Rect rect = EditorGUILayout.GetControlRect(); EditorGUI.PrefixLabel(rect, title); var indent = EditorGUI.indentLevel; var preLabelWidth = EditorGUIUtility.labelWidth; EditorGUI.indentLevel = 0; EditorGUIUtility.labelWidth = labelWidth; Rect propRect1 = new Rect(rect.x + preLabelWidth, rect.y, (rect.width - preLabelWidth) * 0.5f, EditorGUIUtility.singleLineHeight); var prop1val = EditorGUI.FloatField(propRect1, prop1Label, prop1.floatValue); Rect propRect2 = new Rect(propRect1.x + propRect1.width, rect.y, propRect1.width, EditorGUIUtility.singleLineHeight); var prop2val = EditorGUI.FloatField(propRect2, prop2Label, prop2.floatValue); EditorGUI.indentLevel = indent; EditorGUIUtility.labelWidth = preLabelWidth; if (EditorGUI.EndChangeCheck()) { materialEditor.RegisterPropertyChangeUndo(title.text); prop1.floatValue = prop1val; prop2.floatValue = prop2val; } EditorGUI.showMixedValue = false; } public void DoPopup(GUIContent label, MaterialProperty property, string[] options) { DoPopup(label, property, options, materialEditor); } public static void DoPopup(GUIContent label, MaterialProperty property, string[] options, MaterialEditor materialEditor) { if (property == null) throw new ArgumentNullException("property"); EditorGUI.showMixedValue = property.hasMixedValue; var mode = property.floatValue; EditorGUI.BeginChangeCheck(); mode = EditorGUILayout.Popup(label, (int)mode, options); if (EditorGUI.EndChangeCheck()) { materialEditor.RegisterPropertyChangeUndo(label.text); property.floatValue = mode; } EditorGUI.showMixedValue = false; } // Helper to show texture and color properties public static Rect TextureColorProps(MaterialEditor materialEditor, GUIContent label, MaterialProperty textureProp, MaterialProperty colorProp, bool hdr = false) { Rect rect = EditorGUILayout.GetControlRect(); EditorGUI.showMixedValue = textureProp.hasMixedValue; materialEditor.TexturePropertyMiniThumbnail(rect, textureProp, label.text, label.tooltip); EditorGUI.showMixedValue = false; if (colorProp != null) { EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = colorProp.hasMixedValue; int indentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; Rect rectAfterLabel = new Rect(rect.x + EditorGUIUtility.labelWidth, rect.y, EditorGUIUtility.fieldWidth, EditorGUIUtility.singleLineHeight); var col = EditorGUI.ColorField(rectAfterLabel, GUIContent.none, colorProp.colorValue, true, false, hdr); EditorGUI.indentLevel = indentLevel; if (EditorGUI.EndChangeCheck()) { materialEditor.RegisterPropertyChangeUndo(colorProp.displayName); colorProp.colorValue = col; } EditorGUI.showMixedValue = false; } return rect; } // Copied from shaderGUI as it is a protected function in an abstract class, unavailable to others public new static MaterialProperty FindProperty(string propertyName, MaterialProperty[] properties) { return FindProperty(propertyName, properties, true); } // Copied from shaderGUI as it is a protected function in an abstract class, unavailable to others public new static MaterialProperty FindProperty(string propertyName, MaterialProperty[] properties, bool propertyIsMandatory) { for (int index = 0; index < properties.Length; ++index) { if (properties[index] != null && properties[index].name == propertyName) return properties[index]; } if (propertyIsMandatory) throw new ArgumentException("Could not find MaterialProperty: '" + propertyName + "', Num properties: " + (object)properties.Length); return null; } #endregion } } 


LitShaderEditor.cs
 using System; using UnityEngine; using UnityEngine.Rendering; using UnityEditor.Rendering.LWRP; namespace UnityEditor.Rendering.LWRP.ShaderGUI { internal class LitShaderEditor : BaseShaderEditor { // Properties private LitGUI.LitProperties litProperties; // collect properties from the material properties public override void FindProperties(MaterialProperty[] properties) { base.FindProperties(properties); litProperties = new LitGUI.LitProperties(properties); } // material changed check public override void MaterialChanged(Material material) { if (material == null) throw new ArgumentNullException("material"); SetMaterialKeywords(material, LitGUI.SetMaterialKeywords); } // material main surface options public override void DrawSurfaceOptions(Material material) { if (material == null) throw new ArgumentNullException("material"); // Use default labelWidth EditorGUIUtility.labelWidth = 0f; // Detect any changes to the material EditorGUI.BeginChangeCheck(); if (litProperties.workflowMode != null) { DoPopup(LitGUI.Styles.workflowModeText, litProperties.workflowMode, Enum.GetNames(typeof(LitGUI.WorkflowMode))); } if (EditorGUI.EndChangeCheck()) { foreach (var obj in blendModeProp.targets) MaterialChanged((Material)obj); } base.DrawSurfaceOptions(material); } // material main surface inputs public override void DrawSurfaceInputs(Material material) { base.DrawSurfaceInputs(material); LitGUI.Inputs(litProperties, materialEditor, material); DrawEmissionProperties(material, true); DrawTileOffset(materialEditor, baseMapProp); } // material main advanced options public override void DrawAdvancedOptions(Material material) { if (litProperties.reflections != null && litProperties.highlights != null) { EditorGUI.BeginChangeCheck(); { materialEditor.ShaderProperty(litProperties.highlights, LitGUI.Styles.highlightsText); materialEditor.ShaderProperty(litProperties.reflections, LitGUI.Styles.reflectionsText); EditorGUI.BeginChangeCheck(); } } base.DrawAdvancedOptions(material); } public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) { if (material == null) throw new ArgumentNullException("material"); // _Emission property is lost after assigning Standard shader to the material // thus transfer it before assigning the new shader if (material.HasProperty("_Emission")) { material.SetColor("_EmissionColor", material.GetColor("_Emission")); } base.AssignNewShaderToMaterial(material, oldShader, newShader); if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/")) { SetupMaterialBlendMode(material); return; } SurfaceType surfaceType = SurfaceType.Opaque; BlendMode blendMode = BlendMode.Alpha; if (oldShader.name.Contains("/Transparent/Cutout/")) { surfaceType = SurfaceType.Opaque; material.SetFloat("_AlphaClip", 1); } else if (oldShader.name.Contains("/Transparent/")) { // NOTE: legacy shaders did not provide physically based transparency // therefore Fade mode surfaceType = SurfaceType.Transparent; blendMode = BlendMode.Alpha; } material.SetFloat("_Surface", (float)surfaceType); material.SetFloat("_Blend", (float)blendMode); if (oldShader.name.Equals("Standard (Specular setup)")) { material.SetFloat("_WorkflowMode", (float)LitGUI.WorkflowMode.Specular); Texture texture = material.GetTexture("_SpecGlossMap"); if (texture != null) material.SetTexture("_MetallicSpecGlossMap", texture); } else { material.SetFloat("_WorkflowMode", (float)LitGUI.WorkflowMode.Metallic); Texture texture = material.GetTexture("_MetallicGlossMap"); if (texture != null) material.SetTexture("_MetallicSpecGlossMap", texture); } MaterialChanged(material); } } } 


Voyons maintenant l'intérieur du shader.

La première chose à laquelle vous faites attention est qu'il n'y a que cinq passes dans le shader. Arrêtons-nous un peu sur eux:

  1. ForwardLit: Pass avant, nous considérons ici la lumière, le PBR et le brouillard.
  2. ShadowCaster: voici le calcul des ombres.
  3. DepthOnly: Depth (Z-Buffer).
  4. Méta: lumière cuite (lightmaps).
  5. Lightweight2D: sprites et UI.

De plus, Unity a plusieurs compilateurs de shader et compilateurs croisés différents. SRP nécessite HLSLcc. Sur les plates-formes qui utilisent l'API graphique OpenGL ES (comme Android), HLSLcc n'est pas utilisé par défaut.

Par conséquent, nous le forçons à se connecter:

 #pragma prefer_hlslcc gles 

Mais DirectX 9 n'est pas pris en charge, désactivez-le donc de force:

 #pragma exclude_renderers d3d11_9x 

En termes d'écriture du code lui-même, rien n'a changé sauf que maintenant nous n'écrivons pas en CG, mais en HLSL pur, et donc maintenant le corps du programme shader ressemblera à ceci:

 HLSLPROGRAM ... ENDHLSL 

- _Time , _ScreenParams _WorldSpaceCameraPos . , UnityCG.cginc . , , UnityObjectToClipPos(POSITION) TransformWorldToHClip(POSITION) , — UNITY_APPLY_FOG(fogCoord, color) MixFog(color, fogCoord) .

, Core.hlsl:
% localappdata% \ Unity \ cache \ packages \ packages.unity.com \ com.unity.render-pipelines.lightweight @ (version LWRP) \ ShaderLibrary \ Core.hlsl

Nous pouvons trouver une liste complète des fonctionnalités disponibles.

Il convient également de mentionner les tampons constants (CBUFFER) et UnityPerMaterial. Des tampons constants sont utilisés pour stocker des données qui sont rarement modifiées sur le GPU, respectivement, ils peuvent être utilisés pour stocker des variables de shader. Pour ce faire, il suffit d'appeler les macros
CBUFFER_START et CBUFFER_END :

 CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; half4 _BaseColor; half4 _SpecColor; half4 _EmissionColor; half _Cutoff; half _Smoothness; half _Metallic; half _BumpScale; half _OcclusionStrength; CBUFFER_END 

La déclaration des variables globales ou de diverses variables paramétrées (à partir de code ou d'animation, par exemple) a lieu à l'ancienne dans le corps d'un programme de shader.

LWRP utilise deux types de tampons constants - UnityPerObject et UnityPerMaterial . Ces tampons sont liés une fois afin de pouvoir être utilisés pendant le rendu. En gros, cela signifie que pendant le dessin, les tampons constants ne seront pas renforcés ou le setpass ne sera pas appelé pour les matériaux. Cela est avantageux lorsque plusieurs shaders partagent le même tampon constant, car LWRP peut emballer différents matériaux pour cela.

En fait, si vous étudiez attentivement la structure du shader, vous pouvez constater que la plupart des données standard utilisent simplement des tampons constants partout.

Plus en détail, sur toutes les différences, mais en anglais, vous pouvez lire ici .

Soit dit en passant, si vous regardez attentivement SurfaceData:
 SurfaceData surfaceData; 

Vous trouverez peut-être que c'est le maître PBR chéri de ShaderGraph .

Exemple



Donc, maintenant nos mains sont complètement déliées, ce qui signifie que le moment est venu
d'organiser une bacchanale! Ajoutons le déplacement de sommet et l' effet de dissolution à titre d' exemple , et laissons le reste danser. Il est très pratique que toutes les passes soient devant nos yeux et que nous puissions tout éditer de manière complète. Décrivons les propriétés:

LVRP_TextShaders_2020-01-20_21-08-42.gif





 Properties { ... _DissolveMap("Dissolve Map", 2D) = "white" {} _DissolveFactor("Dissolve Factor", Range(0, 1)) = 0.0 _DissolveWidth("Dissolve Width", Range(0, 1)) = 0.0 [HDR]_DissolveColor("Color", Color) = (1,1,0) } 

Qui apparaîtra sans aucun doute dans notre propre onglet bien-aimé dans l'inspecteur: Ajouter des variables:
2020-01-20_22-55-14.png



 CBUFFER_START(UnityPerMaterial) ... float4 _DissolveMap_ST; //    _DissolveMap CBUFFER_END TEXTURE2D(_DissolveMap); SAMPLER(sampler_DissolveMap); float _DissolveFactor; float _DissolveWidth; float4 _DissolveColor; 

Tout d'abord, envoyez la géométrie à une stupeur ivre:

 Varyings LitPassVertex(Attributes input) { ... input.positionOS.xyz += normalize(input.positionOS.xyz) * sin(input.positionOS.x) * sin(_Time.x * 100); ... } 

Puis l'ombre:
 Varyings ShadowPassVertex(Attributes input) { ... input.positionOS.xyz += normalize(input.positionOS.xyz) * sin(input.positionOS.x) * sin(_Time.x * 100); ... } 

Profondeur:

 Varyings DepthOnlyVertex(Attributes input) { ... input.position.xyz += normalize(input.position.xyz) * sin(input.position.x) * sin(_Time.x * 100); ... } 

Eh bien, dissolvez maintenant le temps et le mouvement:

 half4 LitPassFragment(Varyings input) : SV_Target { ... // UV   input.uv += _Time.x * 10; //     Dissolve  float4 mask = SAMPLE_TEXTURE2D(_DissolveMap, sampler_DissolveMap, input.uv); if (mask.r > _DissolveFactor) discard; //  bool outline = mask.r > _DissolveFactor - _DissolveWidth; //    surfaceData.emission *= outline * _DissolveColor; //,    PBR-  half4 color = LightweightFragmentPBR(inputData, surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.occlusion, surfaceData.emission, surfaceData.alpha); //      color *= lerp(1, _DissolveColor, outline); ... } 

Vous pouvez également amener Dissolve dans l'ombre, puis avec un coup de poignet, nous aurons l'ombre correcte, ce qui est assez difficile à réaliser dans le Shader Graph , et voici quelques lignes de code.

 half4 ShadowPassFragment(Varyings input) : SV_TARGET { ... float4 mask = SAMPLE_TEXTURE2D(_DissolveMap, sampler_DissolveMap, input.uv); if (mask.r > _DissolveFactor) discard; ... } 

Eh bien, le code du shader final:

SimpleDissolve
 Shader "TheProxor/LWRP/Dissolve + Vertex Offset" { Properties { // Specular vs Metallic workflow [HideInInspector] _WorkflowMode("WorkflowMode", Float) = 1.0 [MainColor][HideInInspector] _BaseColor("Color", Color) = (0.5,0.5,0.5,1) [MainTexture][HideInInspector] _BaseMap("Albedo", 2D) = "white" {} [HideInInspector]_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 [HideInInspector]_Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5 [HideInInspector]_GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0 [HideInInspector]_SmoothnessTextureChannel("Smoothness texture channel", Float) = 0 [Gamma][HideInInspector] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0 [HideInInspector]_MetallicGlossMap("Metallic", 2D) = "white" {} [HideInInspector]_SpecColor("Specular", Color) = (0.2, 0.2, 0.2) [HideInInspector]_SpecGlossMap("Specular", 2D) = "white" {} [HideInInspector][ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 [HideInInspector][ToggleOff] _EnvironmentReflections("Environment Reflections", Float) = 1.0 [HideInInspector]_BumpScale("Scale", Float) = 1.0 [HideInInspector]_BumpMap("Normal Map", 2D) = "bump" {} [HideInInspector]_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0 [HideInInspector]_OcclusionMap("Occlusion", 2D) = "white" {} [HDR][HideInInspector]_EmissionColor("Color", Color) = (0,0,0) [HideInInspector]_EmissionMap("Emission", 2D) = "white" {} // Blending state [HideInInspector] _Surface("__surface", Float) = 0.0 [HideInInspector] _Blend("__blend", Float) = 0.0 [HideInInspector] _AlphaClip("__clip", Float) = 0.0 [HideInInspector] _SrcBlend("__src", Float) = 1.0 [HideInInspector] _DstBlend("__dst", Float) = 0.0 [HideInInspector] _ZWrite("__zw", Float) = 1.0 [HideInInspector] _Cull("__cull", Float) = 2.0 [HideInInspector]_ReceiveShadows("Receive Shadows", Float) = 1.0 // Editmode props [HideInInspector] _QueueOffset("Queue offset", Float) = 0.0 // ObsoleteProperties [HideInInspector] _MainTex("BaseMap", 2D) = "white" {} [HideInInspector] _Color("Base Color", Color) = (0.5, 0.5, 0.5, 1) [HideInInspector] _GlossMapScale("Smoothness", Float) = 0.0 [HideInInspector] _Glossiness("Smoothness", Float) = 0.0 [HideInInspector] _GlossyReflections("EnvironmentReflections", Float) = 0.0 // _DissolveMap("Dissolve Map", 2D) = "white" {} _DissolveFactor("Dissolve Factor", Range(0, 1)) = 0.0 _DissolveWidth("Dissolve Width", Range(0, 1)) = 0.0 [HDR]_DissolveColor("Color", Color) = (1,1,0) } SubShader { // Lightweight Pipeline tag is required. If Lightweight 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 Lightweight Render Pipeline and Builtin Unity Pipeline Tags{"RenderType" = "Opaque" "RenderPipeline" = "LightweightPipeline" "IgnoreProjector" = "True"} LOD 300 // ------------------------------------------------------------------ // Forward pass. Shades all light in a single pass. GI + emission + Fog Pass { // Lightmode matches the ShaderPassName set in LightweightRenderPipeline.cs. SRPDefaultUnlit and passes with // no LightMode tag are also rendered by Lightweight Render Pipeline Name "ForwardLit" Tags{"LightMode" = "LightweightForward"} Blend[_SrcBlend][_DstBlend] ZWrite[_ZWrite] Cull[_Cull] 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 // ------------------------------------- // Material Keywords #pragma shader_feature _NORMALMAP #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _ALPHAPREMULTIPLY_ON #pragma shader_feature _EMISSION #pragma shader_feature _METALLICSPECGLOSSMAP #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _OCCLUSIONMAP #pragma shader_feature _SPECULARHIGHLIGHTS_OFF #pragma shader_feature _ENVIRONMENTREFLECTIONS_OFF #pragma shader_feature _SPECULAR_SETUP #pragma shader_feature _RECEIVE_SHADOWS_OFF // ------------------------------------- // Lightweight Pipeline keywords #pragma multi_compile _ _MAIN_LIGHT_SHADOWS #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile _ _SHADOWS_SOFT #pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE // ------------------------------------- // Unity defined keywords #pragma multi_compile _ DIRLIGHTMAP_COMBINED #pragma multi_compile _ LIGHTMAP_ON #pragma multi_compile_fog //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma vertex LitPassVertex #pragma fragment LitPassFragment #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Lighting.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/SurfaceInput.hlsl" #ifdef _SPECULAR_SETUP #define SAMPLE_METALLICSPECULAR(uv) SAMPLE_TEXTURE2D(_SpecGlossMap, sampler_SpecGlossMap, uv) #else #define SAMPLE_METALLICSPECULAR(uv) SAMPLE_TEXTURE2D(_MetallicGlossMap, sampler_MetallicGlossMap, uv) #endif struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; float4 tangentOS : TANGENT; float2 texcoord : TEXCOORD0; float2 lightmapUV : TEXCOORD1; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float2 uv : TEXCOORD0; DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 1); #ifdef _ADDITIONAL_LIGHTS float3 positionWS : TEXCOORD2; #endif #ifdef _NORMALMAP half4 normalWS : TEXCOORD3; // xyz: normal, w: viewDir.x half4 tangentWS : TEXCOORD4; // xyz: tangent, w: viewDir.y half4 bitangentWS : TEXCOORD5; // xyz: bitangent, w: viewDir.z #else half3 normalWS : TEXCOORD3; half3 viewDirWS : TEXCOORD4; #endif half4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light #ifdef _MAIN_LIGHT_SHADOWS float4 shadowCoord : TEXCOORD7; #endif float4 positionCS : SV_POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO float3 uvDissolve : TEXCOORD8; }; CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; half4 _BaseColor; half4 _SpecColor; half4 _EmissionColor; half _Cutoff; half _Smoothness; half _Metallic; half _BumpScale; half _OcclusionStrength; float4 _DissolveMap_ST; //    _DissolveMap CBUFFER_END TEXTURE2D(_OcclusionMap); SAMPLER(sampler_OcclusionMap); TEXTURE2D(_MetallicGlossMap); SAMPLER(sampler_MetallicGlossMap); TEXTURE2D(_SpecGlossMap); SAMPLER(sampler_SpecGlossMap); TEXTURE2D(_DissolveMap); SAMPLER(sampler_DissolveMap); float _DissolveFactor; float _DissolveWidth; float4 _DissolveColor; half4 SampleMetallicSpecGloss(float2 uv, half albedoAlpha) { half4 specGloss; #ifdef _METALLICSPECGLOSSMAP specGloss = SAMPLE_METALLICSPECULAR(uv); #ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A specGloss.a = albedoAlpha * _Smoothness; #else specGloss.a *= _Smoothness; #endif #else // _METALLICSPECGLOSSMAP #if _SPECULAR_SETUP specGloss.rgb = _SpecColor.rgb; #else specGloss.rgb = _Metallic.rrr; #endif #ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A specGloss.a = albedoAlpha * _Smoothness; #else specGloss.a = _Smoothness; #endif #endif return specGloss; } half SampleOcclusion(float2 uv) { #ifdef _OCCLUSIONMAP // TODO: Controls things like these by exposing SHADER_QUALITY levels (low, medium, high) #if defined(SHADER_API_GLES) return SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, uv).g; #else half occ = SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, uv).g; return LerpWhiteTo(occ, _OcclusionStrength); #endif #else return 1.0; #endif } inline void InitializeStandardLitSurfaceData(float2 uv, out SurfaceData outSurfaceData) { half4 albedoAlpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv); // half4 albedoAlpha = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)); outSurfaceData.alpha = Alpha(albedoAlpha.a, _BaseColor, _Cutoff); half4 specGloss = SampleMetallicSpecGloss(uv, albedoAlpha.a); outSurfaceData.albedo = albedoAlpha.rgb * _BaseColor.rgb; #if _SPECULAR_SETUP outSurfaceData.metallic = 1.0h; outSurfaceData.specular = specGloss.rgb; #else outSurfaceData.metallic = specGloss.r; outSurfaceData.specular = half3(0.0h, 0.0h, 0.0h); #endif outSurfaceData.smoothness = specGloss.a; outSurfaceData.normalTS = SampleNormal(uv, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap), _BumpScale); outSurfaceData.occlusion = SampleOcclusion(uv); outSurfaceData.emission = SampleEmission(uv, _EmissionColor.rgb, TEXTURE2D_ARGS(_EmissionMap, sampler_EmissionMap)); // outSurfaceData.emission = _EmissionColor.rgb * SAMPLE_TEXTURE2D(_EmissionMap, sampler_EmissionMap, uv); } void InitializeInputData(Varyings input, half3 normalTS, out InputData inputData) { inputData = (InputData)0; #ifdef _ADDITIONAL_LIGHTS inputData.positionWS = input.positionWS; #endif #ifdef _NORMALMAP half3 viewDirWS = half3(input.normalWS.w, input.tangentWS.w, input.bitangentWS.w); inputData.normalWS = TransformTangentToWorld(normalTS, half3x3(input.tangentWS.xyz, input.bitangentWS.xyz, input.normalWS.xyz)); #else half3 viewDirWS = input.viewDirWS; inputData.normalWS = input.normalWS; #endif inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS); viewDirWS = SafeNormalize(viewDirWS); inputData.viewDirectionWS = viewDirWS; #if defined(_MAIN_LIGHT_SHADOWS) && !defined(_RECEIVE_SHADOWS_OFF) inputData.shadowCoord = input.shadowCoord; #else inputData.shadowCoord = float4(0, 0, 0, 0); #endif inputData.fogCoord = input.fogFactorAndVertexLight.x; inputData.vertexLighting = input.fogFactorAndVertexLight.yzw; inputData.bakedGI = SAMPLE_GI(input.lightmapUV, input.vertexSH, inputData.normalWS); } /////////////////////////////////////////////////////////////////////////////// // Vertex and Fragment functions // /////////////////////////////////////////////////////////////////////////////// //Standard (Physically Based) shader Varyings LitPassVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); input.positionOS.xyz += sin(input.positionOS.x) * sin(_Time.x * 100); VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz); VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS); half3 viewDirWS = GetCameraPositionWS() - vertexInput.positionWS; half3 vertexLight = VertexLighting(vertexInput.positionWS, normalInput.normalWS); half fogFactor = ComputeFogFactor(vertexInput.positionCS.z); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); #ifdef _NORMALMAP output.normalWS = half4(normalInput.normalWS, viewDirWS.x); output.tangentWS = half4(normalInput.tangentWS, viewDirWS.y); output.bitangentWS = half4(normalInput.bitangentWS, viewDirWS.z); #else output.normalWS = NormalizeNormalPerVertex(normalInput.normalWS); output.viewDirWS = viewDirWS; #endif OUTPUT_LIGHTMAP_UV(input.lightmapUV, unity_LightmapST, output.lightmapUV); OUTPUT_SH(output.normalWS.xyz, output.vertexSH); output.fogFactorAndVertexLight = half4(fogFactor, vertexLight); #ifdef _ADDITIONAL_LIGHTS output.positionWS = vertexInput.positionWS; #endif #if defined(_MAIN_LIGHT_SHADOWS) && !defined(_RECEIVE_SHADOWS_OFF) output.shadowCoord = GetShadowCoord(vertexInput); #endif output.positionCS = vertexInput.positionCS; return output; } // Used in Standard (Physically Based) shader half4 LitPassFragment(Varyings input) : SV_Target { input.uv += _Time.x * 10; UNITY_SETUP_INSTANCE_ID(input); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); SurfaceData surfaceData; InitializeStandardLitSurfaceData(input.uv, surfaceData); InputData inputData; InitializeInputData(input, surfaceData.normalTS, inputData); float4 mask = SAMPLE_TEXTURE2D(_DissolveMap, sampler_DissolveMap, input.uv); if (mask.r > _DissolveFactor) discard; bool outline = mask.r > _DissolveFactor - _DissolveWidth; surfaceData.emission *= outline * _DissolveColor; half4 color = LightweightFragmentPBR(inputData, surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.occlusion, surfaceData.emission, surfaceData.alpha); color *= lerp(1, _DissolveColor, outline); color.rgb = MixFog(color.rgb, inputData.fogCoord); 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 _ALPHATEST_ON //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma vertex ShadowPassVertex #pragma fragment ShadowPassFragment #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Shadows.hlsl" float3 _LightDirection; struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; float2 texcoord : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float2 uv : TEXCOORD0; float4 positionCS : SV_POSITION; }; CBUFFER_START(UnityPerMaterial) float4 _DissolveMap_ST; //    _DissolveMap float _DissolveFactor; CBUFFER_END TEXTURE2D(_DissolveMap); SAMPLER(sampler_DissolveMap); float4 GetShadowPositionHClip(Attributes input) { float3 positionWS = TransformObjectToWorld(input.positionOS.xyz); float3 normalWS = TransformObjectToWorldNormal(input.normalOS); float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection)); #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 return positionCS; } Varyings ShadowPassVertex(Attributes input) { Varyings output; input.positionOS.xyz += normalize(input.positionOS.xyz) * sin(input.positionOS.x) * sin(_Time.x * 100); UNITY_SETUP_INSTANCE_ID(input); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); output.positionCS = GetShadowPositionHClip(input); return output; } half4 ShadowPassFragment(Varyings input) : SV_TARGET { float4 mask = SAMPLE_TEXTURE2D(_DissolveMap, sampler_DissolveMap, input.uv); if (mask.r > _DissolveFactor) discard; Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff); return 0; } ENDHLSL } Pass { Name "DepthOnly" Tags{"LightMode" = "DepthOnly"} ZWrite On ColorMask 0 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 #pragma vertex DepthOnlyVertex #pragma fragment DepthOnlyFragment // ------------------------------------- // Material Keywords #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Core.hlsl" #ifndef LIGHTWEIGHT_DEPTH_ONLY_PASS_INCLUDED #define LIGHTWEIGHT_DEPTH_ONLY_PASS_INCLUDED struct Attributes { float4 position : POSITION; float2 texcoord : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float2 uv : TEXCOORD0; float4 positionCS : SV_POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO }; Varyings DepthOnlyVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); input.position.xyz += normalize(input.position.xyz) * sin(input.position.x) * sin(_Time.x * 100); output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); output.positionCS = TransformObjectToHClip(input.position.xyz); return output; } half4 DepthOnlyFragment(Varyings input) : SV_TARGET { UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff); return 0; } #endif ENDHLSL } // Pass { Name "Meta" Tags{"LightMode" = "Meta"} Cull Off HLSLPROGRAM // Required to compile gles 2.0 with standard srp library #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma vertex LightweightVertexMeta #pragma fragment LightweightFragmentMeta #pragma shader_feature _SPECULAR_SETUP #pragma shader_feature _EMISSION #pragma shader_feature _METALLICSPECGLOSSMAP #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _SPECGLOSSMAP #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/MetaInput.hlsl" #ifndef LIGHTWEIGHT_LIT_META_PASS_INCLUDED #define LIGHTWEIGHT_LIT_META_PASS_INCLUDED Varyings LightweightVertexMeta(Attributes input) { Varyings output; output.positionCS = MetaVertexPosition(input.positionOS, input.uv1, input.uv2, unity_LightmapST, unity_DynamicLightmapST); output.uv = TRANSFORM_TEX(input.uv0, _BaseMap); return output; } half4 LightweightFragmentMeta(Varyings input) : SV_Target { SurfaceData surfaceData; InitializeStandardLitSurfaceData(input.uv, surfaceData); BRDFData brdfData; InitializeBRDFData(surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.alpha, brdfData); MetaInput metaInput; metaInput.Albedo = brdfData.diffuse + brdfData.specular * brdfData.roughness * 0.5; metaInput.SpecularColor = surfaceData.specular; metaInput.Emission = surfaceData.emission; return MetaFragment(metaInput); } #endif ENDHLSL } Pass { Name "Lightweight2D" Tags{ "LightMode" = "Lightweight2D" } Blend[_SrcBlend][_DstBlend] ZWrite[_ZWrite] Cull[_Cull] HLSLPROGRAM // Required to compile gles 2.0 with standard srp library #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma vertex vert #pragma fragment frag #pragma shader_feature _ALPHATEST_ON #pragma shader_feature _ALPHAPREMULTIPLY_ON #include "Packages/com.unity.render-pipelines.lightweight/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/Shaders/Utils/Lightweight2D.hlsl" ENDHLSL } } FallBack "Hidden/InternalErrorShader" CustomEditor "UnityEditor.Rendering.LWRP.ShaderGUI.LitShaderEditor" } 

Conclusion


Eh bien, il est temps de faire le point. Comme il est devenu clair, dans LWRP, il est possible et même nécessaire d'écrire des shaders avec du code, car cela libère considérablement vos mains, aidant à écrire des choses cool sans béquilles, par exemple, votre système d'éclairage. Bien sûr, cela ne peut pas être comparé au Shader de surface standard pratique et familier , mais peut-être qu'un jour j'aurai les mains pour écrire le même analogique pratique pour LWRP et HDRP, mais plus à ce sujet une autre fois.

Liens utiles:

Référentiel avec tous les matériaux de l'article
Trouvé lors de la préparation du matériel, documentation non officielle Documentation
LWRP

Source: https://habr.com/ru/post/fr485018/


All Articles