summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Editor/tooner.cs28
-rw-r--r--feature_macros.cginc2
-rw-r--r--globals.cginc12
-rw-r--r--tooner.shader8
-rw-r--r--tooner_lighting.cginc133
5 files changed, 148 insertions, 35 deletions
diff --git a/Editor/tooner.cs b/Editor/tooner.cs
index 4e96e61..4d96d76 100644
--- a/Editor/tooner.cs
+++ b/Editor/tooner.cs
@@ -480,6 +480,11 @@ public class ToonerGUI : ShaderGUI {
bc,
"Matcap strength");
+ bc = FindProperty($"_Matcap{i}MixFactor");
+ editor.RangeProperty(
+ bc,
+ "Mix factor");
+
bc = FindProperty($"_Matcap{i}Emission");
editor.FloatProperty(
bc,
@@ -490,6 +495,29 @@ public class ToonerGUI : ShaderGUI {
bc,
"Quantization");
+ bc = FindProperty($"_Matcap{i}Normal_Enabled");
+ enabled = bc.floatValue > 1E-6;
+ EditorGUI.BeginChangeCheck();
+ enabled = EditorGUILayout.Toggle("Replace normals", enabled);
+ EditorGUI.EndChangeCheck();
+ bc.floatValue = enabled ? 1.0f : 0.0f;
+ SetKeyword($"_MATCAP{i}_NORMAL", enabled);
+
+ if (enabled) {
+ EditorGUI.indentLevel += 1;
+ bc = FindProperty($"_Matcap{i}Normal");
+ editor.TexturePropertySingleLine(
+ MakeLabel(bc, "Normal map"),
+ bc);
+ if (bc.textureValue) {
+ editor.TextureScaleOffsetProperty(bc);
+
+ bc = FindProperty($"_Matcap{i}Normal_Str");
+ editor.RangeProperty(bc, "Strength");
+ }
+ EditorGUI.indentLevel -= 1;
+ }
+
bc = FindProperty($"_Matcap{i}Distortion0");
enabled = bc.floatValue > 1E-6;
EditorGUI.BeginChangeCheck();
diff --git a/feature_macros.cginc b/feature_macros.cginc
index 29d3859..bdc1369 100644
--- a/feature_macros.cginc
+++ b/feature_macros.cginc
@@ -20,9 +20,11 @@
#pragma shader_feature_local _ _MATCAP0
#pragma shader_feature_local _ _MATCAP0_MASK
#pragma shader_feature_local _ _MATCAP0_MASK2
+#pragma shader_feature_local _ _MATCAP0_NORMAL
#pragma shader_feature_local _ _MATCAP1
#pragma shader_feature_local _ _MATCAP1_MASK
#pragma shader_feature_local _ _MATCAP1_MASK2
+#pragma shader_feature_local _ _MATCAP1_NORMAL
#pragma shader_feature_local _ _RIM_LIGHTING0
#pragma shader_feature_local _ _RIM_LIGHTING0_MASK
#pragma shader_feature_local _ _RIM_LIGHTING0_GLITTER
diff --git a/globals.cginc b/globals.cginc
index d77b5e9..4bedf19 100644
--- a/globals.cginc
+++ b/globals.cginc
@@ -305,9 +305,15 @@ float _Matcap0_Mask_Invert;
texture2D _Matcap0_Mask2;
float _Matcap0_Mask2_Invert;
float _Matcap0Str;
+float _Matcap0MixFactor;
float _Matcap0Quantization;
float _Matcap0Mode;
float _Matcap0Emission;
+#if defined(_MATCAP0_NORMAL)
+texture2D _Matcap0Normal;
+float4 _Matcap0Normal_ST;
+float _Matcap0Normal_Str;
+#endif
#endif
#if defined(_MATCAP1)
@@ -318,9 +324,15 @@ float _Matcap1_Mask_Invert;
texture2D _Matcap1_Mask2;
float _Matcap1_Mask2_Invert;
float _Matcap1Str;
+float _Matcap1MixFactor;
float _Matcap1Quantization;
float _Matcap1Mode;
float _Matcap1Emission;
+#if defined(_MATCAP1_NORMAL)
+texture2D _Matcap1Normal;
+float4 _Matcap1Normal_ST;
+float _Matcap1Normal_Str;
+#endif
#endif
#if defined(_RIM_LIGHTING0)
diff --git a/tooner.shader b/tooner.shader
index 01f50d1..7fb8751 100644
--- a/tooner.shader
+++ b/tooner.shader
@@ -218,9 +218,13 @@ Shader "yum_food/tooner"
_Matcap0_Mask2_Invert("Invert mask", Float) = 0.0
_Matcap0Mode("Matcap mode", Float) = 0
_Matcap0Str("Matcap strength", Float) = 1
+ _Matcap0MixFactor("Matcap mix factor", Range(0, 1)) = 1
_Matcap0Emission("Matcap emission", Float) = 0
_Matcap0Quantization("Matcap quantization", Float) = -1
_Matcap0Distortion0("Matcap distortion0", Float) = 0
+ _Matcap0Normal_Enabled("Enable normal replacement", Float) = 0
+ _Matcap0Normal("Matcap normals", 2D) = "bump" {}
+ _Matcap0Normal_Str("Matcap normals", Range(0, 10)) = 1
_Matcap1("Matcap", 2D) = "black" {}
_Matcap1_Mask("Matcap mask", 2D) = "white" {}
@@ -229,9 +233,13 @@ Shader "yum_food/tooner"
_Matcap1_Mask2_Invert("Invert mask", Float) = 0.0
_Matcap1Mode("Matcap mode", Float) = 0
_Matcap1Str("Matcap strength", Float) = 1
+ _Matcap1MixFactor("Matcap mix factor", Range(0, 1)) = 1
_Matcap1Emission("Matcap emission", Float) = 0
_Matcap1Quantization("Matcap quantization", Float) = -1
_Matcap1Distortion0("Matcap distortion0", Float) = 0
+ _Matcap1Normal_Enabled("Enable normal replacement", Float) = 0
+ _Matcap1Normal("Matcap normals", 2D) = "bump" {}
+ _Matcap1Normal_Str("Matcap normals", Range(0, 10)) = 1
_Rim_Lighting0_Enabled("Enable rim lighting", Float) = 0
_Rim_Lighting0_Mode("Rim lighting mode", Float) = 0
diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc
index 1f840b7..10383df 100644
--- a/tooner_lighting.cginc
+++ b/tooner_lighting.cginc
@@ -828,7 +828,8 @@ void applyDecal(inout float4 albedo,
}
void mixOverlayAlbedoRoughnessMetallic(inout float4 albedo,
- inout float roughness, inout float metallic, PbrOverlay ov) {
+ inout float roughness, inout float metallic, PbrOverlay ov,
+ float mask) {
// Calculate alpha masks before we start mutating alpha.
#if defined(_PBR_OVERLAY0)
float a0 = saturate(ov.ov0_albedo.a * _PBR_Overlay0_Alpha_Multiplier);
@@ -837,6 +838,7 @@ void mixOverlayAlbedoRoughnessMetallic(inout float4 albedo,
(albedo.a < _PBR_Overlay0_Constrain_By_Alpha_Max);
a0 *= in_range;
}
+ a0 *= mask;
#endif
#if defined(_PBR_OVERLAY1)
float a1 = saturate(ov.ov1_albedo.a * _PBR_Overlay1_Alpha_Multiplier);
@@ -845,6 +847,7 @@ void mixOverlayAlbedoRoughnessMetallic(inout float4 albedo,
(albedo.a < _PBR_Overlay1_Constrain_By_Alpha_Max);
a1 *= in_range;
}
+ a1 *= mask;
#endif
#if defined(_PBR_OVERLAY2)
float a2 = saturate(ov.ov2_albedo.a * _PBR_Overlay2_Alpha_Multiplier);
@@ -853,6 +856,7 @@ void mixOverlayAlbedoRoughnessMetallic(inout float4 albedo,
(albedo.a < _PBR_Overlay2_Constrain_By_Alpha_Max);
a2 *= in_range;
}
+ a2 *= mask;
#endif
#if defined(_PBR_OVERLAY3)
float a3 = saturate(ov.ov3_albedo.a * _PBR_Overlay3_Alpha_Multiplier);
@@ -861,6 +865,7 @@ void mixOverlayAlbedoRoughnessMetallic(inout float4 albedo,
(albedo.a < _PBR_Overlay3_Constrain_By_Alpha_Max);
a3 *= in_range;
}
+ a3 *= mask;
#endif
#if defined(_PBR_OVERLAY0)
@@ -1068,8 +1073,8 @@ float4 pixellate_color(int2 px_res, float2 uv, float4 c)
float4 effect(inout v2f i)
{
- float iddx = ddx(i.uv0.x) * _Mip_Multiplier;
- float iddy = ddx(i.uv0.y) * _Mip_Multiplier;
+ float iddx = (ddx(i.uv0.x) + ddx(i.uv0.y)) * _Mip_Multiplier;
+ float iddy = (ddy(i.uv0.x) + ddy(i.uv0.y)) * _Mip_Multiplier;
const float3 view_dir = normalize(_WorldSpaceCameraPos - i.worldPos);
// Not necessarily normalized after interpolation.
i.normal = normalize(i.normal);
@@ -1204,35 +1209,25 @@ float4 effect(inout v2f i)
{
const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(normal, 0)));
const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(view_dir, 0)));
- const float3 refl = -reflect(cam_view_dir, cam_normal);
+ const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
float m = 2.0 * sqrt(
- refl.x * refl.x +
- refl.y * refl.y +
- (refl.z + 1) * (refl.z + 1));
- matcap_uv = refl.xy / m + 0.5;
+ cam_refl.x * cam_refl.x +
+ cam_refl.y * cam_refl.y +
+ (cam_refl.z + 1) * (cam_refl.z + 1));
+ matcap_uv = cam_refl.xy / m + 0.5;
matcap_radius = length(matcap_uv - 0.5);
matcap_theta = atan2(matcap_uv.y - 0.5, matcap_uv.x - 0.5);
}
#endif
+ float matcap_overwrite_mask = 0;
#if defined(_MATCAP0) || defined(_MATCAP1)
{
float iddx = ddx(i.uv0.x);
float iddy = ddy(i.uv0.y);
#if defined(_MATCAP0)
{
-#if defined(_MATCAP0_DISTORTION0)
- float2 distort_uv = matcap_distortion0(matcap_uv);
- float2 matcap_uv = distort_uv;
-#endif
- float3 matcap = _Matcap0.SampleGrad(linear_repeat_s, matcap_uv, iddx, iddy) * _Matcap0Str;
-
- float q = _Matcap0Quantization;
- if (q > 0) {
- matcap = ceil(matcap * q) / q;
- }
-
#if defined(_MATCAP0_MASK)
- float4 matcap_mask_raw = _Matcap0_Mask.SampleGrad(linear_repeat_s, i.uv0.xy, iddx, iddy);
+ float4 matcap_mask_raw = _Matcap0_Mask.SampleLevel(linear_repeat_s, i.uv0.xy, 0);
float matcap_mask = matcap_mask_raw.r;
matcap_mask = (bool) round(_Matcap0_Mask_Invert) ? 1 - matcap_mask : matcap_mask;
matcap_mask *= matcap_mask_raw.a;
@@ -1241,13 +1236,50 @@ float4 effect(inout v2f i)
#endif
#if defined(_MATCAP0_MASK2)
{
- float4 matcap_mask2_raw = _Matcap0_Mask2.SampleGrad(linear_repeat_s, i.uv0.xy, iddx, iddy);
+ float4 matcap_mask2_raw = _Matcap0_Mask2.SampleLevel(linear_repeat_s, i.uv0.xy, 0);
float matcap_mask2 = matcap_mask2_raw.r;
matcap_mask2 = (bool) round(_Matcap0_Mask2_Invert) ? 1 - matcap_mask2 : matcap_mask2;
matcap_mask2 *= matcap_mask2_raw.a;
matcap_mask *= matcap_mask2;
}
#endif
+#if defined(_MATCAP0_NORMAL)
+ float3 matcap_normal = UnpackScaleNormal(
+ _Matcap0Normal.SampleGrad(linear_repeat_s,
+ UV_SCOFF(i, _Matcap0Normal_ST, /*uv_channel=*/0),
+ iddx * _Matcap0Normal_ST.x,
+ iddy * _Matcap0Normal_ST.y),
+ _Matcap0Normal_Str);
+ raw_normal = (round(matcap_mask) == 1 ? matcap_normal : raw_normal);
+ normal = float3(
+ raw_normal.x * i.tangent +
+ raw_normal.y * binormal +
+ raw_normal.z * i.normal
+ );
+ {
+ const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(normal, 0)));
+ const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(view_dir, 0)));
+ const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
+ float m = 2.0 * sqrt(
+ cam_refl.x * cam_refl.x +
+ cam_refl.y * cam_refl.y +
+ (cam_refl.z + 1) * (cam_refl.z + 1));
+ matcap_uv = cam_refl.xy / m + 0.5;
+ matcap_radius = length(matcap_uv - 0.5);
+ matcap_theta = atan2(matcap_uv.y - 0.5, matcap_uv.x - 0.5);
+ }
+#endif
+
+#if defined(_MATCAP0_DISTORTION0)
+ float2 distort_uv = matcap_distortion0(matcap_uv);
+ float2 matcap_uv = distort_uv;
+#endif
+ float3 matcap = _Matcap0.SampleGrad(linear_repeat_s, matcap_uv, iddx, iddy) * _Matcap0Str;
+
+ float q = _Matcap0Quantization;
+ if (q > 0) {
+ matcap = ceil(matcap * q) / q;
+ }
int mode = round(_Matcap0Mode);
switch (mode) {
@@ -1260,6 +1292,7 @@ float4 effect(inout v2f i)
albedo.rgb *= lerp(1, matcap, matcap_mask);
break;
case 2:
+ matcap_overwrite_mask = max(matcap_mask, matcap_overwrite_mask);
albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);
matcap_emission = lerp(albedo.rgb, matcap, matcap_mask) * _Matcap0Emission;
break;
@@ -1282,19 +1315,8 @@ float4 effect(inout v2f i)
#endif // _MATCAP0
#if defined(_MATCAP1)
{
-#if defined(_MATCAP1_DISTORTION0)
- float2 distort_uv = matcap_distortion0(matcap_uv);
- float2 matcap_uv = distort_uv;
-#endif
- float3 matcap = _Matcap1.SampleGrad(linear_repeat_s, matcap_uv, iddx, iddy) * _Matcap1Str;
-
- float q = _Matcap1Quantization;
- if (q > 0) {
- matcap = ceil(matcap * q) / q;
- }
-
#if defined(_MATCAP1_MASK)
- float4 matcap_mask_raw = _Matcap1_Mask.SampleGrad(linear_repeat_s, i.uv0.xy, iddx, iddy);
+ float4 matcap_mask_raw = _Matcap1_Mask.SampleLevel(linear_repeat_s, i.uv0.xy, 0);
float matcap_mask = matcap_mask_raw.r;
matcap_mask = (bool) round(_Matcap1_Mask_Invert) ? 1 - matcap_mask : matcap_mask;
matcap_mask *= matcap_mask_raw.a;
@@ -1303,13 +1325,51 @@ float4 effect(inout v2f i)
#endif
#if defined(_MATCAP1_MASK2)
{
- float4 matcap_mask2_raw = _Matcap1_Mask2.SampleGrad(linear_repeat_s, i.uv0.xy, iddx, iddy);
+ float4 matcap_mask2_raw = _Matcap1_Mask2.SampleLevel(linear_repeat_s, i.uv0.xy, 0);
float matcap_mask2 = matcap_mask2_raw.r;
matcap_mask2 = (bool) round(_Matcap1_Mask2_Invert) ? 1 - matcap_mask2 : matcap_mask2;
matcap_mask2 *= matcap_mask2_raw.a;
matcap_mask *= matcap_mask2;
}
#endif
+#if defined(_MATCAP1_NORMAL)
+ float3 matcap_normal = UnpackScaleNormal(
+ _Matcap1Normal.SampleGrad(linear_repeat_s,
+ UV_SCOFF(i, _Matcap1Normal_ST, /*uv_channel=*/0),
+ iddx * _Matcap1Normal_ST.x,
+ iddy * _Matcap1Normal_ST.y),
+ _Matcap1Normal_Str * _Matcap1MixFactor);
+ raw_normal = (round(matcap_mask) == 1 ? matcap_normal : raw_normal);
+ normal = float3(
+ raw_normal.x * i.tangent +
+ raw_normal.y * binormal +
+ raw_normal.z * i.normal
+ );
+ {
+ const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(normal, 0)));
+ const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(view_dir, 0)));
+ const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
+ float m = 2.0 * sqrt(
+ cam_refl.x * cam_refl.x +
+ cam_refl.y * cam_refl.y +
+ (cam_refl.z + 1) * (cam_refl.z + 1));
+ matcap_uv = cam_refl.xy / m + 0.5;
+ matcap_radius = length(matcap_uv - 0.5);
+ matcap_theta = atan2(matcap_uv.y - 0.5, matcap_uv.x - 0.5);
+ }
+#endif
+#if defined(_MATCAP1_DISTORTION0)
+ float2 distort_uv = matcap_distortion0(matcap_uv);
+ float2 matcap_uv = distort_uv;
+#endif
+ float3 matcap = _Matcap1.SampleGrad(linear_repeat_s, matcap_uv, iddx, iddy) * _Matcap1Str;
+
+ float q = _Matcap1Quantization;
+ if (q > 0) {
+ matcap = ceil(matcap * q) / q;
+ }
+
+ matcap_mask *= _Matcap1MixFactor;
int mode = round(_Matcap1Mode);
switch (mode) {
@@ -1322,6 +1382,7 @@ float4 effect(inout v2f i)
albedo.rgb *= lerp(1, matcap, matcap_mask);
break;
case 2:
+ matcap_overwrite_mask = max(matcap_mask, matcap_overwrite_mask);
albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);
matcap_emission = lerp(albedo.rgb, matcap, matcap_mask) * _Matcap1Emission;
break;
@@ -1345,7 +1406,9 @@ float4 effect(inout v2f i)
}
#endif // _MATCAP0 || _MATCAP1
- mixOverlayAlbedoRoughnessMetallic(albedo, roughness, metallic, ov);
+ // TODO get rid of the pow. It's a hack to make matcap replace mode look
+ // better with overlay tattoos.
+ mixOverlayAlbedoRoughnessMetallic(albedo, roughness, metallic, ov, 1 - pow(matcap_overwrite_mask, 4));
#if defined(_DECAL0) || defined(_DECAL1) || defined(_DECAL2) || defined(_DECAL3)
float3 decal_emission = 0;
applyDecal(albedo, roughness, metallic, decal_emission, i);