From 2c5c5453b37126cad8587577ca1d38a7b605f1ad Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Thu, 2 Dec 2021 22:55:13 +0900 Subject: [PATCH 1/7] =?UTF-8?q?=E9=AB=98=20FoV=20=E3=82=AB=E3=83=A1?= =?UTF-8?q?=E3=83=A9=E3=81=A7=E3=81=AE=20MToon10=20=E3=82=B7=E3=82=A7?= =?UTF-8?q?=E3=83=BC=E3=83=80=E3=81=AE=E8=BC=AA=E9=83=AD=E7=B7=9A=E3=81=AE?= =?UTF-8?q?=E8=A6=8B=E6=A0=84=E3=81=88=E3=82=92=E8=89=AF=E3=81=8F=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vrmc_materials_mtoon_geometry_vertex.hlsl | 28 ++++++++++++++++--- .../VRM10/vrmc_materials_mtoon_utility.hlsl | 19 +++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) 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 index 6bbec95c2..f1dc861e9 100644 --- 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 @@ -26,14 +26,23 @@ inline half MToon_GetOutlineVertex_OutlineWidth(const float2 uv) inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const half3 normalOS, const float2 uv) { + const float minWidthInPixel = 1.5f; + if (MToon_IsOutlineModeWorldCoordinates()) { const float3 positionWS = mul(unity_ObjectToWorld, float4(positionOS, 1)).xyz; - const half outlineWidth = MToon_GetOutlineVertex_OutlineWidth(uv); const half3 normalWS = UnityObjectToWorldNormal(normalOS); + const half outlineWidth = MToon_GetOutlineVertex_OutlineWidth(uv); + + const float viewDirWS = length(MToon_GetWorldSpaceViewDir(positionWS)); + const float tangentHalfVerticalFov = 1.0f / unity_CameraProjection[1][1]; + const float onePixelWidth = tangentHalfVerticalFov * viewDirWS * 2.0f / _ScreenParams.y; + // NOTE: 線幅が World Space で一定なので、カメラから離れるとすぐに 1 pixel 未満になりエリアシングしてしまう. + // よって 1.5 pixel 未満から徐々に輪郭線を細くし、1 pixel 未満では幅ゼロにする. + const float antiAliasingOutlineWidth = mtoon_linearstep(onePixelWidth, onePixelWidth * minWidthInPixel, outlineWidth) * outlineWidth; VertexPositionInfo output; - output.positionWS = float4(positionWS + normalWS * outlineWidth, 1); + output.positionWS = float4(positionWS + normalWS * antiAliasingOutlineWidth, 1); output.positionCS = UnityWorldToClipPos(output.positionWS); return output; } @@ -48,10 +57,21 @@ inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const float4 positionCS = UnityObjectToClipPos(positionOS); const half3 normalVS = MToon_GetObjectToViewNormal(normalOS); const half3 normalCS = TransformViewToProjection(normalVS.xyz); + + const float onePixelMultiplier = positionCS.w * 2.0f / _ScreenParams.y; + const float oneMeter = 1.0f; + half2 normalProjectedCS = normalize(normalCS.xy); - normalProjectedCS *= positionCS.w; + // NOTE: VR などの高視野角カメラでは、純粋な実装では太くなりすぎる. + // よって 1m 以上離れたら、それ以上太くならないようにする. + // また、World Coords 輪郭線と同様のエリアシング対策もする. + const half multiplier = outlineWidth * min(positionCS.w, oneMeter); + const half antiAliasingMultiplier = mtoon_linearstep(onePixelMultiplier, onePixelMultiplier * minWidthInPixel, multiplier) * multiplier; + normalProjectedCS *= antiAliasingMultiplier; normalProjectedCS.x *= aspect; - positionCS.xy += outlineWidth * normalProjectedCS.xy * saturate(1 - abs(normalVS.z)); // ignore offset when normal toward camera + // NOTE: カメラ方向軸を向く法線を持つ頂点が XY 方向にだけずれると困るので、それを抑制する. + normalProjectedCS.xy *= saturate(1 - normalVS.z * normalVS.z); + positionCS.xy += normalProjectedCS.xy; VertexPositionInfo output; output.positionWS = float4(positionWS, 1); 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 080df8451..bd1d91262 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 @@ -7,6 +7,11 @@ static const float PI_2 = 6.28318530718; static const float EPS_COL = 0.00001; +inline half mtoon_linearstep(const half start, const half end, const half t) +{ + return min(max((t - start) / (end - start), 0.0), 1.0); +} + inline half3 mtoon_linearstep(const half3 start, const half3 end, const half t) { return min(max((t - start) / (end - start), 0.0), 1.0); @@ -17,6 +22,20 @@ inline bool MToon_IsPerspective() return unity_OrthoParams.w != 1.0; } +inline float3 MToon_GetWorldSpaceViewDir(const float3 positionWS) +{ + if (MToon_IsPerspective()) + { + return _WorldSpaceCameraPos.xyz - positionWS; + } + else + { + const float3 cameraForwardWS = normalize(UNITY_MATRIX_V[2].xyz); + const float3 viewDirWS = _WorldSpaceCameraPos.xyz - positionWS; + return cameraForwardWS * dot(cameraForwardWS, viewDirWS); + } +} + inline float3 MToon_GetWorldSpaceNormalizedViewDir(const float3 positionWS) { if (MToon_IsPerspective()) From c2c394800a3beaba4caecb581e3397acb31ac368 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Thu, 2 Dec 2021 23:02:36 +0900 Subject: [PATCH 2/7] rename --- .../Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index f1dc861e9..fdac157d1 100644 --- 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 @@ -59,13 +59,13 @@ inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const const half3 normalCS = TransformViewToProjection(normalVS.xyz); const float onePixelMultiplier = positionCS.w * 2.0f / _ScreenParams.y; - const float oneMeter = 1.0f; + const float widthScaledMaxMeter = 1.0f; half2 normalProjectedCS = normalize(normalCS.xy); // NOTE: VR などの高視野角カメラでは、純粋な実装では太くなりすぎる. // よって 1m 以上離れたら、それ以上太くならないようにする. // また、World Coords 輪郭線と同様のエリアシング対策もする. - const half multiplier = outlineWidth * min(positionCS.w, oneMeter); + const half multiplier = outlineWidth * min(positionCS.w, widthScaledMaxMeter); const half antiAliasingMultiplier = mtoon_linearstep(onePixelMultiplier, onePixelMultiplier * minWidthInPixel, multiplier) * multiplier; normalProjectedCS *= antiAliasingMultiplier; normalProjectedCS.x *= aspect; From 6c14b619fc3c0e61fca2c366682641b2ba5f490e Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Thu, 2 Dec 2021 23:10:58 +0900 Subject: [PATCH 3/7] =?UTF-8?q?=E3=82=A2=E3=83=B3=E3=83=81=E3=82=A8?= =?UTF-8?q?=E3=83=AA=E3=82=A2=E3=82=B7=E3=83=B3=E3=82=B0=E5=AF=BE=E7=AD=96?= =?UTF-8?q?=E3=81=AF=E3=81=97=E3=81=AA=E3=81=84=E3=80=82=20=E3=81=8A?= =?UTF-8?q?=E3=81=9D=E3=82=89=E3=81=8FMToon=20=E3=81=AB=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=81=8C=E3=81=82=E3=82=8B=E3=82=8F=E3=81=91=E3=81=A7=E3=81=AF?= =?UTF-8?q?=E3=81=AA=E3=81=8F=E3=80=81=E5=8D=98=E3=81=AB=20MSAA=20?= =?UTF-8?q?=E3=82=92=E3=81=8B=E3=81=91=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=80=81=E3=81=AA=E3=81=A9=E3=81=8C=E8=80=83=E3=81=88=E3=82=89?= =?UTF-8?q?=E3=82=8C=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vrmc_materials_mtoon_geometry_vertex.hlsl | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) 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 index fdac157d1..d914ac1da 100644 --- 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 @@ -34,15 +34,8 @@ inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const const half3 normalWS = UnityObjectToWorldNormal(normalOS); const half outlineWidth = MToon_GetOutlineVertex_OutlineWidth(uv); - const float viewDirWS = length(MToon_GetWorldSpaceViewDir(positionWS)); - const float tangentHalfVerticalFov = 1.0f / unity_CameraProjection[1][1]; - const float onePixelWidth = tangentHalfVerticalFov * viewDirWS * 2.0f / _ScreenParams.y; - // NOTE: 線幅が World Space で一定なので、カメラから離れるとすぐに 1 pixel 未満になりエリアシングしてしまう. - // よって 1.5 pixel 未満から徐々に輪郭線を細くし、1 pixel 未満では幅ゼロにする. - const float antiAliasingOutlineWidth = mtoon_linearstep(onePixelWidth, onePixelWidth * minWidthInPixel, outlineWidth) * outlineWidth; - VertexPositionInfo output; - output.positionWS = float4(positionWS + normalWS * antiAliasingOutlineWidth, 1); + output.positionWS = float4(positionWS + normalWS * outlineWidth, 1); output.positionCS = UnityWorldToClipPos(output.positionWS); return output; } @@ -64,10 +57,8 @@ inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const half2 normalProjectedCS = normalize(normalCS.xy); // NOTE: VR などの高視野角カメラでは、純粋な実装では太くなりすぎる. // よって 1m 以上離れたら、それ以上太くならないようにする. - // また、World Coords 輪郭線と同様のエリアシング対策もする. - const half multiplier = outlineWidth * min(positionCS.w, widthScaledMaxMeter); - const half antiAliasingMultiplier = mtoon_linearstep(onePixelMultiplier, onePixelMultiplier * minWidthInPixel, multiplier) * multiplier; - normalProjectedCS *= antiAliasingMultiplier; + const half outlineWidthMultiplier = outlineWidth * min(positionCS.w, widthScaledMaxMeter); + normalProjectedCS *= outlineWidthMultiplier; normalProjectedCS.x *= aspect; // NOTE: カメラ方向軸を向く法線を持つ頂点が XY 方向にだけずれると困るので、それを抑制する. normalProjectedCS.xy *= saturate(1 - normalVS.z * normalVS.z); From 536ff33d6ad4bdbf9ee53910c37ddcc4597047f3 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Thu, 2 Dec 2021 23:13:42 +0900 Subject: [PATCH 4/7] =?UTF-8?q?=E6=B6=88=E3=81=97=E5=BF=98=E3=82=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl | 4 ---- 1 file changed, 4 deletions(-) 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 index d914ac1da..44dac0c9b 100644 --- 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 @@ -26,8 +26,6 @@ inline half MToon_GetOutlineVertex_OutlineWidth(const float2 uv) inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const half3 normalOS, const float2 uv) { - const float minWidthInPixel = 1.5f; - if (MToon_IsOutlineModeWorldCoordinates()) { const float3 positionWS = mul(unity_ObjectToWorld, float4(positionOS, 1)).xyz; @@ -51,9 +49,7 @@ inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const const half3 normalVS = MToon_GetObjectToViewNormal(normalOS); const half3 normalCS = TransformViewToProjection(normalVS.xyz); - const float onePixelMultiplier = positionCS.w * 2.0f / _ScreenParams.y; const float widthScaledMaxMeter = 1.0f; - half2 normalProjectedCS = normalize(normalCS.xy); // NOTE: VR などの高視野角カメラでは、純粋な実装では太くなりすぎる. // よって 1m 以上離れたら、それ以上太くならないようにする. From 51893ebe4ec2b695376ffdc954b2dce617205f8c Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Thu, 2 Dec 2021 23:28:56 +0900 Subject: [PATCH 5/7] =?UTF-8?q?Screen=20=E5=BA=A7=E6=A8=99=E7=B3=BB?= =?UTF-8?q?=E3=81=AE=E7=B7=9A=E5=B9=85=E3=81=AE=E3=83=9E=E3=82=A4=E3=82=B0?= =?UTF-8?q?=E3=83=AC=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=83=9F=E3=82=B9?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/Migration/Materials/MigrationMToonMaterial.cs | 4 +++- .../Resources/VRM10/vrmc_materials_mtoon_geometry_vertex.hlsl | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Assets/VRM10/Runtime/Migration/Materials/MigrationMToonMaterial.cs b/Assets/VRM10/Runtime/Migration/Materials/MigrationMToonMaterial.cs index d14bd3c65..8068dd0f3 100644 --- a/Assets/VRM10/Runtime/Migration/Materials/MigrationMToonMaterial.cs +++ b/Assets/VRM10/Runtime/Migration/Materials/MigrationMToonMaterial.cs @@ -298,7 +298,9 @@ namespace UniVRM10 break; case OutlineWidthMode.ScreenCoordinates: dst.OutlineWidthMode = UniGLTF.Extensions.VRMC_materials_mtoon.OutlineWidthMode.screenCoordinates; - dst.OutlineWidthFactor = mtoon.Definition.Outline.OutlineWidthValue * oneHundredth; + // NOTE: 従来は、縦幅の半分を 100% としたときの % の値だった。 + // 1.0 では縦幅を 1 としたときの値とするので、 1/200 する。 + dst.OutlineWidthFactor = mtoon.Definition.Outline.OutlineWidthValue * oneHundredth * 0.5f; break; default: throw new ArgumentOutOfRangeException($"OutlineWidthMode: {(int)mtoon.Definition.Outline.OutlineWidthMode}"); 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 index 44dac0c9b..77dbc0167 100644 --- 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 @@ -49,12 +49,14 @@ inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const const half3 normalVS = MToon_GetObjectToViewNormal(normalOS); const half3 normalCS = TransformViewToProjection(normalVS.xyz); + const float clipSpaceHeight = 2.0f; const float widthScaledMaxMeter = 1.0f; + half2 normalProjectedCS = normalize(normalCS.xy); // NOTE: VR などの高視野角カメラでは、純粋な実装では太くなりすぎる. // よって 1m 以上離れたら、それ以上太くならないようにする. const half outlineWidthMultiplier = outlineWidth * min(positionCS.w, widthScaledMaxMeter); - normalProjectedCS *= outlineWidthMultiplier; + normalProjectedCS *= clipSpaceHeight * outlineWidthMultiplier; normalProjectedCS.x *= aspect; // NOTE: カメラ方向軸を向く法線を持つ頂点が XY 方向にだけずれると困るので、それを抑制する. normalProjectedCS.xy *= saturate(1 - normalVS.z * normalVS.z); From 02e7742c0f394cb08aab0e1bd86caf9df831481a Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Thu, 2 Dec 2021 23:51:46 +0900 Subject: [PATCH 6/7] =?UTF-8?q?=E8=A6=96=E9=8C=90=E5=8F=B0=E5=B9=B3?= =?UTF-8?q?=E9=9D=A2=E3=81=AE=E9=AB=98=E3=81=95=E3=82=92=E7=94=A8=E3=81=84?= =?UTF-8?q?=E3=81=A6=E3=80=81FoV=20=E3=81=A8=E8=B7=9D=E9=9B=A2=E3=81=AB?= =?UTF-8?q?=E5=BF=9C=E3=81=98=E3=81=A6=E3=82=B9=E3=82=B1=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E5=80=A4=E3=81=8C=E3=81=84=E3=81=84=E6=84=9F=E3=81=98=E3=81=AB?= =?UTF-8?q?=E3=81=AA=E3=82=8B=20Screen=20=E5=BA=A7=E6=A8=99=E7=B3=BB?= =?UTF-8?q?=E8=BC=AA=E9=83=AD=E7=B7=9A=E3=81=AE=E3=82=A2=E3=83=AB=E3=82=B4?= =?UTF-8?q?=E3=83=AA=E3=82=BA=E3=83=A0=E3=82=92=E5=B0=8E=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vrmc_materials_mtoon_geometry_vertex.hlsl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) 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 index 77dbc0167..af5180181 100644 --- 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 @@ -49,13 +49,17 @@ inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const const half3 normalVS = MToon_GetObjectToViewNormal(normalOS); const half3 normalCS = TransformViewToProjection(normalVS.xyz); - const float clipSpaceHeight = 2.0f; - const float widthScaledMaxMeter = 1.0f; + const float maxViewFrustumPlaneHeight = 2.0f; + const float invTangentHalfVerticalFov = unity_CameraProjection[1][1]; + // NOTE: viewFrustumPlaneHeight = tan(halfFov) * viewDirDistance * 2.0 + // -> viewDirDistance = viewFrustumPlaneHeight / (tan(halfFov) * 2.0) + const float widthScaledMaxMeter = maxViewFrustumPlaneHeight * invTangentHalfVerticalFov * 0.5f; + // NOTE: VR などの高視野角カメラでは、純粋な実装では太くなりすぎる. + // よってある距離での視錐台平面が高さ 2m 以上になったらスケールをやめる. + const half outlineWidthMultiplier = outlineWidth * min(positionCS.w, widthScaledMaxMeter); half2 normalProjectedCS = normalize(normalCS.xy); - // NOTE: VR などの高視野角カメラでは、純粋な実装では太くなりすぎる. - // よって 1m 以上離れたら、それ以上太くならないようにする. - const half outlineWidthMultiplier = outlineWidth * min(positionCS.w, widthScaledMaxMeter); + const float clipSpaceHeight = 2.0f; normalProjectedCS *= clipSpaceHeight * outlineWidthMultiplier; normalProjectedCS.x *= aspect; // NOTE: カメラ方向軸を向く法線を持つ頂点が XY 方向にだけずれると困るので、それを抑制する. From 0896670e75ddc4400a1bdbe38cbec9f63c08d161 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Fri, 3 Dec 2021 01:09:53 +0900 Subject: [PATCH 7/7] =?UTF-8?q?=E4=BB=95=E6=A7=98=E5=A4=96=E5=AE=9F?= =?UTF-8?q?=E8=A3=85=E3=81=A7=E3=81=82=E3=82=8B=E3=81=93=E3=81=A8=E3=82=92?= =?UTF-8?q?=E6=98=8E=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VRM10/vrmc_materials_mtoon_define.hlsl | 10 ++++++ .../vrmc_materials_mtoon_geometry_vertex.hlsl | 36 ++++++++++++------- 2 files changed, 33 insertions(+), 13 deletions(-) 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 cec236313..909079822 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 @@ -138,4 +138,14 @@ inline bool MToon_IsOutlineModeDisabled() #endif } +// Compile-time constant +inline bool MToon_UseStrictMode() +{ + #if defined(_MTOON_USE_STRICT_MODE) + return true; +#else + return false; +#endif +} + #endif 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 index af5180181..6ee24dbde 100644 --- 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 @@ -24,6 +24,26 @@ inline half MToon_GetOutlineVertex_OutlineWidth(const float2 uv) } } +inline float MToon_GetOutlineVertex_ScreenCoordinatesWidthMultiplier(const float4 positionCS) +{ + // NOTE: VRM 1.0 の仕様にはない実装なので、ユーザが任意で機能を外せるようにする. + if (MToon_UseStrictMode()) + { + return 1.0f; + } + else + { + const float maxViewFrustumPlaneHeight = 2.0f; + const float invTangentHalfVerticalFov = unity_CameraProjection[1][1]; + // NOTE: viewFrustumPlaneHeight = tan(halfFov) * viewDirDistance * 2.0 + // -> viewDirDistance = viewFrustumPlaneHeight / (tan(halfFov) * 2.0) + const float widthScaledMaxDistance = maxViewFrustumPlaneHeight * invTangentHalfVerticalFov * 0.5f; + // NOTE: VR などの高視野角カメラでは、純粋な実装では太くなりすぎる. + // よってある距離での視錐台平面が高さ 2m 以上になったらスケールをやめる. + return min(positionCS.w, widthScaledMaxDistance); + } +} + inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const half3 normalOS, const float2 uv) { if (MToon_IsOutlineModeWorldCoordinates()) @@ -45,30 +65,20 @@ inline VertexPositionInfo MToon_GetOutlineVertex(const float3 positionOS, const 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 float4 positionCS = UnityObjectToClipPos(positionOS); const half3 normalVS = MToon_GetObjectToViewNormal(normalOS); const half3 normalCS = TransformViewToProjection(normalVS.xyz); - const float maxViewFrustumPlaneHeight = 2.0f; - const float invTangentHalfVerticalFov = unity_CameraProjection[1][1]; - // NOTE: viewFrustumPlaneHeight = tan(halfFov) * viewDirDistance * 2.0 - // -> viewDirDistance = viewFrustumPlaneHeight / (tan(halfFov) * 2.0) - const float widthScaledMaxMeter = maxViewFrustumPlaneHeight * invTangentHalfVerticalFov * 0.5f; - // NOTE: VR などの高視野角カメラでは、純粋な実装では太くなりすぎる. - // よってある距離での視錐台平面が高さ 2m 以上になったらスケールをやめる. - const half outlineWidthMultiplier = outlineWidth * min(positionCS.w, widthScaledMaxMeter); - half2 normalProjectedCS = normalize(normalCS.xy); const float clipSpaceHeight = 2.0f; - normalProjectedCS *= clipSpaceHeight * outlineWidthMultiplier; + normalProjectedCS *= clipSpaceHeight * outlineWidth * MToon_GetOutlineVertex_ScreenCoordinatesWidthMultiplier(positionCS); normalProjectedCS.x *= aspect; // NOTE: カメラ方向軸を向く法線を持つ頂点が XY 方向にだけずれると困るので、それを抑制する. normalProjectedCS.xy *= saturate(1 - normalVS.z * normalVS.z); - positionCS.xy += normalProjectedCS.xy; VertexPositionInfo output; output.positionWS = float4(positionWS, 1); - output.positionCS = positionCS; + output.positionCS = float4(positionCS.xy + normalProjectedCS.xy, positionCS.zw); return output; } else