暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PaniniProjection.shader 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. Shader "Hidden/Universal Render Pipeline/PaniniProjection"
  2. {
  3. HLSLINCLUDE
  4. #pragma multi_compile_local _GENERIC _UNIT_DISTANCE
  5. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  6. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/DynamicScalingClamping.hlsl"
  7. #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
  8. float4 _Params;
  9. // Back-ported & adapted from the work of the Stockholm demo team - thanks Lasse
  10. float2 Panini_UnitDistance(float2 view_pos)
  11. {
  12. // Given
  13. // S----------- E--X-------
  14. // | ` . /,´
  15. // |-- --- Q
  16. // 1 | ,´/ `
  17. // | ,´ / ´
  18. // | ,´ / `
  19. // | ,´ / .
  20. // O` / .
  21. // | / `
  22. // | / ´
  23. // 1 | / ´
  24. // | / ´
  25. // |/_ . ´
  26. // P
  27. //
  28. // Have E
  29. // Want to find X
  30. //
  31. // First apply tangent-secant theorem to find Q
  32. // PE*QE = SE*SE
  33. // QE = PE-PQ
  34. // PQ = PE-(SE*SE)/PE
  35. // Q = E*(PQ/PE)
  36. // Then project Q to find X
  37. const float d = 1.0;
  38. const float view_dist = 2.0;
  39. const float view_dist_sq = 4.0;
  40. float view_hyp = sqrt(view_pos.x * view_pos.x + view_dist_sq);
  41. float cyl_hyp = view_hyp - (view_pos.x * view_pos.x) / view_hyp;
  42. float cyl_hyp_frac = cyl_hyp / view_hyp;
  43. float cyl_dist = view_dist * cyl_hyp_frac;
  44. float2 cyl_pos = view_pos * cyl_hyp_frac;
  45. return cyl_pos / (cyl_dist - d);
  46. }
  47. float2 Panini_Generic(float2 view_pos, float d)
  48. {
  49. // Given
  50. // S----------- E--X-------
  51. // | ` ~. /,´
  52. // |-- --- Q
  53. // | ,/ `
  54. // 1 | ,´/ `
  55. // | ,´ / ´
  56. // | ,´ / ´
  57. // |,` / ,
  58. // O /
  59. // | / ,
  60. // d | /
  61. // | / ,
  62. // |/ .
  63. // P
  64. // | ´
  65. // | , ´
  66. // +- ´
  67. //
  68. // Have E
  69. // Want to find X
  70. //
  71. // First compute line-circle intersection to find Q
  72. // Then project Q to find X
  73. float view_dist = 1.0 + d;
  74. float view_hyp_sq = view_pos.x * view_pos.x + view_dist * view_dist;
  75. float isect_D = view_pos.x * d;
  76. float isect_discrim = view_hyp_sq - isect_D * isect_D;
  77. float cyl_dist_minus_d = (-isect_D * view_pos.x + view_dist * sqrt(isect_discrim)) / view_hyp_sq;
  78. float cyl_dist = cyl_dist_minus_d + d;
  79. float2 cyl_pos = view_pos * (cyl_dist / view_dist);
  80. return cyl_pos / (cyl_dist - d);
  81. }
  82. half4 FragPaniniProjection(Varyings input) : SV_Target
  83. {
  84. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  85. float2 view_pos = (2.0 * input.texcoord - 1.0) * _Params.xy * _Params.w;
  86. #if _GENERIC
  87. float2 proj_pos = Panini_Generic(view_pos, _Params.z);
  88. #else // _UNIT_DISTANCE
  89. float2 proj_pos = Panini_UnitDistance(view_pos);
  90. #endif
  91. float2 proj_ndc = proj_pos / _Params.xy;
  92. float2 coords = ClampAndScaleUVForBilinear(proj_ndc * 0.5 + 0.5);
  93. return SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, coords);
  94. }
  95. ENDHLSL
  96. SubShader
  97. {
  98. Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline"}
  99. LOD 100
  100. ZTest Always ZWrite Off Cull Off
  101. Pass
  102. {
  103. Name "Panini Projection"
  104. HLSLPROGRAM
  105. #pragma vertex Vert
  106. #pragma fragment FragPaniniProjection
  107. ENDHLSL
  108. }
  109. }
  110. }