ThetaRealtimeEquirectangular1080p.shader 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  2. // Copyright (c) 2015 Nora
  3. // Released under the MIT license
  4. // http://opensource.org/licenses/mit-license.php
  5. Shader "Theta/RealtimeEquirectangular1080p"
  6. {
  7. Properties
  8. {
  9. [NoScaleOffset] _MainTex("Texture", 2D) = "white" {}
  10. _UVOffset("UVOffset(Forward UV / Backward UV)", Vector) = (0.0, 0.0, 0.0, 0.0)
  11. [KeywordEnum(Theta S 1080p, Theta S, Theta, Insta360 Air)] _Mode("Mode", Int) = 0
  12. }
  13. SubShader
  14. {
  15. Tags{ "RenderType" = "Overlay" "Queue" = "Overlay" "ForceNoShadowCasting" = "True" }
  16. // Tags{ "RenderType" = "Opaque" "Queue" = "Geometry" "ForceNoShadowCasting" = "True" }
  17. ZTest Always
  18. Cull Off
  19. ZWrite Off
  20. Pass
  21. {
  22. CGPROGRAM
  23. #pragma vertex vert
  24. #pragma fragment frag
  25. #pragma multi_compile _MODE_THETA_S_1080P _MODE_THETA_S _MODE_THETA _MODE_INSTA360_AIR
  26. #include "UnityCG.cginc"
  27. struct appdata
  28. {
  29. float4 vertex : POSITION;
  30. float2 uv : TEXCOORD0;
  31. };
  32. struct v2f
  33. {
  34. float2 uv : TEXCOORD0;
  35. float4 vertex : SV_POSITION;
  36. };
  37. sampler2D _MainTex;
  38. float4 _UVOffset;
  39. #if defined(_MODE_THETA_S_1080P)
  40. #define _RADIUS 0.4425
  41. #define _TEXTURE_Y_OFFSET 0
  42. #define _TEXTURE_Y_SCALE (640.0 / 720.0)
  43. #define _FORWARD_ROTATION_DEGREE 0
  44. #define _BACKWARD_ROTATION_DEGREE 0
  45. #elif defined(_MODE_THETA_S)
  46. #define _RADIUS 0.445
  47. #define _TEXTURE_Y_OFFSET ((720.0 - 640.0) / 720.0)
  48. #define _TEXTURE_Y_SCALE (640.0 / 720.0)
  49. #define _FORWARD_ROTATION_DEGREE 0
  50. #define _BACKWARD_ROTATION_DEGREE 0
  51. #elif defined(_MODE_INSTA360_AIR)
  52. #define _INSTA360_AIR_SENSOR_ROTATION_DEGREE 4.0
  53. #define _RADIUS 0.47
  54. #define _TEXTURE_Y_OFFSET 0
  55. #define _TEXTURE_Y_SCALE 1
  56. #define _FORWARD_ROTATION_DEGREE (-90 + _INSTA360_AIR_SENSOR_ROTATION_DEGREE)
  57. #define _BACKWARD_ROTATION_DEGREE (90 + _INSTA360_AIR_SENSOR_ROTATION_DEGREE)
  58. #else
  59. #define _RADIUS 0.445
  60. #define _TEXTURE_Y_OFFSET 0
  61. #define _TEXTURE_Y_SCALE 1
  62. #define _FORWARD_ROTATION_DEGREE 0
  63. #define _BACKWARD_ROTATION_DEGREE 0
  64. #endif
  65. v2f vert (appdata v)
  66. {
  67. v2f o;
  68. // MVP行列を掛ける
  69. // mul(UNITY_MATRIX_MVP, v.vertex)と同じ処理だけどパフォーマンス良いらしい
  70. o.vertex = UnityObjectToClipPos(v.vertex);
  71. o.uv = v.uv;
  72. // プラットフォームによる射影行列の違いを吸収
  73. o.uv.y *= _ProjectionParams.x;
  74. return o;
  75. }
  76. // 2次元変換行列 (3次元目は平行移動用に使う)
  77. float3x3 rotate_matrix_radian(float rot) {
  78. float sinX = sin(rot);
  79. float cosX = cos(rot);
  80. return float3x3(cosX, -sinX, 0, sinX, cosX, 0, 0, 0, 1);
  81. }
  82. // Scale/Rotate/Translate Matrix群
  83. float3x3 rotate_matrix_degree(float rot) {
  84. return rotate_matrix_radian(rot * UNITY_PI / 180.0);
  85. }
  86. float3x3 scale_matrix(float2 scale) {
  87. return float3x3(scale.x, 0, 0, 0, scale.y, 0, 0, 0, 1);
  88. }
  89. float3x3 scaleX_matrix(float x) {
  90. return float3x3(x, 0, 0, 0, 1, 0, 0, 0, 1);
  91. }
  92. float3x3 scaleY_matrix(float y) {
  93. return float3x3(1, 0, 0, 0, y, 0, 0, 0, 1);
  94. }
  95. float3x3 translate_matrix(float2 vec) {
  96. return float3x3(1, 0, 0, 0, 1, 0, vec.x, vec.y, 1);
  97. }
  98. float3x3 translateX_matrix(float x) {
  99. return float3x3(1, 0, 0, 0, 1, 0, x, 0, 1);
  100. }
  101. float3x3 translateY_matrix(float y) {
  102. return float3x3(1, 0, 0, 0, 1, 0, 0, y, 1);
  103. }
  104. float3x3 texture_matrix3() {
  105. float3x3 mat = float3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
  106. mat = mul(mat, scaleY_matrix(_TEXTURE_Y_SCALE));
  107. mat = mul(mat, translateY_matrix(_TEXTURE_Y_OFFSET));
  108. return mat;
  109. }
  110. // forward用変換行列
  111. // (0,0)を中心として半径1の範囲の座標、をテクスチャ座標に変換するmatrix
  112. // 計算量多いようだが、すべてコンパイル時に解決されるはず。
  113. float3x3 forward_matrix3() {
  114. float3x3 mat = float3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
  115. mat = mul(mat, rotate_matrix_degree(_FORWARD_ROTATION_DEGREE));
  116. mat = mul(mat, translate_matrix(float2(0.5, 0.5)));
  117. // 裏側なので逆方向にする
  118. mat = mul(mat, scaleX_matrix(-1));
  119. mat = mul(mat, translateX_matrix(1));
  120. // XのUV幅は半分なので x0.5
  121. mat = mul(mat, scaleX_matrix(0.5));
  122. // オフセット
  123. mat = mul(mat, translate_matrix(_UVOffset.yx));
  124. mat = mul(mat, texture_matrix3());
  125. return mat;
  126. }
  127. // backward用変換行列
  128. // (0,0)を中心として半径1の範囲の座標、をテクスチャ座標に変換するmatrix
  129. // 計算量多いようだが、すべてコンパイル時に解決されるはず。
  130. float3x3 backward_matrix3() {
  131. float3x3 mat = float3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
  132. mat = mul(mat, rotate_matrix_degree(_BACKWARD_ROTATION_DEGREE));
  133. mat = mul(mat, translate_matrix(float2(0.5, 0.5)));
  134. // 片目分のUV幅は半分なので x0.5
  135. mat = mul(mat, scaleX_matrix(0.5));
  136. // 右側なので +0.5
  137. mat = mul(mat, translateX_matrix(0.5));
  138. // Y逆方向
  139. mat = mul(mat, scaleY_matrix(-1));
  140. mat = mul(mat, translateY_matrix(1));
  141. // オフセット
  142. mat = mul(mat, translate_matrix(_UVOffset.wz));
  143. mat = mul(mat, texture_matrix3());
  144. return mat;
  145. }
  146. float2 convert_for_forward(float2 st) {
  147. return mul(float3(st.x, st.y, 1), forward_matrix3()).xy;
  148. }
  149. float2 convert_for_backward(float2 st) {
  150. return mul(float3(st.x, st.y, 1), backward_matrix3()).xy;
  151. }
  152. float4 frag(v2f i) : SV_Target
  153. {
  154. // float2 revUV = i.uv;
  155. float2 revUV = float2(i.uv.x, 1.0 - i.uv.y); // THETAの画像そのままだと上下が入れ替わってしまうので対策
  156. if (i.uv.x <= 0.5) {
  157. revUV.x = 1.0 - revUV.x * 2.0;
  158. }
  159. else {
  160. revUV.x = 1.0 - (revUV.x - 0.5) * 2.0;
  161. }
  162. revUV *= UNITY_PI;
  163. float3 p = float3(cos(revUV.x), cos(revUV.y), sin(revUV.x));
  164. p.xz *= sqrt(1.0 - p.y * p.y);
  165. float r = 1.0 - asin(p.z) / (UNITY_PI / 2.0);
  166. float2 st = float2(p.y, p.x);
  167. st *= r / sqrt(1.0 - p.z * p.z);
  168. st *= _RADIUS;
  169. // stは (0,0)を中心としたFisheye座標
  170. float4 col;
  171. if (i.uv.x <= 0.5)
  172. { // 後
  173. st = convert_for_backward(st);
  174. #if !defined(SHADER_API_OPENGL)
  175. col = tex2Dlod(_MainTex, float4(st, 0.0, 0.0));
  176. #else // Memo: OpenGL not supported tex2Dlod.( Texture should be setting to generateMipMap = off. )
  177. col = tex2D(_MainTex, st);
  178. #endif
  179. }
  180. else {
  181. // 前
  182. st = convert_for_forward(st);
  183. #if !defined(SHADER_API_OPENGL)
  184. col = tex2Dlod(_MainTex, float4(st, 0.0, 0.0));
  185. #else // Memo: OpenGL not supported tex2Dlod.( Texture should be setting to generateMipMap = off. )
  186. col = tex2D(_MainTex, st);
  187. #endif
  188. }
  189. return col;
  190. }
  191. ENDCG
  192. }
  193. }
  194. }