From c81e4c275a1202aadb6070852b54ec20162a4efe Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Fri, 4 Jun 2021 21:21:04 +0900 Subject: [PATCH] add outline pass --- .../VRM10/vrmc_materials_mtoon.shader | 39 ++++++++++- .../VRM10/vrmc_materials_mtoon_attribute.hlsl | 5 +- .../VRM10/vrmc_materials_mtoon_define.hlsl | 34 ++++++++++ ...vrmc_materials_mtoon_forward_fragment.hlsl | 1 + .../vrmc_materials_mtoon_forward_vertex.hlsl | 25 +++++-- .../vrmc_materials_mtoon_geometry_vertex.hlsl | 66 +++++++++++++++++++ ..._materials_mtoon_geometry_vertex.hlsl.meta | 3 + .../vrmc_materials_mtoon_lighting_mtoon.hlsl | 8 ++- .../VRM10/vrmc_materials_mtoon_utility.hlsl | 5 ++ 9 files changed, 175 insertions(+), 11 deletions(-) create mode 100644 Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl create mode 100644 Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl.meta diff --git a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon.shader b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon.shader index 4384fbe73..dabf697db 100644 --- a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon.shader +++ b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon.shader @@ -62,6 +62,7 @@ Shader "Hidden/VRM10/vrmc_materials_mtoon" _M_DebugMode ("_DebugMode", Float) = 0.0 } + // Shader Model 3.0 SubShader { Tags { "RenderType" = "Opaque" "Queue" = "Geometry" } @@ -77,7 +78,7 @@ Shader "Hidden/VRM10/vrmc_materials_mtoon" ZWrite [_M_ZWrite] ZTest LEqual BlendOp Add, Max - AlphaToMask Off + AlphaToMask [_M_AlphaToMask] HLSLPROGRAM #pragma target 3.0 @@ -99,6 +100,42 @@ Shader "Hidden/VRM10/vrmc_materials_mtoon" ENDHLSL } + // Built-in Forward Base Pass: OUTLINE + Pass + { + Name "FORWARD_BASE_OUTLINE" + Tags { "LightMode" = "ForwardBase" } + + Cull Front + Blend [_M_SrcBlend] [_M_DstBlend] + ZWrite [_M_ZWrite] + ZTest LEqual + BlendOp Add, Max + AlphaToMask [_M_AlphaToMask] + + HLSLPROGRAM + #pragma target 3.0 + + // Unity defined keywords + #pragma multi_compile_fwdbase + #pragma multi_compile_fog + #pragma multi_compile_instancing + + #pragma multi_compile_local __ _ALPHATEST_ON _ALPHABLEND_ON + #pragma multi_compile_local __ _NORMALMAP + #pragma multi_compile_local __ _UVANIMATION + + #define MTOON_PASS_OUTLINE + #define MTOON_OUTLINE_WIDTH_WORLD + + #pragma vertex MToonVertex + #pragma fragment MToonFragment + + #include "./vrmc_materials_mtoon_forward_vertex.hlsl" + #include "./vrmc_materials_mtoon_forward_fragment.hlsl" + ENDHLSL + } + // Built-in Forward Add Pass Pass { diff --git a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_attribute.hlsl b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_attribute.hlsl index f1aa1e87b..a9068f852 100644 --- a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_attribute.hlsl +++ b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_attribute.hlsl @@ -25,8 +25,9 @@ struct Varyings half4 tangentWS : TEXCOORD3; #endif float3 viewDirWS : TEXCOORD4; - UNITY_FOG_COORDS(5) - UNITY_LIGHTING_COORDS(6,7) + half outlineFactor : TEXCOORD5; + UNITY_FOG_COORDS(6) + UNITY_LIGHTING_COORDS(7,8) float4 pos : SV_POSITION; // UnityCG macro specified name. Accurately "positionCS" UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO diff --git a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_define.hlsl b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_define.hlsl index 52dc4e9ea..4c1eac67a 100644 --- a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_define.hlsl +++ b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_define.hlsl @@ -1,6 +1,10 @@ #ifndef VRMC_MATERIALS_MTOON_DEFINE_INCLUDED #define VRMC_MATERIALS_MTOON_DEFINE_INCLUDED +#ifndef UNITY_SAMPLE_TEX2D_LOD + #define UNITY_SAMPLE_TEX2D_LOD(tex,coord,lod) tex.SampleLevel (sampler##tex,coord,lod) +#endif + // Compile-time constant inline bool MToon_IsForwardBasePass() { @@ -14,6 +18,16 @@ inline bool MToon_IsForwardBasePass() #endif } +// Compile-time constant +inline bool MToon_IsOutlinePass() +{ +#if defined(MTOON_PASS_OUTLINE) + return true; +#else + return false; +#endif +} + // Compile-time constant inline bool MToon_IsUvAnimationOn() { @@ -34,4 +48,24 @@ inline bool MToon_IsNormalMapOn() #endif } +// Compile-time constant +inline bool MToon_IsOutlineModeWorldCoordinates() +{ + #if defined(MTOON_OUTLINE_WIDTH_WORLD) + return true; +#else + return false; +#endif +} + +// Compile-time constant +inline bool MToon_IsOutlineModeScreenCoordinates() +{ + #if defined(MTOON_OUTLINE_WIDTH_SCREEN) + return true; +#else + return false; +#endif +} + #endif diff --git a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_forward_fragment.hlsl b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_forward_fragment.hlsl index bf01828ef..5d9dc4a57 100644 --- a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_forward_fragment.hlsl +++ b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_forward_fragment.hlsl @@ -45,6 +45,7 @@ half4 MToonFragment(const Varyings input) : SV_Target mtoonInput.viewDirWS = input.viewDirWS; mtoonInput.litColor = litColor.rgb; mtoonInput.alpha = alpha; + mtoonInput.outlineFactor = input.outlineFactor; const half4 col = GetMToonLighting(unityLighting, mtoonInput); UNITY_APPLY_FOG(i.fogCoord, col); diff --git a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_forward_vertex.hlsl b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_forward_vertex.hlsl index 15b597141..232495023 100644 --- a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_forward_vertex.hlsl +++ b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_forward_vertex.hlsl @@ -3,9 +3,11 @@ #include #include +#include "./vrmc_materials_mtoon_define.hlsl" #include "./vrmc_materials_mtoon_utility.hlsl" #include "./vrmc_materials_mtoon_input.hlsl" #include "./vrmc_materials_mtoon_attribute.hlsl" +#include "./vrmc_materials_mtoon_geometry_vertex.hlsl" Varyings MToonVertex(const Attributes v) // v is UnityCG macro specified name. { @@ -15,18 +17,31 @@ Varyings MToonVertex(const Attributes v) // v is UnityCG macro specified name. UNITY_TRANSFER_INSTANCE_ID(v, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - output.pos = UnityObjectToClipPos(v.vertex); - output.positionWS = mul(unity_ObjectToWorld, v.vertex); output.uv = TRANSFORM_TEX(v.texcoord0, _MainTex); + output.viewDirWS = MToon_GetWorldSpaceNormalizedViewDir(output.positionWS); + + if (MToon_IsOutlinePass()) + { + output.normalWS = UnityObjectToWorldNormal(-v.normalOS); + const VertexPositionInfo position = MToon_GetOutlineVertex(v.vertex.xyz, normalize(v.normalOS), output.uv); + output.pos = position.positionCS; + output.positionWS = position.positionWS; + output.outlineFactor = 1; + } + else + { + output.normalWS = UnityObjectToWorldNormal(v.normalOS); + const VertexPositionInfo position = MToon_GetVertex(v.vertex.xyz); + output.pos = position.positionCS; + output.positionWS = position.positionWS; + output.outlineFactor = 0; + } - output.normalWS = UnityObjectToWorldNormal(v.normalOS); #if defined(_NORMALMAP) const half tangentSign = v.tangentOS.w * unity_WorldTransformParams.w; output.tangentWS = half4(UnityObjectToWorldDir(v.tangentOS), tangentSign); #endif - output.viewDirWS = MToon_GetWorldSpaceNormalizedViewDir(output.positionWS); - UNITY_TRANSFER_FOG(output, output.positionWS); UNITY_TRANSFER_LIGHTING(output, v.texcoord1.xy); diff --git a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl new file mode 100644 index 000000000..dad41bfcc --- /dev/null +++ b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl @@ -0,0 +1,66 @@ +#ifndef VRMC_MATERIALS_MTOON_GEOMETRY_VERTEX_INCLUDED +#define VRMC_MATERIALS_MTOON_GEOMETRY_VERTEX_INCLUDED + +#include +#include "./vrmc_materials_mtoon_define.hlsl" +#include "./vrmc_materials_mtoon_utility.hlsl" +#include "./vrmc_materials_mtoon_input.hlsl" + +struct VertexPositionInfo +{ + float4 positionWS; + float4 positionCS; +}; + +inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const half3 normalOS, const float2 uv) +{ + if (MToon_IsOutlineModeWorldCoordinates()) + { + const float3 positionWS = mul(unity_ObjectToWorld, float4(positionOS, 1)).xyz; + const half outlineWidth = _OutlineWidth * UNITY_SAMPLE_TEX2D_LOD(_OutlineWidthTex, uv, 0); + const half3 normalWS = UnityObjectToWorldNormal(normalOS); + + VertexPositionInfo output; + output.positionWS = float4(positionWS + normalWS * outlineWidth, 1); + output.positionCS = UnityWorldToClipPos(output.positionWS); + return output; + } + else if (MToon_IsOutlineModeScreenCoordinates()) + { + const float3 positionWS = mul(unity_ObjectToWorld, float4(positionOS, 1)).xyz; + const half outlineWidth = _OutlineWidth * UNITY_SAMPLE_TEX2D_LOD(_OutlineWidthTex, uv, 0); + + const float4 nearUpperRight = mul(unity_CameraInvProjection, float4(1, 1, UNITY_NEAR_CLIP_VALUE, _ProjectionParams.y)); + const half aspect = abs(nearUpperRight.y / nearUpperRight.x); + + float4 positionCS = UnityObjectToClipPos(positionOS); + const half3 normalVS = MToon_GetObjectToViewNormal(normalOS); + const half3 normalCS = TransformViewToProjection(normalVS.xyz); + half2 normalProjectedCS = normalize(normalCS.xy); + normalProjectedCS *= positionCS.w; + normalProjectedCS.x *= aspect; + positionCS.xy += outlineWidth * normalProjectedCS.xy * saturate(1 - abs(normalVS.z)); // ignore offset when normal toward camera + + VertexPositionInfo output; + output.positionWS = float4(positionWS, 1); + output.positionCS = positionCS; + return output; + } + else + { + VertexPositionInfo output; + output.positionWS = mul(unity_ObjectToWorld, float4(positionOS, 1)); + output.positionCS = UnityWorldToClipPos(output.positionWS); + return output; + } +} + +inline VertexPositionInfo MToon_GetVertex(const float3 positionOS) +{ + VertexPositionInfo output; + output.positionWS = mul(unity_ObjectToWorld, float4(positionOS, 1)); + output.positionCS = UnityWorldToClipPos(output.positionWS); + return output; +} + +#endif diff --git a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl.meta b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl.meta new file mode 100644 index 000000000..c11dec7d6 --- /dev/null +++ b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 92e89e208e604f28acdce8a142d1e241 +timeCreated: 1622805067 \ No newline at end of file diff --git a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_lighting_mtoon.hlsl b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_lighting_mtoon.hlsl index c487ce1bd..aa97eaa13 100644 --- a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_lighting_mtoon.hlsl +++ b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_lighting_mtoon.hlsl @@ -14,6 +14,7 @@ struct MToonInput half3 viewDirWS; half3 litColor; half alpha; + half outlineFactor; }; inline half GetMToonLighting_Reflectance(const UnityLighting lighting, const MToonInput input) @@ -91,12 +92,13 @@ half4 GetMToonLighting(const UnityLighting unityLight, const MToonInput input) const half3 direct = GetMToonLighting_DirectLighting(unityLight, input, reflectance); const half3 indirect = GetMToonLighting_GlobalIllumination(unityLight, input); const half3 lighting = direct + indirect; - const half3 emissive = GetMToonLighting_Emissive(input); - const half3 rim = GetMToonLighting_Rim(input, lighting); - const half3 col = lighting + emissive + rim; + const half3 baseCol = lighting + emissive + rim; + const half3 outlineCol = _OutlineColor.rgb * lerp(half3(1, 1, 1), baseCol, _OutlineLightingMix); + + const half3 col = lerp(baseCol, outlineCol, input.outlineFactor); return half4(col, input.alpha); } diff --git a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_utility.hlsl b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_utility.hlsl index 98b994edc..080df8451 100644 --- a/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_utility.hlsl +++ b/Assets/VRMShaders/VRM10/MToon10/Resources/VRM10/vrmc_materials_mtoon_utility.hlsl @@ -39,4 +39,9 @@ inline half3x3 MToon_GetTangentToWorld(const half3 normalWS, const half4 tangent return half3x3(normalizedTangentWS, normalizedBitangentWS, normalizedNormalWS); } +inline half3 MToon_GetObjectToViewNormal(const half3 normalOS) +{ + return normalize(mul((half3x3)UNITY_MATRIX_IT_MV, normalOS)); +} + #endif