diff options
| -rw-r--r-- | Editor/tooner.cs | 153 | ||||
| -rw-r--r-- | clones.cginc | 5 | ||||
| -rw-r--r-- | globals.cginc | 31 | ||||
| -rw-r--r-- | interpolators.cginc | 8 | ||||
| -rw-r--r-- | pbr.cginc | 12 | ||||
| -rw-r--r-- | tooner.shader | 55 | ||||
| -rw-r--r-- | tooner_lighting.cginc | 233 | ||||
| -rw-r--r-- | tooner_outline_pass.cginc | 72 |
8 files changed, 360 insertions, 209 deletions
diff --git a/Editor/tooner.cs b/Editor/tooner.cs index 414c1b2..8368b55 100644 --- a/Editor/tooner.cs +++ b/Editor/tooner.cs @@ -224,90 +224,92 @@ public class ToonerGUI : ShaderGUI { } void DoRimLighting() { - GUILayout.Label($"Rim lighting", EditorStyles.boldLabel); - EditorGUI.indentLevel += 1; + for (int i = 0; i < 2; i++) { + GUILayout.Label($"Rim lighting {i}", EditorStyles.boldLabel); + EditorGUI.indentLevel += 1; - MaterialProperty bc; + MaterialProperty bc; - bc = FindProperty("_Rim_Lighting_Enabled"); - bool enabled = bc.floatValue > 1E-6; - EditorGUI.BeginChangeCheck(); - enabled = EditorGUILayout.Toggle("Enable", enabled); - EditorGUI.EndChangeCheck(); - bc.floatValue = enabled ? 1.0f : 0.0f; - SetKeyword($"_RIM_LIGHTING", enabled); + bc = FindProperty($"_Rim_Lighting{i}_Enabled"); + bool enabled = bc.floatValue > 1E-6; + EditorGUI.BeginChangeCheck(); + enabled = EditorGUILayout.Toggle("Enable", enabled); + EditorGUI.EndChangeCheck(); + bc.floatValue = enabled ? 1.0f : 0.0f; + SetKeyword($"_RIM_LIGHTING{i}", enabled); - if (!enabled) { - return; - } + if (!enabled) { + return; + } + + bc = FindProperty($"_Rim_Lighting{i}_Color"); + editor.ColorProperty(bc, "Color (RGB)"); - bc = FindProperty("_Rim_Lighting_Color"); - editor.ColorProperty(bc, "Color (RGB)"); + bc = FindProperty($"_Rim_Lighting{i}_Mask"); + editor.TexturePropertySingleLine( + MakeLabel(bc, "Mask"), + bc); + SetKeyword($"_RIM_LIGHTING{i}_MASK", bc.textureValue); - bc = FindProperty($"_Rim_Lighting_Mask"); - editor.TexturePropertySingleLine( - MakeLabel(bc, "Mask"), - bc); - SetKeyword($"_RIM_LIGHTING_MASK", bc.textureValue); + if (bc.textureValue) { + bc = FindProperty($"_Rim_Lighting{i}_Mask_Invert"); + enabled = bc.floatValue > 1E-6; + EditorGUI.BeginChangeCheck(); + enabled = EditorGUILayout.Toggle("Invert mask", enabled); + EditorGUI.EndChangeCheck(); + bc.floatValue = enabled ? 1.0f : 0.0f; + } - if (bc.textureValue) { - bc = FindProperty($"_Rim_Lighting_Mask_Invert"); - enabled = bc.floatValue > 1E-6; EditorGUI.BeginChangeCheck(); - enabled = EditorGUILayout.Toggle("Invert mask", enabled); - EditorGUI.EndChangeCheck(); - bc.floatValue = enabled ? 1.0f : 0.0f; - } - - EditorGUI.BeginChangeCheck(); - bc = FindProperty($"_Rim_Lighting_Mode"); - MatcapMode mode = (MatcapMode) Math.Round(bc.floatValue); - mode = (MatcapMode) EditorGUILayout.EnumPopup( - MakeLabel("Rim lighting mode"), mode); - if (EditorGUI.EndChangeCheck()) { - RecordAction("Rim lighting mode"); - foreach (Material m in editor.targets) { - m.SetFloat($"_Rim_Lighting_Mode", (int) mode); + bc = FindProperty($"_Rim_Lighting{i}_Mode"); + MatcapMode mode = (MatcapMode) Math.Round(bc.floatValue); + mode = (MatcapMode) EditorGUILayout.EnumPopup( + MakeLabel("Rim lighting mode"), mode); + if (EditorGUI.EndChangeCheck()) { + RecordAction("Rim lighting mode"); + foreach (Material m in editor.targets) { + m.SetFloat($"_Rim_Lighting{i}_Mode", (int) mode); + } } - } - bc = FindProperty($"_Rim_Lighting_Center"); - editor.FloatProperty( - bc, - "Center"); + bc = FindProperty($"_Rim_Lighting{i}_Center"); + editor.FloatProperty( + bc, + "Center"); - bc = FindProperty($"_Rim_Lighting_Power"); - editor.FloatProperty( - bc, - "Power"); + bc = FindProperty($"_Rim_Lighting{i}_Power"); + editor.FloatProperty( + bc, + "Power"); - bc = FindProperty($"_Rim_Lighting_Strength"); - editor.FloatProperty( - bc, - "Strength"); + bc = FindProperty($"_Rim_Lighting{i}_Strength"); + editor.FloatProperty( + bc, + "Strength"); - EditorGUI.indentLevel -= 1; + EditorGUI.indentLevel -= 1; + } } + enum NormalsMode { + Flat, + Spherical + }; + void DoShadingMode() { MaterialProperty bc; - /* - bc = FindProperty("_Shading_Mode"); - editor.RangeProperty( - bc, - "Shading mode (0=realistic,1=flat)"); - SetKeyword("_SHADING_MODE_FLAT", ((int) Math.Round(bc.floatValue, 0)) == 1); - */ - - bc = FindProperty("_Flatten_Mesh_Normals"); - bool enabled = bc.floatValue > 1E-6; + bc = FindProperty($"_Mesh_Normals_Mode"); EditorGUI.BeginChangeCheck(); - enabled = EditorGUILayout.Toggle("Flatten normals", enabled); - EditorGUI.EndChangeCheck(); - bc.floatValue = enabled ? 1.0f : 0.0f; + NormalsMode mode = (NormalsMode) Math.Round(bc.floatValue, 0); + mode = (NormalsMode) EditorGUILayout.EnumPopup( + MakeLabel("Normals mode"), mode); + if (EditorGUI.EndChangeCheck()) { + RecordAction("Rendering Mode"); + } + bc.floatValue = (float) mode; - if (enabled) { + if (mode == NormalsMode.Flat) { bc = FindProperty("_Flatten_Mesh_Normals_Str"); editor.FloatProperty( bc, @@ -315,7 +317,7 @@ public class ToonerGUI : ShaderGUI { } bc = FindProperty("_Confabulate_Normals"); - enabled = bc.floatValue > 1E-6; + bool enabled = bc.floatValue > 1E-6; EditorGUI.BeginChangeCheck(); enabled = EditorGUILayout.Toggle("Confabulate normals", enabled); EditorGUI.EndChangeCheck(); @@ -570,21 +572,26 @@ public class ToonerGUI : ShaderGUI { } } - void DoChainTessellation() { - MaterialProperty bc = FindProperty("_Enable_Chain_Tessellation"); + void DoTessellation() { + MaterialProperty bc = FindProperty("_Enable_Tessellation"); bool enabled = bc.floatValue > 1E-6; EditorGUI.BeginChangeCheck(); enabled = EditorGUILayout.Toggle("Enable", enabled); EditorGUI.EndChangeCheck(); - SetKeyword("_CHAIN_TESSELLATION", enabled); + SetKeyword("_TESSELLATION", enabled); bc.floatValue = enabled ? 1.0f : 0.0f; if (enabled) { - bc = FindProperty("_Chain_Tess_Factor"); + bc = FindProperty("_Tess_Factor"); editor.RangeProperty( bc, "Tessellation factor"); + + bc = FindProperty("_Tess_Dist_Cutoff"); + editor.FloatProperty( + bc, + "Activation distance (negative=always on)"); } } @@ -745,12 +752,10 @@ public class ToonerGUI : ShaderGUI { DoUVScroll(); EditorGUI.indentLevel -= 1; - /* - GUILayout.Label("Chain tessellation", EditorStyles.boldLabel); + GUILayout.Label("Tessellation", EditorStyles.boldLabel); EditorGUI.indentLevel += 1; - DoChainTessellation(); + DoTessellation(); EditorGUI.indentLevel -= 1; - */ GUILayout.Label("Hue shift", EditorStyles.boldLabel); EditorGUI.indentLevel += 1; diff --git a/clones.cginc b/clones.cginc index 6369fee..fe51f18 100644 --- a/clones.cginc +++ b/clones.cginc @@ -12,6 +12,11 @@ void add_clones(in v2f clone_verts[3], inout TriangleStream<v2f> tri_out) return; } + float factor = _Tess_Factor; + if (_Clones_Dist_Cutoff > 0 && length(_WorldSpaceCameraPos - clone_verts[0].worldPos) > _Clones_Dist_Cutoff) { + factor = 1; + } + uint n_clones = (uint) round(_Clones_Count); for (uint i = 0; i < (uint) n_clones; i++) { for (uint j = 0; j < 3; j++) { diff --git a/globals.cginc b/globals.cginc index aa23216..2ed4be1 100644 --- a/globals.cginc +++ b/globals.cginc @@ -34,7 +34,7 @@ float _Max_Brightness; float _Alpha_Cutoff; -float _Flatten_Mesh_Normals; +float _Mesh_Normals_Mode; float _Flatten_Mesh_Normals_Str; float _Confabulate_Normals; @@ -61,7 +61,8 @@ float _Scroll_Width; float _Scroll_Strength; float _Scroll_Speed; -float _Chain_Tess_Factor; +float _Tess_Factor; +float _Tess_Dist_Cutoff; float _Enable_Matcap0; texture2D _Matcap0; @@ -77,14 +78,23 @@ float _Matcap1_Mask_Invert; float _Matcap1Str; float _Matcap1Mode; -float _Rim_Lighting_Enabled; -float _Rim_Lighting_Mode; -float3 _Rim_Lighting_Color; -texture2D _Rim_Lighting_Mask; -float _Rim_Lighting_Mask_Invert; -float _Rim_Lighting_Center; -float _Rim_Lighting_Power; -float _Rim_Lighting_Strength; +float _Rim_Lighting0_Enabled; +float _Rim_Lighting0_Mode; +float3 _Rim_Lighting0_Color; +texture2D _Rim_Lighting0_Mask; +float _Rim_Lighting0_Mask_Invert; +float _Rim_Lighting0_Center; +float _Rim_Lighting0_Power; +float _Rim_Lighting0_Strength; + +float _Rim_Lighting1_Enabled; +float _Rim_Lighting1_Mode; +float3 _Rim_Lighting1_Color; +texture2D _Rim_Lighting1_Mask; +float _Rim_Lighting1_Mask_Invert; +float _Rim_Lighting1_Center; +float _Rim_Lighting1_Power; +float _Rim_Lighting1_Strength; float _OKLAB_Enabled; texture2D _OKLAB_Mask; @@ -95,6 +105,7 @@ float _OKLAB_Hue_Shift; float _Clones_Enabled; float _Clones_Count; float _Clones_dx; +float _Clones_Dist_Cutoff; float _UVScroll_Enabled; texture2D _UVScroll_Mask; diff --git a/interpolators.cginc b/interpolators.cginc index 186a851..9e967c3 100644 --- a/interpolators.cginc +++ b/interpolators.cginc @@ -17,9 +17,12 @@ struct v2f { float4 clipPos : POSITION; float2 uv : TEXCOORD0; + #if defined(LIGHTMAP_ON) float2 lmuv : TEXCOORD1; + #endif float3 worldPos : TEXCOORD2; float3 normal : TEXCOORD3; + float3 objPos : TEXCOORD4; }; #else @@ -37,13 +40,16 @@ struct v2f { float4 clipPos : SV_POSITION; float2 uv : TEXCOORD0; + #if defined(LIGHTMAP_ON) float2 lmuv : TEXCOORD1; + #endif float3 normal : TEXCOORD2; float4 tangent : TEXCOORD3; float3 worldPos : TEXCOORD4; + float3 objPos : TEXCOORD5; #if defined(VERTEXLIGHT_ON) - float3 vertexLightColor : TEXCOORD5; + float3 vertexLightColor : TEXCOORD6; #endif }; #endif @@ -126,13 +126,16 @@ float4 getLitColor( float3 view_dir = normalize(_WorldSpaceCameraPos - worldPos); - bool flat = round(_Flatten_Mesh_Normals) == 1.0; + uint normals_mode = round(_Mesh_Normals_Mode); + bool flat = (normals_mode == 0); float3 flat_normal = normalize( (1.0 / _Flatten_Mesh_Normals_Str) * normal + _Flatten_Mesh_Normals_Str * view_dir); + float3 spherical_normal = normalize(UnityObjectToWorldNormal(normalize(i.objPos))); + normal = lerp(spherical_normal, flat_normal, flat); UnityIndirect indirect_light = CreateIndirectLight(vertexLightColor, - view_dir, flat ? flat_normal : normal, smoothness, worldPos, uv); + view_dir, normal, smoothness, worldPos, uv); UnityLight direct_light = CreateDirectLight(normal, i); if (flat) { @@ -141,6 +144,7 @@ float4 getLitColor( direct_light.color *= (1 - e); } + direct_light.color = clamp(direct_light.color, _Min_Brightness, _Max_Brightness*.5); indirect_light.diffuse = clamp(indirect_light.diffuse, _Min_Brightness, _Max_Brightness); indirect_light.specular = clamp(indirect_light.specular, _Min_Brightness, _Max_Brightness); @@ -152,7 +156,7 @@ float4 getLitColor( one_minus_reflectivity, smoothness, view_dir, - flat ? flat_normal : normal, + normal, direct_light, indirect_light).xyz; } else { @@ -161,7 +165,7 @@ float4 getLitColor( specular_tint, one_minus_reflectivity, smoothness, - flat ? flat_normal : normal, + normal, view_dir, direct_light, indirect_light).xyz; diff --git a/tooner.shader b/tooner.shader index d04a45b..c9f88ac 100644 --- a/tooner.shader +++ b/tooner.shader @@ -33,7 +33,7 @@ Shader "yum_food/tooner" _NormalStr("Normal strength", Range(0, 10)) = 1 _Shading_Mode("Shading mode", Range(0, 1)) = 0 - [MaterialToggle] _Flatten_Mesh_Normals("Flatten mesh normals", Float) = 0.0 + _Mesh_Normals_Mode("Normals mode", Float) = 0.0 _Flatten_Mesh_Normals_Str("Flatten mesh normals strength", Float) = 100.0 [MaterialToggle] _Confabulate_Normals("Confabulate mesh normals", Float) = 0.0 @@ -82,14 +82,23 @@ Shader "yum_food/tooner" _Matcap1Mode("Matcap mode", Float) = 0 _Matcap1Str("Matcap strength", Float) = 1 - _Rim_Lighting_Enabled("Enable rim lighting", Float) = 0 - _Rim_Lighting_Mode("Rim lighting mode", Float) = 0 - _Rim_Lighting_Mask("Rim lighting mask", 2D) = "white" {} - _Rim_Lighting_Mask_Invert("Invert rim lighting mask", Float) = 0.0 - _Rim_Lighting_Color("Rim lighting color", Color) = (1, 1, 1, 1) - _Rim_Lighting_Center("Rim lighting center", Float) = 0.5 - _Rim_Lighting_Power("Rim lighting power", Float) = 2.0 - _Rim_Lighting_Strength("Rim lighting power", Float) = 1.0 + _Rim_Lighting0_Enabled("Enable rim lighting", Float) = 0 + _Rim_Lighting0_Mode("Rim lighting mode", Float) = 0 + _Rim_Lighting0_Mask("Rim lighting mask", 2D) = "white" {} + _Rim_Lighting0_Mask_Invert("Invert rim lighting mask", Float) = 0.0 + _Rim_Lighting0_Color("Rim lighting color", Color) = (1, 1, 1, 1) + _Rim_Lighting0_Center("Rim lighting center", Float) = 0.5 + _Rim_Lighting0_Power("Rim lighting power", Float) = 2.0 + _Rim_Lighting0_Strength("Rim lighting power", Float) = 1.0 + + _Rim_Lighting1_Enabled("Enable rim lighting", Float) = 0 + _Rim_Lighting1_Mode("Rim lighting mode", Float) = 0 + _Rim_Lighting1_Mask("Rim lighting mask", 2D) = "white" {} + _Rim_Lighting1_Mask_Invert("Invert rim lighting mask", Float) = 0.0 + _Rim_Lighting1_Color("Rim lighting color", Color) = (1, 1, 1, 1) + _Rim_Lighting1_Center("Rim lighting center", Float) = 0.5 + _Rim_Lighting1_Power("Rim lighting power", Float) = 2.0 + _Rim_Lighting1_Strength("Rim lighting power", Float) = 1.0 _OKLAB_Enabled("Enable OKLAB", Float) = 0.0 _OKLAB_Mask("Mask", 2D) = "white" {} @@ -98,7 +107,8 @@ Shader "yum_food/tooner" _OKLAB_Hue_Shift("OKLAB hue shift", Range(0, 6.283185307)) = 0.0 _Clones_Enabled("Enable clones", Float) = 0.0 - _Clones_Count("Clones count", Range(0,4)) = 0.0 + _Clones_Count("Clones count", Range(0,16)) = 0.0 + _Clones_Dist_Cutoff("Clones distance cutoff", Float) = -1.0 _Clones_dx("Clones dx", Range(0, 1)) = 1.0 _UVScroll_Enabled("Enable UV scrolling", Float) = 0.0 @@ -110,6 +120,10 @@ Shader "yum_food/tooner" _LTCGI_Enabled("LTCGI enabled", Float) = 0.0 _LTCGI_SpecularColor("LTCGI specular color", Color) = (1, 1, 1, 1) _LTCGI_DiffuseColor("LTCGI diffuse color", Color) = (1, 1, 1, 1) + + _Enable_Tessellation("Enable tessellation", Float) = 0.0 + _Tess_Factor("Tessellation factor", Range(1, 64)) = 1.0 + _Tess_Dist_Cutoff("Tessellation distance cutoff", Float) = -1.0 } SubShader { @@ -153,8 +167,10 @@ Shader "yum_food/tooner" #pragma shader_feature_local _ _MATCAP0_MASK #pragma shader_feature_local _ _MATCAP1 #pragma shader_feature_local _ _MATCAP1_MASK - #pragma shader_feature_local _ _RIM_LIGHTING - #pragma shader_feature_local _ _RIM_LIGHTING_MASK + #pragma shader_feature_local _ _RIM_LIGHTING0 + #pragma shader_feature_local _ _RIM_LIGHTING0_MASK + #pragma shader_feature_local _ _RIM_LIGHTING1 + #pragma shader_feature_local _ _RIM_LIGHTING1_MASK #pragma shader_feature_local _ _OKLAB #pragma shader_feature_local _ _CLONES #pragma shader_feature_local _ _PBR_OVERLAY @@ -163,6 +179,7 @@ Shader "yum_food/tooner" #pragma shader_feature_local _ _PBR_OVERLAY_ROUGHNESS_MAP #pragma shader_feature_local _ _PBR_OVERLAY_METALLIC_MAP #pragma shader_feature_local _ _LTCGI + #pragma shader_feature_local _ _TESSELLATION #pragma vertex vert //#pragma vertex hull_vertex @@ -211,8 +228,10 @@ Shader "yum_food/tooner" #pragma shader_feature_local _ _MATCAP0_MASK #pragma shader_feature_local _MATCAP1 #pragma shader_feature_local _ _MATCAP1_MASK - #pragma shader_feature_local _ _RIM_LIGHTING - #pragma shader_feature_local _ _RIM_LIGHTING_MASK + #pragma shader_feature_local _ _RIM_LIGHTING0 + #pragma shader_feature_local _ _RIM_LIGHTING0_MASK + #pragma shader_feature_local _ _RIM_LIGHTING1 + #pragma shader_feature_local _ _RIM_LIGHTING1_MASK #pragma shader_feature_local _ _OKLAB #pragma shader_feature_local _ _CLONES #pragma shader_feature_local _ _PBR_OVERLAY @@ -221,6 +240,7 @@ Shader "yum_food/tooner" #pragma shader_feature_local _ _PBR_OVERLAY_ROUGHNESS_MAP #pragma shader_feature_local _ _PBR_OVERLAY_METALLIC_MAP #pragma shader_feature_local _ _LTCGI + #pragma shader_feature_local _ _TESSELLATION #pragma vertex vert //#pragma vertex hull_vertex @@ -251,8 +271,10 @@ Shader "yum_food/tooner" #pragma shader_feature_local _ _MATCAP0_MASK #pragma shader_feature_local _MATCAP1 #pragma shader_feature_local _ _MATCAP1_MASK - #pragma shader_feature_local _ _RIM_LIGHTING - #pragma shader_feature_local _ _RIM_LIGHTING_MASK + #pragma shader_feature_local _ _RIM_LIGHTING0 + #pragma shader_feature_local _ _RIM_LIGHTING0_MASK + #pragma shader_feature_local _ _RIM_LIGHTING1 + #pragma shader_feature_local _ _RIM_LIGHTING1_MASK #pragma shader_feature_local _ _OKLAB #pragma shader_feature_local _ _CLONES #pragma shader_feature_local _ _PBR_OVERLAY @@ -261,6 +283,7 @@ Shader "yum_food/tooner" #pragma shader_feature_local _ _PBR_OVERLAY_ROUGHNESS_MAP #pragma shader_feature_local _ _PBR_OVERLAY_METALLIC_MAP #pragma shader_feature_local _ _LTCGI + #pragma shader_feature_local _ _TESSELLATION #pragma vertex vert //#pragma vertex hull_vertex diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc index cdc10b0..45a69e8 100644 --- a/tooner_lighting.cginc +++ b/tooner_lighting.cginc @@ -42,7 +42,9 @@ struct tess_data { float4 position : INTERNALTESSPOS; float2 uv : TEXCOORD0; + #if defined(LIGHTMAP_ON) float2 lmuv : TEXCOORD1; + #endif float3 normal : TEXCOORD2; float4 tangent : TEXCOORD3; @@ -52,15 +54,16 @@ struct tess_data }; struct tess_factors { - float edge[4] : SV_TessFactor; - float inside[2] : SV_InsideTessFactor; + float edge[3] : SV_TessFactor; + float inside : SV_InsideTessFactor; }; void getVertexLightColor(inout v2f i) { #if defined(VERTEXLIGHT_ON) float3 view_dir = normalize(_WorldSpaceCameraPos - i.worldPos); - bool flat = round(_Flatten_Mesh_Normals) == 1.0; + uint normals_mode = round(_Mesh_Normals_Mode); + bool flat = (normals_mode == 0); float3 flat_normal = normalize( (1.0 / _Flatten_Mesh_Normals_Str) * i.normal + _Flatten_Mesh_Normals_Str * view_dir); @@ -86,12 +89,13 @@ v2f vert(appdata v) o.clipPos = UnityObjectToClipPos(v.position); o.worldPos = mul(unity_ObjectToWorld, v.position); + o.objPos = v.position; o.normal = UnityObjectToWorldNormal(v.normal); o.tangent = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); o.uv = v.uv0.xy; #if defined(LIGHTMAP_ON) - o.lmuv = v.uv1 * unity_LightmapST.xy + unity_LightmapST.zw + o.lmuv = v.uv1 * unity_LightmapST.xy + unity_LightmapST.zw; #endif getVertexLightColor(o); @@ -102,13 +106,20 @@ v2f vert(appdata v) void getVertexLightColorTess(inout tess_data i) { #if defined(VERTEXLIGHT_ON) + float3 worldPos = mul(unity_ObjectToWorld, i.position).xyz; + float3 view_dir = normalize(_WorldSpaceCameraPos - worldPos); + uint normals_mode = round(_Mesh_Normals_Mode); + bool flat = (normals_mode == 0); + float3 flat_normal = normalize( + (1.0 / _Flatten_Mesh_Normals_Str) * i.normal + + _Flatten_Mesh_Normals_Str * view_dir); i.vertexLightColor = Shade4PointLights( unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb, - unity_4LightAtten0, worldPos, i.normal + unity_4LightAtten0, worldPos, flat ? flat_normal : i.normal ); #endif } @@ -117,13 +128,21 @@ tess_data hull_vertex(appdata v) { tess_data o; + UNITY_INITIALIZE_OUTPUT(tess_data, o); + UNITY_SETUP_INSTANCE_ID(v); + UNITY_TRANSFER_INSTANCE_ID(v, o); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + o.position = v.position; + //o.position = UnityObjectToClipPos(v.position); + //o.worldPos = mul(unity_ObjectToWorld, v.position); + //o.objPos = v.position; o.normal = UnityObjectToWorldNormal(v.normal); o.tangent = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w); o.uv = v.uv0.xy; #if defined(LIGHTMAP_ON) - o.lmuv = v.uv1 * unity_LightmapST.xy + unity_LightmapST.zw + o.lmuv = v.uv1 * unity_LightmapST.xy + unity_LightmapST.zw; #endif getVertexLightColorTess(o); @@ -131,45 +150,50 @@ tess_data hull_vertex(appdata v) return o; } -tess_factors patch_constant(InputPatch<tess_data, 4> patch) +tess_factors patch_constant(InputPatch<tess_data, 3> patch) { tess_factors f; - float factor = _Chain_Tess_Factor; - factor = 1; + + float3 worldPos = mul(unity_ObjectToWorld, patch[0].position); + float factor = _Tess_Factor; + if (_Tess_Dist_Cutoff > 0 && length(_WorldSpaceCameraPos - worldPos) > _Tess_Dist_Cutoff) { + factor = 1; + } + f.edge[0] = factor; f.edge[1] = factor; f.edge[2] = factor; - f.edge[3] = factor; - f.inside[0] = factor; - f.inside[1] = factor; + f.inside = factor; return f; } -[UNITY_domain("quad")] -[UNITY_outputcontrolpoints(4)] +[UNITY_domain("tri")] +[UNITY_outputcontrolpoints(3)] [UNITY_outputtopology("triangle_cw")] [UNITY_partitioning("fractional_odd")] [UNITY_patchconstantfunc("patch_constant")] tess_data hull( - InputPatch<tess_data, 4> patch, + InputPatch<tess_data, 3> patch, uint id : SV_OutputControlPointID) { return patch[id]; } -[UNITY_domain("quad")] +[UNITY_domain("tri")] v2f domain( tess_factors factors, - OutputPatch<tess_data, 4> patch, - float2 uv : SV_DomainLocation) + OutputPatch<tess_data, 3> patch, + float3 baryc : SV_DomainLocation) { v2f data; #define DOMAIN_INTERP(fieldName) data.fieldName = \ - lerp(\ - lerp(patch[0].fieldName, patch[1].fieldName, uv.x), \ - lerp(patch[2].fieldName, patch[3].fieldName, uv.x), \ - uv.y) + patch[0].fieldName * baryc.x + \ + patch[1].fieldName * baryc.y + \ + patch[2].fieldName * baryc.z; DOMAIN_INTERP(uv); + #if defined(LIGHTMAP_ON) + DOMAIN_INTERP(lmuv); + #endif DOMAIN_INTERP(normal); DOMAIN_INTERP(tangent); @@ -177,11 +201,12 @@ v2f domain( DOMAIN_INTERP(vertexLightColor); #endif - float4 pos = lerp( - lerp(patch[0].position, patch[1].position, uv.x), - lerp(patch[2].position, patch[3].position, uv.x), - uv.y); + float4 pos = + patch[0].position * baryc.x + + patch[1].position * baryc.y + + patch[2].position * baryc.z; data.clipPos = UnityObjectToClipPos(pos); + data.objPos = pos; data.worldPos = mul(unity_ObjectToWorld, pos); return data; @@ -189,7 +214,7 @@ v2f domain( // maxvertexcount == the number of vertices we create #if defined(_CLONES) -[maxvertexcount(15)] +[maxvertexcount(45)] #else [maxvertexcount(3)] #endif @@ -264,12 +289,6 @@ void geom(triangle v2f tri_in[3], v1.normal = n; v2.normal = n; - n = normalize(cross(v1.worldPos - v0.worldPos, v2.worldPos - v0.worldPos)); - avg_pos = (v0.worldPos + v1.worldPos + v2.worldPos) / 3; - v0.worldPos = applyScroll(v0.worldPos, n, avg_pos); - v1.worldPos = applyScroll(v1.worldPos, n, avg_pos); - v2.worldPos = applyScroll(v2.worldPos, n, avg_pos); - // Omit geometry that's too close when exploded. /* if (_Explode_Phase > .05 && length(v0.worldPos - _WorldSpaceCameraPos) < .2) { @@ -289,6 +308,23 @@ void geom(triangle v2f tri_in[3], } } #endif // __EXPLODE +#if defined(_SCROLL) + { + float3 n = normalize(cross(v1.worldPos - v0.worldPos, v2.worldPos - v0.worldPos)); + float3 avg_pos = (v0.worldPos + v1.worldPos + v2.worldPos) / 3; + v0.worldPos = applyScroll(v0.worldPos, n, avg_pos); + v1.worldPos = applyScroll(v1.worldPos, n, avg_pos); + v2.worldPos = applyScroll(v2.worldPos, n, avg_pos); + + float3 v0_objPos = mul(unity_WorldToObject, float4(v0.worldPos, 1)); + float3 v1_objPos = mul(unity_WorldToObject, float4(v1.worldPos, 1)); + float3 v2_objPos = mul(unity_WorldToObject, float4(v2.worldPos, 1)); + + v0.clipPos = UnityObjectToClipPos(v0_objPos); + v1.clipPos = UnityObjectToClipPos(v1_objPos); + v2.clipPos = UnityObjectToClipPos(v2_objPos); + } +#endif #if defined(_CLONES) v2f clone_verts[3] = {v0, v1, v2}; add_clones(clone_verts, tri_out); @@ -375,6 +411,15 @@ float4 effect(inout v2f i) albedo.a = 1; #endif +#if defined(_PBR_OVERLAY) +#if defined(_PBR_OVERLAY_BASECOLOR_MAP) + float4 ov_albedo = _PBR_Overlay_BaseColorTex.SampleGrad(linear_repeat_s, i.uv, iddx, iddy); + ov_albedo *= _PBR_Overlay_BaseColor; +#else + float4 ov_albedo = _BaseColor; +#endif // _PBR_OVERLAY_BASECOLOR_MAP +#endif // _PBR_OVERLAY + #if defined(_NORMAL_MAP) // Use UVs to smoothly blend between fully detailed normals when close up and // flat normals when far away. If we don't do this, then we see moire effects @@ -386,19 +431,19 @@ float4 effect(inout v2f i) (1/fw) * raw_normal, fw * float3(0, 0, 1)); -#if defined(_PBR_OVERLAY_NORMAL_MAP) +#if defined(_PBR_OVERLAY) && defined(_PBR_OVERLAY_NORMAL_MAP) { // Use UVs to smoothly blend between fully detailed normals when close up and // flat normals when far away. If we don't do this, then we see moire effects // on e.g. striped normal maps. //float3 raw_normal = UnpackScaleNormal(_PBR_Overlay_NormalTex.SampleGrad(linear_repeat_s, i.uv, iddx/2, iddy/2), _PBR_Overlay_Tex_NormalStr); - float3 raw_normal_2 = UnpackScaleNormal(_PBR_Overlay_NormalTex.SampleGrad(linear_repeat_s, i.uv, iddx/2, iddy/2), _PBR_Overlay_Tex_NormalStr); + float3 raw_normal_2 = UnpackScaleNormal(_PBR_Overlay_NormalTex.SampleGrad(linear_repeat_s, i.uv, iddx/2, iddy/2), _PBR_Overlay_Tex_NormalStr * ov_albedo.a); raw_normal = BlendNormals( raw_normal, raw_normal_2); } -#endif // _PBR_OVERLAY_NORMAL_MAP +#endif // _PBR_OVERLAY && _PBR_OVERLAY_NORMAL_MAP float3 binormal = CreateBinormal(i.normal, i.tangent.xyz, i.tangent.w); float3 normal = normalize( @@ -427,14 +472,7 @@ float4 effect(inout v2f i) #endif #if defined(_PBR_OVERLAY) -#if defined(_PBR_OVERLAY_BASECOLOR_MAP) - float4 ov_albedo = _PBR_Overlay_BaseColorTex.SampleGrad(linear_repeat_s, i.uv, iddx, iddy); - ov_albedo *= _PBR_Overlay_BaseColor; -#else - float4 ov_albedo = _BaseColor; -#endif // _PBR_OVERLAY_BASECOLOR_MAP albedo.rgb = lerp(albedo.rgb, ov_albedo.rgb, ov_albedo.a); - #endif // _PBR_OVERLAY #if defined(_MATCAP0) || defined(_MATCAP1) @@ -455,8 +493,8 @@ float4 effect(inout v2f i) #if defined(_MATCAP0_MASK) float4 matcap_mask_raw = _Matcap0_Mask.SampleGrad(linear_repeat_s, i.uv.xy, iddx, iddy); - matcap_mask_raw.rgb = (bool) round(_Matcap0_Mask_Invert) ? 1 - matcap_mask_raw.rgb : matcap_mask_raw.rgb; float matcap_mask = matcap_mask_raw.r * matcap_mask_raw.a; + matcap_mask = (bool) round(_Matcap0_Mask_Invert) ? 1 - matcap_mask : matcap_mask; #else float matcap_mask = 1; #endif @@ -492,8 +530,8 @@ float4 effect(inout v2f i) #if defined(_MATCAP1_MASK) float4 matcap_mask_raw = _Matcap1_Mask.SampleGrad(linear_repeat_s, i.uv.xy, iddx, iddy); - matcap_mask_raw.rgb = (bool) round(_Matcap1_Mask_Invert) ? 1 - matcap_mask_raw.rgb : matcap_mask_raw.rgb; float matcap_mask = matcap_mask_raw.r * matcap_mask_raw.a; + matcap_mask = (bool) round(_Matcap1_Mask_Invert) ? 1 - matcap_mask : matcap_mask; #else float matcap_mask = 1; #endif @@ -525,49 +563,88 @@ float4 effect(inout v2f i) } } #endif // _MATCAP0 || _MATCAP1 +#if defined(_RIM_LIGHTING0) || defined(_RIM_LIGHTING1) { -#if defined(_RIM_LIGHTING) // identity: (a, b, c) and (c, c, -(a +b)) are perpendicular to each other float theta = atan2(length(cross(view_dir, normal)), dot(view_dir, normal)); #define PI 3.14159265 - float rl = abs(theta) / PI; // on [0, 1] - rl = pow(2, -_Rim_Lighting_Power * abs(rl - _Rim_Lighting_Center)); - - float3 matcap = rl * _Rim_Lighting_Color * _Rim_Lighting_Strength; -#if defined(_RIM_LIGHTING_MASK) - float4 matcap_mask_raw = _Rim_Lighting_Mask.SampleGrad(linear_repeat_s, i.uv.xy, iddx, iddy); - matcap_mask_raw.rgb = (bool) round(_Rim_Lighting_Mask_Invert) ? 1 - matcap_mask_raw.rgb : matcap_mask_raw.rgb; - float matcap_mask = matcap_mask_raw.r * matcap_mask_raw.a; +#if defined(_RIM_LIGHTING0) + { + float rl = abs(theta) / PI; // on [0, 1] + rl = pow(2, -_Rim_Lighting0_Power * abs(rl - _Rim_Lighting0_Center)); + float3 matcap = rl * _Rim_Lighting0_Color * _Rim_Lighting0_Strength; +#if defined(_RIM_LIGHTING0_MASK) + float4 matcap_mask_raw = _Rim_Lighting0_Mask.SampleGrad(linear_repeat_s, i.uv.xy, iddx, iddy); + float matcap_mask = matcap_mask_raw.r * matcap_mask_raw.a; + matcap_mask = (bool) round(_Rim_Lighting0_Mask_Invert) ? 1 - matcap_mask : matcap_mask; #else - float matcap_mask = 1; + float matcap_mask = 1; #endif - - int mode = round(_Rim_Lighting_Mode); - switch (mode) { - case 0: - albedo.rgb += lerp(0, matcap, matcap_mask); - break; - case 1: - albedo.rgb *= lerp(1, matcap, matcap_mask); - break; - case 2: - albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);; - break; - case 3: - albedo.rgb -= lerp(0, matcap, matcap_mask); - break; - case 4: - albedo.rgb = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask); - break; - case 5: - albedo.rgb = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask); - break; - default: - break; + int mode = round(_Rim_Lighting0_Mode); + switch (mode) { + case 0: + albedo.rgb += lerp(0, matcap, matcap_mask); + break; + case 1: + albedo.rgb *= lerp(1, matcap, matcap_mask); + break; + case 2: + albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);; + break; + case 3: + albedo.rgb -= lerp(0, matcap, matcap_mask); + break; + case 4: + albedo.rgb = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask); + break; + case 5: + albedo.rgb = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask); + break; + default: + break; + } } +#endif // _RIM_LIGHTING0 +#if defined(_RIM_LIGHTING1) + { + float rl = abs(theta) / PI; // on [0, 1] + rl = pow(2, -_Rim_Lighting1_Power * abs(rl - _Rim_Lighting1_Center)); + float3 matcap = rl * _Rim_Lighting1_Color * _Rim_Lighting1_Strength; +#if defined(_RIM_LIGHTING1_MASK) + float4 matcap_mask_raw = _Rim_Lighting1_Mask.SampleGrad(linear_repeat_s, i.uv.xy, iddx, iddy); + float matcap_mask = matcap_mask_raw.r * matcap_mask_raw.a; + matcap_mask = (bool) round(_Rim_Lighting1_Mask_Invert) ? 1 - matcap_mask : matcap_mask; +#else + float matcap_mask = 1; #endif + int mode = round(_Rim_Lighting1_Mode); + switch (mode) { + case 0: + albedo.rgb += lerp(0, matcap, matcap_mask); + break; + case 1: + albedo.rgb *= lerp(1, matcap, matcap_mask); + break; + case 2: + albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);; + break; + case 3: + albedo.rgb -= lerp(0, matcap, matcap_mask); + break; + case 4: + albedo.rgb = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask); + break; + case 5: + albedo.rgb = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask); + break; + default: + break; + } + } +#endif // _RIM_LIGHTING1 } +#endif // _RIM_LIGHTING0 || _RIM_LIGHTING1 #if defined(_OKLAB) // Do hue shift in perceptually uniform color space so it doesn't look like diff --git a/tooner_outline_pass.cginc b/tooner_outline_pass.cginc index a2b222b..35e22b5 100644 --- a/tooner_outline_pass.cginc +++ b/tooner_outline_pass.cginc @@ -19,8 +19,8 @@ struct tess_data }; struct tess_factors { - float edge[4] : SV_TessFactor; - float inside[2] : SV_InsideTessFactor; + float edge[3] : SV_TessFactor; + float inside: SV_InsideTessFactor; }; v2f vert(appdata v) @@ -61,6 +61,7 @@ v2f vert(appdata v) v2f o; o.worldPos = mul(unity_ObjectToWorld, v.vertex); + o.objPos = v.vertex; o.clipPos = UnityObjectToClipPos(v.vertex); o.normal = normal; o.uv = v.uv0.xy; @@ -103,43 +104,46 @@ tess_data hull_vertex(appdata v) return o; } -tess_factors patch_constant(InputPatch<tess_data, 4> patch) +tess_factors patch_constant(InputPatch<tess_data, 3> patch) { tess_factors f; - float factor = _Chain_Tess_Factor; + + float3 worldPos = mul(unity_ObjectToWorld, patch[0].vertex); + float factor = _Tess_Factor; + if (_Tess_Dist_Cutoff > 0 && length(_WorldSpaceCameraPos - worldPos) > _Tess_Dist_Cutoff) { + factor = 1; + } + f.edge[0] = factor; f.edge[1] = factor; f.edge[2] = factor; - f.edge[3] = factor; - f.inside[0] = factor; - f.inside[1] = factor; + f.inside = factor; return f; } -[UNITY_domain("quad")] +[UNITY_domain("tri")] [UNITY_outputcontrolpoints(3)] [UNITY_outputtopology("triangle_cw")] [UNITY_partitioning("fractional_odd")] [UNITY_patchconstantfunc("patch_constant")] tess_data hull( - InputPatch<tess_data, 4> patch, + InputPatch<tess_data, 3> patch, uint id : SV_OutputControlPointID) { return patch[id]; } -[UNITY_domain("quad")] +[UNITY_domain("tri")] v2f domain( tess_factors factors, - OutputPatch<tess_data, 4> patch, - float2 uv : SV_DomainLocation) + OutputPatch<tess_data, 3> patch, + float3 baryc : SV_DomainLocation) { v2f data; #define DOMAIN_INTERP(fieldName) data.fieldName = \ - lerp(\ - lerp(patch[0].fieldName, patch[1].fieldName, uv.x), \ - lerp(patch[2].fieldName, patch[3].fieldName, uv.x), \ - uv.y) + patch[0].fieldName * baryc.x + \ + patch[1].fieldName * baryc.y + \ + patch[2].fieldName * baryc.z; DOMAIN_INTERP(uv); DOMAIN_INTERP(normal); //DOMAIN_INTERP(tangent); @@ -148,11 +152,12 @@ v2f domain( DOMAIN_INTERP(vertexLightColor); #endif - float4 pos = lerp( - lerp(patch[0].vertex, patch[1].vertex, uv.x), - lerp(patch[2].vertex, patch[3].vertex, uv.x), - uv.y); + float4 pos = + patch[0].vertex * baryc.x + + patch[1].vertex * baryc.y + + patch[2].vertex * baryc.z; data.clipPos = UnityObjectToClipPos(pos); + data.objPos = pos; data.worldPos = mul(unity_ObjectToWorld, pos); return data; @@ -168,6 +173,10 @@ void geom(triangle v2f tri_in[3], uint pid: SV_PrimitiveID, inout TriangleStream<v2f> tri_out) { +#if !defined(_OUTLINES) + return; +#endif + v2f v0 = tri_in[0]; v2f v1 = tri_in[1]; v2f v2 = tri_in[2]; @@ -245,12 +254,6 @@ void geom(triangle v2f tri_in[3], v1.normal = nn; v2.normal = nn; - n = normalize(cross(v1.worldPos - v0.worldPos, v2.worldPos - v0.worldPos)); - avg_pos = (v0.worldPos + v1.worldPos + v2.worldPos) / 3; - v0.worldPos = applyScroll(v0.worldPos, n, avg_pos); - v1.worldPos = applyScroll(v1.worldPos, n, avg_pos); - v2.worldPos = applyScroll(v2.worldPos, n, avg_pos); - // Omit geometry that's too close when exploded. /* if (_Explode_Phase > .05 && length(v0.worldPos - _WorldSpaceCameraPos) < .2) { @@ -268,6 +271,23 @@ void geom(triangle v2f tri_in[3], v2.clipPos = UnityObjectToClipPos(v2_objPos); } #endif +#if defined(_SCROLL) + { + float3 n = normalize(cross(v1.worldPos - v0.worldPos, v2.worldPos - v0.worldPos)); + float3 avg_pos = (v0.worldPos + v1.worldPos + v2.worldPos) / 3; + v0.worldPos = applyScroll(v0.worldPos, n, avg_pos); + v1.worldPos = applyScroll(v1.worldPos, n, avg_pos); + v2.worldPos = applyScroll(v2.worldPos, n, avg_pos); + + float3 v0_objPos = mul(unity_WorldToObject, float4(v0.worldPos, 1)); + float3 v1_objPos = mul(unity_WorldToObject, float4(v1.worldPos, 1)); + float3 v2_objPos = mul(unity_WorldToObject, float4(v2.worldPos, 1)); + + v0.clipPos = UnityObjectToClipPos(v0_objPos); + v1.clipPos = UnityObjectToClipPos(v1_objPos); + v2.clipPos = UnityObjectToClipPos(v2_objPos); + } +#endif #if defined(_CLONES) v2f clone_verts[3] = {v0, v1, v2}; add_clones(clone_verts, tri_out); |
