SpatialMappingWireframe.shader 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. Shader "Universal Render Pipeline/VR/SpatialMapping/Wireframe"
  2. {
  3. Properties
  4. {
  5. _WireThickness ("Wire Thickness", RANGE(0, 800)) = 100
  6. }
  7. SubShader
  8. {
  9. Tags {"RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
  10. LOD 100
  11. Pass
  12. {
  13. Name "Spatial Mapping Wireframe"
  14. // Wireframe shader based on the the following
  15. // http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf
  16. HLSLPROGRAM
  17. #pragma require geometry
  18. #pragma vertex vert
  19. #pragma geometry geom
  20. #pragma fragment frag
  21. // -------------------------------------
  22. // Unity defined keywords
  23. #pragma multi_compile_instancing
  24. #include "UnlitInput.hlsl"
  25. float _WireThickness;
  26. struct Attributes
  27. {
  28. float4 positionOS : POSITION;
  29. UNITY_VERTEX_INPUT_INSTANCE_ID
  30. };
  31. struct v2g
  32. {
  33. float4 projectionSpaceVertex : SV_POSITION;
  34. float4 worldSpacePosition : TEXCOORD1;
  35. UNITY_VERTEX_OUTPUT_STEREO
  36. };
  37. v2g vert(Attributes input)
  38. {
  39. v2g output = (v2g)0;
  40. UNITY_SETUP_INSTANCE_ID(input);
  41. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
  42. VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
  43. output.projectionSpaceVertex = vertexInput.positionCS;
  44. output.worldSpacePosition = mul(unity_ObjectToWorld, input.positionOS);
  45. return output;
  46. }
  47. struct g2f
  48. {
  49. float4 projectionSpaceVertex : SV_POSITION;
  50. float4 worldSpacePosition : TEXCOORD0;
  51. float4 dist : TEXCOORD1;
  52. UNITY_VERTEX_OUTPUT_STEREO
  53. };
  54. [maxvertexcount(3)]
  55. void geom(triangle v2g i[3], inout TriangleStream<g2f> triangleStream)
  56. {
  57. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i[0]);
  58. float2 p0 = i[0].projectionSpaceVertex.xy / i[0].projectionSpaceVertex.w;
  59. float2 p1 = i[1].projectionSpaceVertex.xy / i[1].projectionSpaceVertex.w;
  60. float2 p2 = i[2].projectionSpaceVertex.xy / i[2].projectionSpaceVertex.w;
  61. float2 edge0 = p2 - p1;
  62. float2 edge1 = p2 - p0;
  63. float2 edge2 = p1 - p0;
  64. // To find the distance to the opposite edge, we take the
  65. // formula for finding the area of a triangle Area = Base/2 * Height,
  66. // and solve for the Height = (Area * 2)/Base.
  67. // We can get the area of a triangle by taking its cross product
  68. // divided by 2. However we can avoid dividing our area/base by 2
  69. // since our cross product will already be double our area.
  70. float area = abs(edge1.x * edge2.y - edge1.y * edge2.x);
  71. float wireThickness = 800 - _WireThickness;
  72. g2f o;
  73. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  74. o.worldSpacePosition = i[0].worldSpacePosition;
  75. o.projectionSpaceVertex = i[0].projectionSpaceVertex;
  76. o.dist.xyz = float3( (area / length(edge0)), 0.0, 0.0) * o.projectionSpaceVertex.w * wireThickness;
  77. o.dist.w = 1.0 / o.projectionSpaceVertex.w;
  78. triangleStream.Append(o);
  79. o.worldSpacePosition = i[1].worldSpacePosition;
  80. o.projectionSpaceVertex = i[1].projectionSpaceVertex;
  81. o.dist.xyz = float3(0.0, (area / length(edge1)), 0.0) * o.projectionSpaceVertex.w * wireThickness;
  82. o.dist.w = 1.0 / o.projectionSpaceVertex.w;
  83. triangleStream.Append(o);
  84. o.worldSpacePosition = i[2].worldSpacePosition;
  85. o.projectionSpaceVertex = i[2].projectionSpaceVertex;
  86. o.dist.xyz = float3(0.0, 0.0, (area / length(edge2))) * o.projectionSpaceVertex.w * wireThickness;
  87. o.dist.w = 1.0 / o.projectionSpaceVertex.w;
  88. triangleStream.Append(o);
  89. }
  90. half4 frag(g2f i) : SV_Target
  91. {
  92. float minDistanceToEdge = min(i.dist[0], min(i.dist[1], i.dist[2])) * i.dist[3];
  93. // Early out if we know we are not on a line segment.
  94. if(minDistanceToEdge > 0.9)
  95. {
  96. return half4(0,0,0,0);
  97. }
  98. // Smooth our line out
  99. float t = exp2(-2 * minDistanceToEdge * minDistanceToEdge);
  100. const half4 colors[11] = {
  101. half4(1.0, 1.0, 1.0, 1.0), // White
  102. half4(1.0, 0.0, 0.0, 1.0), // Red
  103. half4(0.0, 1.0, 0.0, 1.0), // Green
  104. half4(0.0, 0.0, 1.0, 1.0), // Blue
  105. half4(1.0, 1.0, 0.0, 1.0), // Yellow
  106. half4(0.0, 1.0, 1.0, 1.0), // Cyan/Aqua
  107. half4(1.0, 0.0, 1.0, 1.0), // Magenta
  108. half4(0.5, 0.0, 0.0, 1.0), // Maroon
  109. half4(0.0, 0.5, 0.5, 1.0), // Teal
  110. half4(1.0, 0.65, 0.0, 1.0), // Orange
  111. half4(1.0, 1.0, 1.0, 1.0) // White
  112. };
  113. float cameraToVertexDistance = length(_WorldSpaceCameraPos - i.worldSpacePosition.xyz);
  114. int index = clamp(floor(cameraToVertexDistance), 0, 10);
  115. half4 wireColor = colors[index];
  116. half4 finalColor = lerp(float4(0,0,0,1), wireColor, t);
  117. finalColor.a = t;
  118. return finalColor;
  119. }
  120. ENDHLSL
  121. }
  122. }
  123. FallBack "Hidden/Universal Render Pipeline/FallbackError"
  124. }