From 5b4248c5bc0840ea3e768c2069ab954d5e810b25 Mon Sep 17 00:00:00 2001 From: Jakob Feldmann Date: Thu, 15 Feb 2024 14:08:35 +0100 Subject: [PATCH] feat: shader experiments, for new look. Work in Progress! --- .../Materials/FresnelRippleMaterial.mat | 2 +- Assets/Models/Materials/Shaders.meta | 8 + .../Materials/Shaders/FesnelRipple.shader | 206 ++++++ .../Shaders/FesnelRipple.shader.meta | 10 + Assets/Models/Materials/Wireframe.shadergraph | 642 ++++++++++++++++++ .../Materials/Wireframe.shadergraph.meta | 10 + Assets/Scripts/MeshWireframeComputor.cs | 102 +++ Assets/Scripts/MeshWireframeComputor.cs.meta | 11 + 8 files changed, 990 insertions(+), 1 deletion(-) create mode 100644 Assets/Models/Materials/Shaders.meta create mode 100644 Assets/Models/Materials/Shaders/FesnelRipple.shader create mode 100644 Assets/Models/Materials/Shaders/FesnelRipple.shader.meta create mode 100644 Assets/Models/Materials/Wireframe.shadergraph create mode 100644 Assets/Models/Materials/Wireframe.shadergraph.meta create mode 100644 Assets/Scripts/MeshWireframeComputor.cs create mode 100644 Assets/Scripts/MeshWireframeComputor.cs.meta diff --git a/Assets/Models/Materials/FresnelRippleMaterial.mat b/Assets/Models/Materials/FresnelRippleMaterial.mat index 2d65d50..859551d 100644 --- a/Assets/Models/Materials/FresnelRippleMaterial.mat +++ b/Assets/Models/Materials/FresnelRippleMaterial.mat @@ -124,7 +124,7 @@ Material: - _Surface: 0 - _WorkflowMode: 1 - _ZWrite: 1 - - _base_alpha: 0.41 + - _base_alpha: 0.695 - _impact_amplitude: 0 - _impact_anim: 0 - _impact_blend: 0 diff --git a/Assets/Models/Materials/Shaders.meta b/Assets/Models/Materials/Shaders.meta new file mode 100644 index 0000000..62b2618 --- /dev/null +++ b/Assets/Models/Materials/Shaders.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1d708c750e0f2b840a9799ed7b0da849 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Models/Materials/Shaders/FesnelRipple.shader b/Assets/Models/Materials/Shaders/FesnelRipple.shader new file mode 100644 index 0000000..3547e01 --- /dev/null +++ b/Assets/Models/Materials/Shaders/FesnelRipple.shader @@ -0,0 +1,206 @@ +Shader "CustomShader/FesnelRipple" + +{ + Properties + { + _base_alpha ("base alpha", Range(0.0, 1.0)) = 0.5 + _shield_color ("shield color", Color) = (0, 0, 1, 1) + _shield_color_brightness ("shield color brightness", Range(0.25, 20)) = 10.0 + _shield_intensity ("shield intensity", Range(0.1,20)) = 2.0 + _rotation ("rotation", Vector) = (0.1, 0.0, 0.0) + _shield_size ("shield size", Range(0.0,0.5)) = 0.0 + _shield_pulse_frequency ("shield pulse frequency", float)= 1.0 + _shield_pulse_density ("shield pulse density", float) = 1.0 + _shield_pulse_amplitude ("shield pulse amplitude", float) = 1.0 + _shield_pulse_blend ("shield pulse blend", float) = 1.0 + _shield_pulse_radius ("shield pulse radius", float) = 1.0 + _impact_origin ("impact origin", Vector) = (1.0, 0.0, 0.0) + _impact_frequency ("impact frequency", float) = 5.0 + _impact_density ("impact density", float) = 5.0 + _impact_amplitude ("impact amplitude", float) = 6.0 + _impact_blend ("impact blend", float) = 0 + _impact_radius ("impact radius", float) = 1.1 + _impact_anim ("impact anim", Range(0.0,0.1)) = 0.0 + } + HLSLINCLUDE + #pragma vertex vert + #pragma fragment frag + #pragma enable_d3d11_debug_symbols + #include "UnityCG.cginc" + // properties + float _base_alpha; + float4 _shield_color; + float _shield_color_brightness; + float _shield_intensity; + float3 _rotation; + float _shield_size; + float _shield_pulse_frequency; + float _shield_pulse_density; + float _shield_pulse_amplitude; + float _shield_pulse_blend; + float _shield_pulse_radius; + float3 _impact_origin; + float _impact_frequency; + float _impact_amplitude; + float _impact_blend; + float _impact_density; + float _impact_radius; + float _impact_anim; + + // Impact functions + + float _FadeRipple(float dist, float blend, float radius) { + // create a radius + return smoothstep(radius, 0, dist); + } + + float _ComputeRipple(float3 vert, float3 orig, float blend, float radius, float freq, float dens, float ampl, float anim) { + // calculate the intensity of the impact + float dist = distance(vert, orig); + float i = sin((freq * anim - dist * dens)) * ampl; + return i * _FadeRipple(dist, blend, radius); + } + + // Shield functions + + float ComputeFresnel(float3 norm, float3 view_dir, float intensity) { + float width = 0.95; + float softness = 0.96; + float fresnel = 1.0 - saturate(dot(norm, view_dir)); + fresnel = pow(fresnel, intensity); + fresnel = lerp(1, smoothstep(width, softness, fresnel), step(0, width)); + return fresnel; + } + + float4 Rotate(float3 vert, float3 speed) { + // build the 3 rotation matrices + speed = speed * _Time * 5.0; + + float4x4 xrot = float4x4( + float4(1.0, 0.0, 0.0, 0.0), + float4(0.0, cos(speed.x), -sin(speed.x), 0.0), + float4(0.0, sin(speed.x), cos(speed.x), 0.0), + float4(0.0, 0.0, 0.0, 1.0)); + + float4x4 yrot = float4x4( + float4(cos(speed.y), 0.0, -sin(speed.y), 0.0), + float4(0.0, 1.0, 0.0, 0.0), + float4(sin(speed.y), 0.0, cos(speed.y), 0.0), + float4(0.0, 0.0, 0.0, 1.0)); + + float4x4 zrot = float4x4( + float4(cos(speed.z), -sin(speed.z), 0.0, 0.0), + float4(sin(speed.z), cos(speed.z), 0.0, 0.0), + float4(0.0, 0.0, 1.0, 0.0), + float4(0.0, 0.0, 0.0, 1.0)); + + float4 output = mul(xrot, mul(yrot, mul(zrot, float4(vert.xyz, 1.0)))); + return output; + } + + // vertex shader inputs + struct appdata + { + float4 vertex : POSITION; + float4 normal : NORMAL; + float2 uv : TEXCOORD0; + }; + + // vertex shader outputs to fragment + struct v2f + { + float2 uv : TEXCOORD0; // texture coordinate + float4 vertex : SV_POSITION; // clips space position + float3 normal : NORMAL; + float3 viewDirection : TEXCOORD2; + }; + + // vertex shader + v2f vert (appdata v) + { + v.vertex = Rotate(v.vertex, _rotation); + v.normal = Rotate(v.normal, _rotation); + + float4 vert_world_pos = mul(unity_ObjectToWorld, v.vertex); + + float impact_ripple = _ComputeRipple(v.vertex.xyz, + _impact_origin.xyz, + _impact_blend, + _impact_radius, + _impact_frequency, + _impact_density, + _impact_amplitude, + _impact_anim); + + v.vertex += v.normal * (impact_ripple + _shield_size); + + v2f o; + // transform position to clip space + // (multiply with model*view*projection matrix) + o.vertex = UnityObjectToClipPos(v.vertex); + // just pass the texture coordinate + o.uv = v.uv; + o.normal = v.normal.xyz; + o.viewDirection = normalize(WorldSpaceViewDir(vert_world_pos)); + return o; + } + ENDHLSL + SubShader + { + Tags { "RenderType"="Transparent" + "RenderPipeline" = "UniversalPipeline" + "Queue"="Transparent" + "ForceNoShadowCasting"="True" + // "IgnoreProjector"="True" + // "Zwrite"="Off" + } + + Blend SrcAlpha OneMinusSrcAlpha + Pass + { + Tags + { + "LightMode" = "UniversalForward" + "RenderType"="Opaque" + "Queue"="Transparent" + } + Name "BackCullingPass" + Cull Back + + HLSLPROGRAM + half4 frag (v2f i) : SV_Target + { + float f = ComputeFresnel(i.normal, i.viewDirection, _shield_intensity); + half4 col = 0; + half3 normalToGray = (0.299 * i.normal.r) + (0.587 * i.normal.g) + (0.114 * i.normal.b); + col.rgb = f * _shield_color_brightness * _shield_color + (abs(normalToGray) - 0.3); + col.a = f * _base_alpha; + return col; + } + ENDHLSL + } + Pass + { + Tags + { + "LightMode" = "SRPDefaultUnLit" + "RenderType"="Transparent" + "Queue"="Transparent" + } + Name "FrontCullingPass" + Cull Front + + HLSLPROGRAM + half4 frag (v2f i) : SV_Target + { + //float f = ComputeFresnel(i.normal, i.viewDirection, _shield_intensity); + half4 col = 0; + half3 normalToGray = (0.299 * i.normal.r) + (0.587 * i.normal.g) + (0.114 * i.normal.b); + col.rgb = _shield_color_brightness * _shield_color + (abs(normalToGray) * 0.5 - 0.5); + col.a = _base_alpha * 0.5; + return col; + } + ENDHLSL + } + } +} diff --git a/Assets/Models/Materials/Shaders/FesnelRipple.shader.meta b/Assets/Models/Materials/Shaders/FesnelRipple.shader.meta new file mode 100644 index 0000000..979e076 --- /dev/null +++ b/Assets/Models/Materials/Shaders/FesnelRipple.shader.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: b965bf942e2a1754ea5b506226e626ed +ShaderImporter: + externalObjects: {} + defaultTextures: + - _MainTex: {instanceID: 0} + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Models/Materials/Wireframe.shadergraph b/Assets/Models/Materials/Wireframe.shadergraph new file mode 100644 index 0000000..18e42a7 --- /dev/null +++ b/Assets/Models/Materials/Wireframe.shadergraph @@ -0,0 +1,642 @@ +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.GraphData", + "m_ObjectId": "f852c3228dbb4591896a0d27e8832393", + "m_Properties": [], + "m_Keywords": [], + "m_Dropdowns": [], + "m_CategoryData": [], + "m_Nodes": [ + { + "m_Id": "6929c9dd7a084a88bdec920b898bdac6" + }, + { + "m_Id": "d752680a34384be29f6fcb555e3615ec" + }, + { + "m_Id": "f71842fc9a7749d29e0bc57d3f9012fe" + }, + { + "m_Id": "09982701fedd40d78500ca0aaa8d4c9b" + }, + { + "m_Id": "83c8ee5e4a114b07b3c3fed8032e3197" + }, + { + "m_Id": "86dff511efc34e059ea69079a0c66e4b" + }, + { + "m_Id": "56608722645f44b197db281df47fbc0a" + }, + { + "m_Id": "71319502054540aaa54a3ddf8587d9ac" + }, + { + "m_Id": "03d8e809db6e42db8906183335778f00" + } + ], + "m_GroupDatas": [], + "m_StickyNoteDatas": [], + "m_Edges": [], + "m_VertexContext": { + "m_Position": { + "x": 0.0, + "y": 0.0 + }, + "m_Blocks": [ + { + "m_Id": "6929c9dd7a084a88bdec920b898bdac6" + }, + { + "m_Id": "d752680a34384be29f6fcb555e3615ec" + }, + { + "m_Id": "f71842fc9a7749d29e0bc57d3f9012fe" + } + ] + }, + "m_FragmentContext": { + "m_Position": { + "x": 0.0, + "y": 200.0 + }, + "m_Blocks": [ + { + "m_Id": "09982701fedd40d78500ca0aaa8d4c9b" + }, + { + "m_Id": "83c8ee5e4a114b07b3c3fed8032e3197" + }, + { + "m_Id": "86dff511efc34e059ea69079a0c66e4b" + }, + { + "m_Id": "56608722645f44b197db281df47fbc0a" + }, + { + "m_Id": "71319502054540aaa54a3ddf8587d9ac" + }, + { + "m_Id": "03d8e809db6e42db8906183335778f00" + } + ] + }, + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "preventRotation": false + }, + "m_Path": "Shader Graphs", + "m_GraphPrecision": 1, + "m_PreviewMode": 2, + "m_OutputNode": { + "m_Id": "" + }, + "m_ActiveTargets": [ + { + "m_Id": "759ffdfdaf1c4c68ac61f149023be8e6" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "03d8e809db6e42db8906183335778f00", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Occlusion", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "e1137cc030fa4c979370bcabc63292b7" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Occlusion" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "09982701fedd40d78500ca0aaa8d4c9b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BaseColor", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "f647c0b8fafe4302a28c0254273544e4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BaseColor" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "0c3b7926f9f34cd5971c25f885258da5", + "m_Id": 0, + "m_DisplayName": "Normal (Tangent Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalTS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_Space": 3 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1bb234ddbdec4b4d828eaa4bc86423d8", + "m_Id": 0, + "m_DisplayName": "Smoothness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Smoothness", + "m_StageCapability": 2, + "m_Value": 0.5, + "m_DefaultValue": 0.5, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot", + "m_ObjectId": "2aeae748e2ae460dadb100d99ea5cf2e", + "m_Id": 0, + "m_DisplayName": "Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Position", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "56608722645f44b197db281df47fbc0a", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Smoothness", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "1bb234ddbdec4b4d828eaa4bc86423d8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Smoothness" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot", + "m_ObjectId": "58957bbacaa44c37a3d0469a71446f4b", + "m_Id": 0, + "m_DisplayName": "Tangent", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Tangent", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "5996287d54c84cb5adccade6786cfe03", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "6929c9dd7a084a88bdec920b898bdac6", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "2aeae748e2ae460dadb100d99ea5cf2e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Position" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "71319502054540aaa54a3ddf8587d9ac", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Emission", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "909f3b4029fd4d4fbc9a1eab27b5189b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Emission" +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget", + "m_ObjectId": "759ffdfdaf1c4c68ac61f149023be8e6", + "m_Datas": [], + "m_ActiveSubTarget": { + "m_Id": "ee6d19387b3c441c8772166e0add2e63" + }, + "m_AllowMaterialOverride": false, + "m_SurfaceType": 0, + "m_ZTestMode": 4, + "m_ZWriteControl": 0, + "m_AlphaMode": 0, + "m_RenderFace": 2, + "m_AlphaClip": false, + "m_CastShadows": true, + "m_ReceiveShadows": true, + "m_SupportsLODCrossFade": false, + "m_CustomEditorGUI": "", + "m_SupportVFX": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "83c8ee5e4a114b07b3c3fed8032e3197", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalTS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "0c3b7926f9f34cd5971c25f885258da5" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalTS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "86dff511efc34e059ea69079a0c66e4b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Metallic", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "b5035b2a70814f45ae62f614f82046fb" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Metallic" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "909f3b4029fd4d4fbc9a1eab27b5189b", + "m_Id": 0, + "m_DisplayName": "Emission", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Emission", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_ColorMode": 1, + "m_DefaultColor": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b5035b2a70814f45ae62f614f82046fb", + "m_Id": 0, + "m_DisplayName": "Metallic", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Metallic", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "d752680a34384be29f6fcb555e3615ec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Normal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "5996287d54c84cb5adccade6786cfe03" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Normal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e1137cc030fa4c979370bcabc63292b7", + "m_Id": 0, + "m_DisplayName": "Ambient Occlusion", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Occlusion", + "m_StageCapability": 2, + "m_Value": 1.0, + "m_DefaultValue": 1.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 2, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalLitSubTarget", + "m_ObjectId": "ee6d19387b3c441c8772166e0add2e63", + "m_WorkflowMode": 1, + "m_NormalDropOffSpace": 0, + "m_ClearCoat": false, + "m_BlendModePreserveSpecular": true +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "f647c0b8fafe4302a28c0254273544e4", + "m_Id": 0, + "m_DisplayName": "Base Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BaseColor", + "m_StageCapability": 2, + "m_Value": { + "x": 0.5, + "y": 0.5, + "z": 0.5 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_ColorMode": 0, + "m_DefaultColor": { + "r": 0.5, + "g": 0.5, + "b": 0.5, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f71842fc9a7749d29e0bc57d3f9012fe", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Tangent", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "58957bbacaa44c37a3d0469a71446f4b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Tangent" +} + diff --git a/Assets/Models/Materials/Wireframe.shadergraph.meta b/Assets/Models/Materials/Wireframe.shadergraph.meta new file mode 100644 index 0000000..af1be58 --- /dev/null +++ b/Assets/Models/Materials/Wireframe.shadergraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 1d42a1e828399e3419e843ccaf360423 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} diff --git a/Assets/Scripts/MeshWireframeComputor.cs b/Assets/Scripts/MeshWireframeComputor.cs new file mode 100644 index 0000000..ef0a5c0 --- /dev/null +++ b/Assets/Scripts/MeshWireframeComputor.cs @@ -0,0 +1,102 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +[RequireComponent(typeof(MeshFilter))] +public class MeshWireframeComputor : MonoBehaviour +{ + private static Color[] _COLORS = new Color[] + { + Color.red, + Color.green, + Color.blue, + }; + +#if UNITY_EDITOR + private void OnValidate() + { + // (called whenever the object is updated) + UpdateMesh(); + } +#endif + + [ContextMenu("Update Mesh")] + public void UpdateMesh() + { + if (!gameObject.activeSelf || !GetComponent().enabled) + return; + + Mesh m = GetComponent().sharedMesh; + if (m == null) return; + + // compute and store vertex colors for the + // wireframe shader + Color[] colors = _SortedColoring(m); + + if (colors != null) + m.SetColors(colors); + } + + private Color[] _SortedColoring(Mesh mesh) + { + int n = mesh.vertexCount; + int[] labels = new int[n]; + + List triangles = _GetSortedTriangles(mesh.triangles); + triangles.Sort((int[] t1, int[] t2) => + { + int i = 0; + while (i < t1.Length && i < t2.Length) + { + if (t1[i] < t2[i]) return -1; + if (t1[i] > t2[i]) return 1; + i += 1; + } + if (t1.Length < t2.Length) return -1; + if (t1.Length > t2.Length) return 1; + return 0; + }); + + foreach (int[] triangle in triangles) + { + List availableLabels = new List() { 1, 2, 3 }; + foreach (int vertexIndex in triangle) + { + if (availableLabels.Contains(labels[vertexIndex])) + availableLabels.Remove(labels[vertexIndex]); + } + foreach (int vertexIndex in triangle) + { + if (labels[vertexIndex] == 0) + { + if (availableLabels.Count == 0) + { + Debug.LogError("Could not find color"); + return null; + } + labels[vertexIndex] = availableLabels[0]; + availableLabels.RemoveAt(0); + } + } + } + + Color[] colors = new Color[n]; + for (int i = 0; i < n; i++) + colors[i] = labels[i] > 0 ? _COLORS[labels[i] - 1] : _COLORS[0]; + + return colors; + } + + private List _GetSortedTriangles(int[] triangles) + { + List result = new List(); + for (int i = 0; i < triangles.Length; i += 3) + { + List t = new List { triangles[i], triangles[i + 1], triangles[i + 2] }; + t.Sort(); + result.Add(t.ToArray()); + } + return result; + } + +} diff --git a/Assets/Scripts/MeshWireframeComputor.cs.meta b/Assets/Scripts/MeshWireframeComputor.cs.meta new file mode 100644 index 0000000..90cec94 --- /dev/null +++ b/Assets/Scripts/MeshWireframeComputor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9f2a6e75f30c618429854af62cf7010c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: