DXManager.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. using System.Drawing.Drawing2D;
  2. using System.Drawing.Imaging;
  3. using Client.MirControls;
  4. using Client.MirScenes;
  5. using SlimDX;
  6. using SlimDX.Direct3D9;
  7. using Blend = SlimDX.Direct3D9.Blend;
  8. namespace Client.MirGraphics
  9. {
  10. class DXManager
  11. {
  12. public static List<MImage> TextureList = new List<MImage>();
  13. public static List<MirControl> ControlList = new List<MirControl>();
  14. public static Device Device;
  15. public static Sprite Sprite;
  16. public static Line Line;
  17. public static Surface CurrentSurface;
  18. public static Surface MainSurface;
  19. public static PresentParameters Parameters;
  20. public static bool DeviceLost;
  21. public static float Opacity = 1F;
  22. public static bool Blending;
  23. public static float BlendingRate;
  24. public static BlendMode BlendingMode;
  25. public static Texture RadarTexture;
  26. public static List<Texture> Lights = new List<Texture>();
  27. public static Texture PoisonDotBackground;
  28. public static Texture FloorTexture, LightTexture;
  29. public static Surface FloorSurface, LightSurface;
  30. public static PixelShader GrayScalePixelShader;
  31. public static PixelShader NormalPixelShader;
  32. public static PixelShader MagicPixelShader;
  33. public static bool GrayScale;
  34. public static Point[] LightSizes =
  35. {
  36. new Point(125,95),
  37. new Point(205,156),
  38. new Point(285,217),
  39. new Point(365,277),
  40. new Point(445,338),
  41. new Point(525,399),
  42. new Point(605,460),
  43. new Point(685,521),
  44. new Point(765,581),
  45. new Point(845,642),
  46. new Point(925,703)
  47. };
  48. public static void Create()
  49. {
  50. Parameters = new PresentParameters
  51. {
  52. BackBufferFormat = Format.X8R8G8B8,
  53. PresentFlags = PresentFlags.LockableBackBuffer,
  54. BackBufferWidth = Settings.ScreenWidth,
  55. BackBufferHeight = Settings.ScreenHeight,
  56. SwapEffect = SwapEffect.Discard,
  57. PresentationInterval = Settings.FPSCap ? PresentInterval.One : PresentInterval.Immediate,
  58. Windowed = !Settings.FullScreen,
  59. };
  60. Direct3D d3d = new Direct3D();
  61. Capabilities devCaps = d3d.GetDeviceCaps(0, DeviceType.Hardware);
  62. DeviceType devType = DeviceType.Reference;
  63. CreateFlags devFlags = CreateFlags.HardwareVertexProcessing;
  64. if (devCaps.VertexShaderVersion.Major >= 2 && devCaps.PixelShaderVersion.Major >= 2)
  65. devType = DeviceType.Hardware;
  66. if ((devCaps.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0)
  67. devFlags = CreateFlags.HardwareVertexProcessing;
  68. if ((devCaps.DeviceCaps & DeviceCaps.PureDevice) != 0)
  69. devFlags |= CreateFlags.PureDevice;
  70. Device = new Device(d3d, d3d.Adapters.DefaultAdapter.Adapter, devType, Program.Form.Handle, devFlags, Parameters);
  71. Device.SetDialogBoxMode(true);
  72. LoadTextures();
  73. LoadPixelsShaders();
  74. }
  75. private static unsafe void LoadPixelsShaders()
  76. {
  77. var shaderNormalPath = Settings.ShadersPath + "normal.ps";
  78. var shaderGrayScalePath = Settings.ShadersPath + "grayscale.ps";
  79. var shaderMagicPath = Settings.ShadersPath + "magic.ps";
  80. if (System.IO.File.Exists(shaderNormalPath))
  81. {
  82. using (var gs = ShaderBytecode.AssembleFromFile(shaderNormalPath, ShaderFlags.None))
  83. NormalPixelShader = new PixelShader(Device, gs);
  84. }
  85. if (System.IO.File.Exists(shaderGrayScalePath))
  86. {
  87. using (var gs = ShaderBytecode.AssembleFromFile(shaderGrayScalePath, ShaderFlags.None))
  88. GrayScalePixelShader = new PixelShader(Device, gs);
  89. }
  90. if (System.IO.File.Exists(shaderMagicPath))
  91. {
  92. using (var gs = ShaderBytecode.AssembleFromFile(shaderMagicPath, ShaderFlags.None))
  93. MagicPixelShader = new PixelShader(Device, gs);
  94. }
  95. }
  96. private static unsafe void LoadTextures()
  97. {
  98. Sprite = new Sprite(Device);
  99. Line = new Line(Device) { Width = 1F };
  100. MainSurface = Device.GetBackBuffer(0, 0);
  101. CurrentSurface = MainSurface;
  102. Device.SetRenderTarget(0, MainSurface);
  103. if (RadarTexture == null || RadarTexture.Disposed)
  104. {
  105. RadarTexture = new Texture(Device, 2, 2, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
  106. DataRectangle stream = RadarTexture.LockRectangle(0, LockFlags.Discard);
  107. using (Bitmap image = new Bitmap(2, 2, 8, PixelFormat.Format32bppArgb, stream.Data.DataPointer))
  108. using (Graphics graphics = Graphics.FromImage(image))
  109. graphics.Clear(Color.White);
  110. RadarTexture.UnlockRectangle(0);
  111. }
  112. if (PoisonDotBackground == null || PoisonDotBackground.Disposed)
  113. {
  114. PoisonDotBackground = new Texture(Device, 5, 5, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
  115. DataRectangle stream = PoisonDotBackground.LockRectangle(0, LockFlags.Discard);
  116. using (Bitmap image = new Bitmap(5, 5, 20, PixelFormat.Format32bppArgb, stream.Data.DataPointer))
  117. using (Graphics graphics = Graphics.FromImage(image))
  118. graphics.Clear(Color.White);
  119. PoisonDotBackground.UnlockRectangle(0);
  120. }
  121. CreateLights();
  122. }
  123. private unsafe static void CreateLights()
  124. {
  125. for (int i = Lights.Count - 1; i >= 0; i--)
  126. Lights[i].Dispose();
  127. Lights.Clear();
  128. for (int i = 1; i < LightSizes.Length; i++)
  129. {
  130. // int width = 125 + (57 *i);
  131. //int height = 110 + (57 * i);
  132. int width = LightSizes[i].X;
  133. int height = LightSizes[i].Y;
  134. Texture light = new Texture(Device, width, height, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
  135. DataRectangle stream = light.LockRectangle(0, LockFlags.Discard);
  136. using (Bitmap image = new Bitmap(width, height, width * 4, PixelFormat.Format32bppArgb, stream.Data.DataPointer))
  137. {
  138. using (Graphics graphics = Graphics.FromImage(image))
  139. {
  140. using (GraphicsPath path = new GraphicsPath())
  141. {
  142. //path.AddEllipse(new Rectangle(0, 0, width, height));
  143. //using (PathGradientBrush brush = new PathGradientBrush(path))
  144. //{
  145. // graphics.Clear(Color.FromArgb(0, 0, 0, 0));
  146. // brush.SurroundColors = new[] { Color.FromArgb(0, 255, 255, 255) };
  147. // brush.CenterColor = Color.FromArgb(255, 255, 255, 255);
  148. // graphics.FillPath(brush, path);
  149. // graphics.Save();
  150. //}
  151. path.AddEllipse(new Rectangle(0, 0, width, height));
  152. using (PathGradientBrush brush = new PathGradientBrush(path))
  153. {
  154. Color[] blendColours = { Color.White,
  155. Color.FromArgb(255,210,210,210),
  156. Color.FromArgb(255,160,160,160),
  157. Color.FromArgb(255,70,70,70),
  158. Color.FromArgb(255,40,40,40),
  159. Color.FromArgb(0,0,0,0)};
  160. float[] radiusPositions = { 0f, .20f, .40f, .60f, .80f, 1.0f };
  161. ColorBlend colourBlend = new ColorBlend();
  162. colourBlend.Colors = blendColours;
  163. colourBlend.Positions = radiusPositions;
  164. graphics.Clear(Color.FromArgb(0, 0, 0, 0));
  165. brush.InterpolationColors = colourBlend;
  166. brush.SurroundColors = blendColours;
  167. brush.CenterColor = Color.White;
  168. graphics.FillPath(brush, path);
  169. graphics.Save();
  170. }
  171. }
  172. }
  173. }
  174. light.UnlockRectangle(0);
  175. //light.Disposing += (o, e) => Lights.Remove(light);
  176. Lights.Add(light);
  177. }
  178. }
  179. public static void SetSurface(Surface surface)
  180. {
  181. if (CurrentSurface == surface)
  182. return;
  183. Sprite.Flush();
  184. CurrentSurface = surface;
  185. Device.SetRenderTarget(0, surface);
  186. }
  187. public static void SetGrayscale(bool value)
  188. {
  189. GrayScale = value;
  190. if (value == true)
  191. {
  192. if (Device.PixelShader == GrayScalePixelShader) return;
  193. Sprite.Flush();
  194. Device.PixelShader = GrayScalePixelShader;
  195. }
  196. else
  197. {
  198. if (Device.PixelShader == null) return;
  199. Sprite.Flush();
  200. Device.PixelShader = null;
  201. }
  202. }
  203. public static void DrawOpaque(Texture texture, Rectangle? sourceRect, Vector3? position, Color4 color, float opacity)
  204. {
  205. color.Alpha = opacity;
  206. Draw(texture, sourceRect, position, color);
  207. }
  208. public static void Draw(Texture texture, Rectangle? sourceRect, Vector3? position, Color4 color)
  209. {
  210. Sprite.Draw(texture, sourceRect, Vector3.Zero, position, color);
  211. CMain.DPSCounter++;
  212. }
  213. public static void AttemptReset()
  214. {
  215. try
  216. {
  217. Result result = DXManager.Device.TestCooperativeLevel();
  218. if (result.Code == ResultCode.DeviceLost.Code) return;
  219. if (result.Code == ResultCode.DeviceNotReset.Code)
  220. {
  221. DXManager.ResetDevice();
  222. return;
  223. }
  224. if (result.Code != ResultCode.Success.Code) return;
  225. DXManager.DeviceLost = false;
  226. }
  227. catch
  228. {
  229. }
  230. }
  231. public static void ResetDevice()
  232. {
  233. DXManager.CleanUp();
  234. DXManager.DeviceLost = true;
  235. if (DXManager.Parameters == null) return;
  236. Size clientSize = Program.Form.ClientSize;
  237. if (clientSize.Width == 0 || clientSize.Height == 0) return;
  238. DXManager.Parameters.Windowed = !Settings.FullScreen;
  239. DXManager.Parameters.BackBufferWidth = clientSize.Width;
  240. DXManager.Parameters.BackBufferHeight = clientSize.Height;
  241. DXManager.Parameters.PresentationInterval = Settings.FPSCap ? PresentInterval.Default : PresentInterval.Immediate;
  242. DXManager.Device.Reset(DXManager.Parameters);
  243. DXManager.LoadTextures();
  244. }
  245. public static void AttemptRecovery()
  246. {
  247. try
  248. {
  249. Sprite.End();
  250. }
  251. catch
  252. {
  253. }
  254. try
  255. {
  256. Device.EndScene();
  257. }
  258. catch
  259. {
  260. }
  261. try
  262. {
  263. MainSurface = Device.GetBackBuffer(0, 0);
  264. CurrentSurface = MainSurface;
  265. Device.SetRenderTarget(0, MainSurface);
  266. }
  267. catch
  268. {
  269. }
  270. }
  271. public static void SetOpacity(float opacity)
  272. {
  273. if (Opacity == opacity)
  274. return;
  275. Sprite.Flush();
  276. Device.SetRenderState(RenderState.AlphaBlendEnable, true);
  277. if (opacity >= 1 || opacity < 0)
  278. {
  279. Device.SetRenderState(RenderState.SourceBlend, SlimDX.Direct3D9.Blend.SourceAlpha);
  280. Device.SetRenderState(RenderState.DestinationBlend, SlimDX.Direct3D9.Blend.InverseSourceAlpha);
  281. Device.SetRenderState(RenderState.SourceBlendAlpha, Blend.One);
  282. Device.SetRenderState(RenderState.BlendFactor, Color.FromArgb(255, 255, 255, 255).ToArgb());
  283. }
  284. else
  285. {
  286. Device.SetRenderState(RenderState.SourceBlend, Blend.BlendFactor);
  287. Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseBlendFactor);
  288. Device.SetRenderState(RenderState.SourceBlendAlpha, Blend.SourceAlpha);
  289. Device.SetRenderState(RenderState.BlendFactor, Color.FromArgb((byte)(255 * opacity), (byte)(255 * opacity), (byte)(255 * opacity), (byte)(255 * opacity)).ToArgb());
  290. }
  291. Opacity = opacity;
  292. Sprite.Flush();
  293. }
  294. public static void SetBlend(bool value, float rate = 1F, BlendMode mode = BlendMode.NORMAL)
  295. {
  296. if (value == Blending && BlendingRate == rate && BlendingMode == mode) return;
  297. Blending = value;
  298. BlendingRate = rate;
  299. BlendingMode = mode;
  300. Sprite.Flush();
  301. Sprite.End();
  302. if (Blending)
  303. {
  304. Sprite.Begin(SpriteFlags.DoNotSaveState);
  305. Device.SetRenderState(RenderState.AlphaBlendEnable, true);
  306. switch (BlendingMode)
  307. {
  308. case BlendMode.INVLIGHT:
  309. Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
  310. Device.SetRenderState(RenderState.SourceBlend, Blend.BlendFactor);
  311. Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceColor);
  312. break;
  313. default:
  314. Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
  315. Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
  316. break;
  317. }
  318. Device.SetRenderState(RenderState.BlendFactor, Color.FromArgb((byte)(255 * BlendingRate), (byte)(255 * BlendingRate),
  319. (byte)(255 * BlendingRate), (byte)(255 * BlendingRate)).ToArgb());
  320. }
  321. else
  322. Sprite.Begin(SpriteFlags.AlphaBlend);
  323. Device.SetRenderTarget(0, CurrentSurface);
  324. }
  325. public static void SetNormal(float blend, Color tintcolor)
  326. {
  327. if (Device.PixelShader == NormalPixelShader)
  328. return;
  329. Sprite.Flush();
  330. Device.PixelShader = NormalPixelShader;
  331. Device.SetPixelShaderConstant(0, new Vector4[] { new Vector4(1.0F, 1.0F, 1.0F, blend) });
  332. Device.SetPixelShaderConstant(1, new Vector4[] { new Vector4(tintcolor.R / 255, tintcolor.G / 255, tintcolor.B / 255, 1.0F) });
  333. Sprite.Flush();
  334. }
  335. public static void SetGrayscale(float blend, Color tintcolor)
  336. {
  337. if (Device.PixelShader == GrayScalePixelShader)
  338. return;
  339. Sprite.Flush();
  340. Device.PixelShader = GrayScalePixelShader;
  341. Device.SetPixelShaderConstant(0, new Vector4[] { new Vector4(1.0F, 1.0F, 1.0F, blend) });
  342. Device.SetPixelShaderConstant(1, new Vector4[] { new Vector4(tintcolor.R / 255, tintcolor.G / 255, tintcolor.B / 255, 1.0F) });
  343. Sprite.Flush();
  344. }
  345. public static void SetBlendMagic(float blend, Color tintcolor)
  346. {
  347. if (Device.PixelShader == MagicPixelShader || MagicPixelShader == null)
  348. return;
  349. Sprite.Flush();
  350. Device.PixelShader = MagicPixelShader;
  351. Device.SetPixelShaderConstant(0, new Vector4[] { new Vector4(1.0F, 1.0F, 1.0F, blend) });
  352. Device.SetPixelShaderConstant(1, new Vector4[] { new Vector4(tintcolor.R / 255, tintcolor.G / 255, tintcolor.B / 255, 1.0F) });
  353. Sprite.Flush();
  354. }
  355. public static void Clean()
  356. {
  357. for (int i = TextureList.Count - 1; i >= 0; i--)
  358. {
  359. MImage m = TextureList[i];
  360. if (m == null)
  361. {
  362. TextureList.RemoveAt(i);
  363. continue;
  364. }
  365. if (CMain.Time <= m.CleanTime) continue;
  366. m.DisposeTexture();
  367. }
  368. for (int i = ControlList.Count - 1; i >= 0; i--)
  369. {
  370. MirControl c = ControlList[i];
  371. if (c == null)
  372. {
  373. ControlList.RemoveAt(i);
  374. continue;
  375. }
  376. if (CMain.Time <= c.CleanTime) continue;
  377. c.DisposeTexture();
  378. }
  379. }
  380. private static void CleanUp()
  381. {
  382. if (Sprite != null)
  383. {
  384. if (!Sprite.Disposed)
  385. {
  386. Sprite.Dispose();
  387. }
  388. Sprite = null;
  389. }
  390. if (Line != null)
  391. {
  392. if (!Line.Disposed)
  393. {
  394. Line.Dispose();
  395. }
  396. Line = null;
  397. }
  398. if (CurrentSurface != null)
  399. {
  400. if (!CurrentSurface.Disposed)
  401. {
  402. CurrentSurface.Dispose();
  403. }
  404. CurrentSurface = null;
  405. }
  406. if (PoisonDotBackground != null)
  407. {
  408. if (!PoisonDotBackground.Disposed)
  409. {
  410. PoisonDotBackground.Dispose();
  411. }
  412. PoisonDotBackground = null;
  413. }
  414. if (RadarTexture != null)
  415. {
  416. if (!RadarTexture.Disposed)
  417. {
  418. RadarTexture.Dispose();
  419. }
  420. RadarTexture = null;
  421. }
  422. if (FloorTexture != null)
  423. {
  424. if (!FloorTexture.Disposed)
  425. {
  426. FloorTexture.Dispose();
  427. }
  428. DXManager.FloorTexture = null;
  429. if (DXManager.FloorSurface != null && !DXManager.FloorSurface.Disposed)
  430. {
  431. DXManager.FloorSurface.Dispose();
  432. }
  433. DXManager.FloorSurface = null;
  434. }
  435. if (LightTexture != null)
  436. {
  437. if (!LightTexture.Disposed)
  438. LightTexture.Dispose();
  439. DXManager.LightTexture = null;
  440. if (DXManager.LightSurface != null && !DXManager.LightSurface.Disposed)
  441. {
  442. DXManager.LightSurface.Dispose();
  443. }
  444. DXManager.LightSurface = null;
  445. }
  446. if (Lights != null)
  447. {
  448. for (int i = 0; i < Lights.Count; i++)
  449. {
  450. if (!Lights[i].Disposed)
  451. Lights[i].Dispose();
  452. }
  453. Lights.Clear();
  454. }
  455. for (int i = TextureList.Count - 1; i >= 0; i--)
  456. {
  457. MImage m = TextureList[i];
  458. if (m == null) continue;
  459. m.DisposeTexture();
  460. }
  461. TextureList.Clear();
  462. for (int i = ControlList.Count - 1; i >= 0; i--)
  463. {
  464. MirControl c = ControlList[i];
  465. if (c == null) continue;
  466. c.DisposeTexture();
  467. }
  468. ControlList.Clear();
  469. }
  470. public static void Dispose()
  471. {
  472. CleanUp();
  473. Device?.Direct3D?.Dispose();
  474. Device?.Dispose();
  475. NormalPixelShader?.Dispose();
  476. GrayScalePixelShader?.Dispose();
  477. MagicPixelShader?.Dispose();
  478. }
  479. }
  480. }