Display Viewport.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************
  5. There are 3 types of shaders:
  6. 2D Shaders - lines, images, text, rectangles, circles, ...
  7. vertex position affected by Coords (in DX9 Coords are adjusted by pixel center)
  8. 3D Shaders - 3d models
  9. vertex position affected by 'ProjMatrix' (in DX9 'ProjMatrix' is adjusted by pixel center)
  10. PostProcess Shaders - bloom, ambient occlusion, motion blur, depth of field, sun rays, ..
  11. vertex position calculated completely on the CPU (in DX9 adjusted by pixel center in the shader)
  12. /******************************************************************************/
  13. // SETTINGS
  14. /******************************************************************************/
  15. void Display::ViewportSettings::get()
  16. {
  17. from =D.viewFrom ();
  18. range =D.viewRange ();
  19. fov =D.viewFov ();
  20. fov_mode=D.viewFovMode();
  21. rect =D.viewRect ();
  22. }
  23. void Display::ViewportSettings::set()C
  24. {
  25. D.view(rect, from, range, fov, fov_mode);
  26. }
  27. /******************************************************************************/
  28. // VIEWPORT
  29. /******************************************************************************/
  30. Display::Viewport& Display::Viewport::set3DFrom(C Viewport &src)
  31. {
  32. from =src.from;
  33. range =src.range;
  34. fov =src.fov;
  35. fov_sin =src.fov_sin;
  36. fov_cos =src.fov_cos;
  37. fov_tan =src.fov_tan;
  38. fov_mode=src.fov_mode;
  39. return T;
  40. }
  41. /******************************************************************************/
  42. Display::Viewport& Display::Viewport::setRect(C RectI &recti)
  43. {
  44. T.recti=recti;
  45. Clamp(T.recti.min.x, 0, Renderer.resW()-1); Clamp(T.recti.max.x, T.recti.min.x, Renderer.resW());
  46. Clamp(T.recti.min.y, 0, Renderer.resH()-1); Clamp(T.recti.max.y, T.recti.min.y, Renderer.resH());
  47. T.full=(T.recti.min.x==0 && T.recti.min.y==0 && T.recti.max.x==Renderer.resW() && T.recti.max.y==Renderer.resH());
  48. return T;
  49. }
  50. /******************************************************************************/
  51. Display::Viewport& Display::Viewport::setFrom (Flt from ) {T.from =from ; return T;}
  52. Display::Viewport& Display::Viewport::setRange(Flt range) {T.range=range; return T;}
  53. /******************************************************************************/
  54. Display::Viewport& Display::Viewport::setFov()
  55. {
  56. Flt aspect=(D._view_square_pixel ? 1 : D._pixel_aspect)*recti.aspect();
  57. if(FovPerspective(fov_mode))
  58. {
  59. switch(fov_mode)
  60. {
  61. case FOV_X:
  62. Clamp(fov.x, EPS, PI-EPS);
  63. fov.y=2*Atan(Tan(fov.x*0.5f)/aspect);
  64. break;
  65. case FOV_Y:
  66. Clamp(fov.y, EPS, PI-EPS);
  67. fov.x=2*Atan(Tan(fov.y*0.5f)*aspect);
  68. break;
  69. case FOV_XY:
  70. Clamp(fov.x, EPS, PI-EPS);
  71. Clamp(fov.y, EPS, PI-EPS);
  72. break;
  73. }
  74. CosSin(fov_cos.x, fov_sin.x, fov.x*0.5f);
  75. CosSin(fov_cos.y, fov_sin.y, fov.y*0.5f);
  76. fov_tan=fov_sin/fov_cos;
  77. }else
  78. {
  79. switch(fov_mode)
  80. {
  81. /*case FOV_ORTHO:
  82. fov.x=fov.x;
  83. fov.y=fov.y;
  84. break;*/
  85. case FOV_ORTHO_X:
  86. //fov.x=fov.x;
  87. fov.y=fov.x/aspect;
  88. break;
  89. case FOV_ORTHO_Y:
  90. //fov.y=fov.y;
  91. fov.x=fov.y*aspect;
  92. break;
  93. }
  94. fov_tan=fov;
  95. }
  96. return T;
  97. }
  98. Display::Viewport& Display::Viewport::setFov(C Vec2 &fov, FOV_MODE fov_mode)
  99. {
  100. T.fov =fov;
  101. T.fov_mode=fov_mode;
  102. return setFov();
  103. }
  104. Display::Viewport& Display::Viewport::set(C RectI &recti, Flt from, Flt range, C Vec2 &fov, FOV_MODE fov_mode)
  105. {
  106. return setRect(recti).setFrom(from).setRange(range).setFov(fov, fov_mode);
  107. }
  108. /******************************************************************************
  109. inline Vec2 FracToPosXY(Vec2 screen) // return view space xy position at z=1
  110. {
  111. (((screen-Viewport.min)/Viewport.size)-0.5)/Vec2(0.5,-0.5)*z*Viewport.fov_tan;
  112. (screen/Viewport.size-(Viewport.min/Viewport.size+0.5))*z*(Viewport.fov_tan/Vec2(0.5,-0.5))
  113. ( screen * (Viewport.fov_tan/Vec2(0.5,-0.5)/Viewport.size) - ((Viewport.min/Viewport.size+0.5)*(Viewport.fov_tan/Vec2(0.5,-0.5))) ) * z
  114. return screen * (Viewport.fov_tan/Vec2(0.5,-0.5)) - (0.5*(Viewport.fov_tan/Vec2(0.5,-0.5)));
  115. return screen * Viewport.FracToPosXY.xy + Viewport.FracToPosXY.zw ;
  116. }
  117. inline Vec2 ScreenToPosXY(Vec2 screen) // return view space xy position at z=1
  118. {
  119. return screen * (Viewport.fov_tan/Vec2(0.5,-0.5)/Viewport.size) - ((Viewport.min/Viewport.size+0.5)*(Viewport.fov_tan/Vec2(0.5,-0.5)));
  120. return screen * Viewport.ScreenToPosXY.xy + Viewport.ScreenToPosXY.zw ;
  121. }
  122. inline Vec2 PosToScreen(Vec pos)
  123. {
  124. return (pos.xy/pos.z) * ((Vec2(0.5,-0.5)/Viewport.fov_tan+0.5)*Viewport.size) + Viewport.min;
  125. }
  126. inline Vec2 PosToScreen(Vec4 pos)
  127. {
  128. Vec2 screen=pos.xy/pos.w*Vec2(0.5,-0.5)+0.5; return screen*Viewport.size+(Viewport.min+0.5/RTSizeI);
  129. return (pos.xy/pos.w*Vec2(0.5,-0.5)+0.5)*Viewport.size+(Viewport.min+0.5/RTSizeI);
  130. return (pos.xy/pos.w) * (Vec2(0.5,-0.5)*Viewport.size) + (0.5*Viewport.size+Viewport.min+0.5/RTSizeI);
  131. return (pos.xy/pos.w) * Viewport.PosToScreen.xy + Viewport.PosToScreen.zw ;
  132. }
  133. /******************************************************************************/
  134. Display::Viewport& Display::Viewport::setViewport(Bool allow_proj_matrix_update)
  135. {
  136. #if DX9
  137. D.viewport(recti, allow_proj_matrix_update);
  138. #elif DX11
  139. D.viewport(recti, allow_proj_matrix_update);
  140. #elif GL
  141. if(D.mainFBO())
  142. {
  143. RectI r; r.setX(recti.min.x, recti.max.x); r.min.y=Renderer.resH()-recti.max.y; r.max.y=r.min.y+recti.h(); D.viewport(r, allow_proj_matrix_update);
  144. }else D.viewport(recti, allow_proj_matrix_update);
  145. #endif
  146. return T;
  147. }
  148. /******************************************************************************/
  149. #pragma pack(push, 4)
  150. struct GpuViewport
  151. {
  152. Flt from, range;//, ortho;
  153. Vec2 center, size, size_fov_tan;
  154. Vec2 FracToPosXY[2], ScreenToPosXY[2], PosToScreen[2]; // helpers
  155. };
  156. #pragma pack(pop)
  157. Display::Viewport& Display::Viewport::setShader(Flt *offset)
  158. {
  159. // helpers
  160. Vec2 size =Renderer.res(),
  161. v_min=Vec2(recti.min)/size,
  162. v_ft =fov_tan/Vec2(0.5f, -0.5f);
  163. GpuViewport v;
  164. v.from =from ;
  165. v.range =range;
  166. //v.ortho =FovOrthogonal(fov_mode);
  167. v.center =recti.centerF()/size;
  168. v.size =recti.size ()/size;
  169. v.size_fov_tan=v.size/fov_tan;
  170. v.FracToPosXY[0]= v_ft;
  171. v.FracToPosXY[1]=-0.5f*v_ft;
  172. v.ScreenToPosXY[0]= v_ft/v.size;
  173. v.ScreenToPosXY[1]=-(v_min/v.size+0.5f)*v_ft;
  174. #if DX9 || DX11
  175. v.PosToScreen[0]=Vec2(0.5f, -0.5f)*v.size;
  176. v.PosToScreen[1]= 0.5f *v.size + v_min;
  177. #elif GL
  178. v.PosToScreen[0]=Vec2(0.5f, 0.5f)*v.size;
  179. v.PosToScreen[1]= 0.5f *v.size + v_min;
  180. #endif
  181. if(offset)
  182. {
  183. Flt o=*offset*v.ScreenToPosXY[0].x*0.25f;
  184. v. FracToPosXY[1].x-=o;
  185. v.ScreenToPosXY[1].x-=o;
  186. //v.PosToScreen [1].x this shouldn't be modified because we're referring to screen which is already offsetted (this was tested on rendering fur which uses 'PosToScreen')
  187. }
  188. Sh.h_Viewport->set(v);
  189. return T;
  190. }
  191. inline Dbl DelinearizeDepth(Dbl z, Dbl mp_z_z, Dbl mp_w_z, Bool perspective)
  192. {
  193. return perspective ? (z*mp_z_z+mp_w_z)/z : z*mp_z_z+REVERSE_DEPTH;
  194. }
  195. inline Dbl LinearizeDepth(Dbl w, Dbl mp_z_z, Dbl mp_w_z, Bool perspective)
  196. {
  197. return perspective ? mp_w_z/(w-mp_z_z) : (w-REVERSE_DEPTH)/mp_z_z;
  198. }
  199. Flt DepthError(Dbl from, Dbl range, Dbl z, Bool perspective, Int bits)
  200. {
  201. Dbl v, mp_z_z, mp_w_z;
  202. if(perspective) // in perspective we have viewport depth ranges from "from .. range"
  203. {
  204. v=range;
  205. }else // in orthogonal we have viewport depth ranges from "0 .. range"
  206. {
  207. from=0;
  208. v =1;
  209. }
  210. v/=range-from;
  211. #if REVERSE_DEPTH
  212. if(perspective)
  213. {
  214. mp_z_z=-v+1;
  215. mp_w_z= v*from;
  216. }else
  217. {
  218. mp_z_z=-v;
  219. mp_w_z= 1;
  220. }
  221. #else
  222. {
  223. mp_z_z=v;
  224. mp_w_z=v*-from;
  225. }
  226. #endif
  227. Dbl w=DelinearizeDepth(z , mp_z_z, mp_w_z, perspective), w1=w+1.0/(1ull<<bits),
  228. z1= LinearizeDepth(w1, mp_z_z, mp_w_z, perspective);
  229. return Abs(z1-z);
  230. }
  231. Display::Viewport& Display::Viewport::setProjMatrix(Bool set_frustum) // !! must be the same as "Flt DepthError" !!
  232. {
  233. Dbl z, from, range=T.range; // use 'Dbl' to perform computations in best precision because we need 'ProjMatrix' to be as precise as possible
  234. if(FovPerspective(fov_mode)) // in perspective we have viewport depth ranges from "from .. range"
  235. {
  236. from=T.from;
  237. z =range;
  238. ProjMatrix.x .x=1/fov_tan.x;
  239. ProjMatrix.y .y=1/fov_tan.y;
  240. ProjMatrix.z .w=1;
  241. ProjMatrix.pos.w=0;
  242. }else // in orthogonal we have viewport depth ranges from "0 .. range"
  243. {
  244. from=0;
  245. z =1;
  246. ProjMatrix.x .x=1/fov.x;
  247. ProjMatrix.y .y=1/fov.y;
  248. ProjMatrix.z .w=0;
  249. ProjMatrix.pos.w=1;
  250. }
  251. z/=range-from;
  252. #if REVERSE_DEPTH
  253. if(FovPerspective(fov_mode))
  254. {
  255. ProjMatrix.z .z=-z+1;
  256. ProjMatrix.pos.z= z*from;
  257. }else
  258. {
  259. ProjMatrix.z .z=-z;
  260. ProjMatrix.pos.z= 1;
  261. }
  262. #else
  263. {
  264. ProjMatrix.z .z=z;
  265. ProjMatrix.pos.z=z*-from;
  266. }
  267. #endif
  268. #if DEBUG && 0
  269. #pragma message("!! Warning: Use this only for debugging !!")
  270. Vec4 p; Dbl w;
  271. p=Vec4(0, 0, from , 1)*ProjMatrix; p.z/=p.w; w=DelinearizeDepth( from , ProjMatrix.z.z, ProjMatrix.pos.z, FovPerspective(fov_mode)); z=LinearizeDepth(w, ProjMatrix.z.z, ProjMatrix.pos.z, FovPerspective(fov_mode));
  272. p=Vec4(0, 0, range , 1)*ProjMatrix; p.z/=p.w; w=DelinearizeDepth( range , ProjMatrix.z.z, ProjMatrix.pos.z, FovPerspective(fov_mode)); z=LinearizeDepth(w, ProjMatrix.z.z, ProjMatrix.pos.z, FovPerspective(fov_mode));
  273. p=Vec4(0, 0, Avg(from, range), 1)*ProjMatrix; p.z/=p.w; w=DelinearizeDepth(Avg(from, range), ProjMatrix.z.z, ProjMatrix.pos.z, FovPerspective(fov_mode)); z=LinearizeDepth(w, ProjMatrix.z.z, ProjMatrix.pos.z, FovPerspective(fov_mode)); // should be 0.5f for orthogonal (but not perspective)
  274. #endif
  275. SetProjMatrix();
  276. if(set_frustum)Frustum.set();
  277. return T;
  278. }
  279. /******************************************************************************/
  280. }
  281. /******************************************************************************/