add outline pass

This commit is contained in:
Masataka SUMI 2021-06-04 21:21:04 +09:00
parent 598e3d7013
commit c81e4c275a
9 changed files with 175 additions and 11 deletions

View File

@ -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
{

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -3,9 +3,11 @@
#include <UnityCG.cginc>
#include <AutoLight.cginc>
#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);

View File

@ -0,0 +1,66 @@
#ifndef VRMC_MATERIALS_MTOON_GEOMETRY_VERTEX_INCLUDED
#define VRMC_MATERIALS_MTOON_GEOMETRY_VERTEX_INCLUDED
#include <UnityCG.cginc>
#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

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 92e89e208e604f28acdce8a142d1e241
timeCreated: 1622805067

View File

@ -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);
}

View File

@ -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