SpectAreaBarRender.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics.CodeAnalysis;
  4. using System.Drawing;
  5. using System.Numerics;
  6. using System.Runtime.CompilerServices;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. using Veldrid.Common.Tools;
  10. namespace Veldrid.Common.VeldridRender
  11. {
  12. internal unsafe class SpectAreaBarRender : BaseVeldridRender
  13. {
  14. private Boolean _ClearCache = true;
  15. private Vector2* _Dataptr;
  16. private Framebuffer _Framebuffer;
  17. private Texture _FrameTextureBuffer;
  18. private float _Brightness = 0;
  19. private ImageRender.VeldridSpriteBatch _StashRenderer;
  20. #region PipLine
  21. [AllowNull]
  22. Pipeline linepipline;
  23. Pipeline tripipline;
  24. #endregion
  25. #region vertex
  26. [AllowNull]
  27. DeviceBuffer vertexBuffer;
  28. VertexLayoutDescription vertexLayout;
  29. #endregion
  30. #region Uniform
  31. [AllowNull]
  32. Shader[] shaders;
  33. /// <summary>
  34. /// rgbafloat color
  35. /// vec4 linerange
  36. /// float VerticalOffset
  37. /// float HorizontalOffset
  38. /// float Brightness
  39. /// float spare
  40. /// </summary>
  41. [AllowNull]
  42. DeviceBuffer lineInfoBuffer;
  43. [AllowNull]
  44. DeviceBuffer proviewBuffer;
  45. [AllowNull]
  46. ResourceLayout sharedLayout;
  47. [AllowNull]
  48. ResourceSet sharedSet;
  49. #endregion
  50. private BlendStateDescription _CacheBlend = new BlendStateDescription()
  51. {
  52. AlphaToCoverageEnabled = false,
  53. BlendFactor = RgbaFloat.Clear,
  54. AttachmentStates = new BlendAttachmentDescription[]
  55. {
  56. new BlendAttachmentDescription()
  57. {
  58. BlendEnabled = true,
  59. SourceColorFactor = BlendFactor.SourceAlpha,
  60. DestinationColorFactor = BlendFactor.One,
  61. ColorFunction = BlendFunction.Maximum,
  62. SourceAlphaFactor = BlendFactor.SourceAlpha,
  63. DestinationAlphaFactor = BlendFactor.One,
  64. AlphaFunction = BlendFunction.Add,
  65. }
  66. }
  67. };
  68. public SpectAreaBarRender(IVeldridContent control, int xbarCount = 50, int yBarCount = 50) : base(control)
  69. {
  70. if (xbarCount <= 0 || yBarCount <= 0) throw new ArgumentOutOfRangeException();
  71. XBarCount = xbarCount;
  72. YBarCount = yBarCount;
  73. _Dataptr = (Vector2*)Marshal.AllocHGlobal(((xbarCount + yBarCount) * 4 + 5) * Unsafe.SizeOf<Vector2>()).ToPointer();
  74. }
  75. public override void CreateResources()
  76. {
  77. base.CreateResources();
  78. vertexBuffer = ResourceFactory.CreateBuffer(new BufferDescription((uint)(Unsafe.SizeOf<Vector2>() * (((XBarCount + YBarCount) * 4 + 5))), BufferUsage.VertexBuffer | BufferUsage.Dynamic));
  79. vertexLayout = new VertexLayoutDescription(new VertexElementDescription("in_Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2));
  80. shaders = CreateShader("DataRender");
  81. ResourceLayoutElementDescription[] resourceLayoutElementDescriptions =
  82. {
  83. new ResourceLayoutElementDescription("ProView", ResourceKind.UniformBuffer, ShaderStages.Vertex),
  84. new ResourceLayoutElementDescription("LineInfo", ResourceKind.UniformBuffer, ShaderStages.Vertex),
  85. };
  86. proviewBuffer = ResourceFactory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf<Matrix4x4>() * 2, BufferUsage.Dynamic | BufferUsage.UniformBuffer));
  87. lineInfoBuffer = ResourceFactory.CreateBuffer(new BufferDescription((uint)(Unsafe.SizeOf<RgbaFloat>() + Unsafe.SizeOf<Vector4>() * 2), BufferUsage.UniformBuffer | BufferUsage.Dynamic));
  88. ResourceLayoutDescription resourceLayoutDescription = new ResourceLayoutDescription(resourceLayoutElementDescriptions);
  89. sharedLayout = ResourceFactory.CreateResourceLayout(resourceLayoutDescription);
  90. BindableResource[] bindableResources = new BindableResource[] { proviewBuffer, lineInfoBuffer };
  91. ResourceSetDescription resourceSetDescription = new ResourceSetDescription(sharedLayout, bindableResources);
  92. sharedSet = ResourceFactory.CreateResourceSet(resourceSetDescription);
  93. this[nameof(Range), nameof(Margin)] = true;
  94. linepipline = CreatePipLine(PrimitiveTopology.LineStrip, sharedLayout, vertexLayout, shaders, frontFace: FrontFace.Clockwise);
  95. tripipline = CreatePipLine(PrimitiveTopology.TriangleStrip, sharedLayout, vertexLayout, shaders, frontFace: FrontFace.Clockwise);
  96. CreateBuffer();
  97. _StashRenderer = new ImageRender.VeldridSpriteBatch(GraphicsDevice, MainSwapchainBuffer.OutputDescription, CreateShader("ImageRender"), blendState: _CacheBlend);
  98. }
  99. private void CreateBuffer()
  100. {
  101. var texturedesc = TextureDescription.Texture2D(MainSwapchainBuffer.Width, MainSwapchainBuffer.Height, 1, 1, MainSwapchainBuffer.ColorTargets[0].Target.Format, TextureUsage.RenderTarget | TextureUsage.Sampled);
  102. if (_Framebuffer == null || _Framebuffer.Width != MainSwapchainBuffer.Width || _Framebuffer.Height != MainSwapchainBuffer.Height)
  103. {
  104. _FrameTextureBuffer?.Dispose();
  105. _FrameTextureBuffer = ResourceFactory.CreateTexture(texturedesc);
  106. _Framebuffer?.Dispose();
  107. _Framebuffer = ResourceFactory.CreateFramebuffer(new FramebufferDescription(null, _FrameTextureBuffer));
  108. }
  109. }
  110. internal override void PreDraw()
  111. {
  112. if (WindowSizeState)
  113. {
  114. CreateBuffer();
  115. }
  116. if (this[nameof(Margin), nameof(Range)] || WindowSizeState)
  117. {
  118. CommandList.UpdateBuffer(proviewBuffer, 0, Camera.OrthographicMatrix);
  119. CommandList.UpdateBuffer(proviewBuffer, (uint)Unsafe.SizeOf<Matrix4x4>(), Camera.GetLineMatrix(Margin, Range));
  120. CommandList.UpdateBuffer(lineInfoBuffer, (uint)Unsafe.SizeOf<RgbaFloat>(), (Vector4)Range);
  121. this[nameof(Range), nameof(Margin)] = false;
  122. if (WindowSizeState) WindowSizeState = false;
  123. }
  124. if (this[nameof(Brightness)])
  125. {
  126. UpdateBrightness();
  127. this[nameof(Brightness)] = false;
  128. }
  129. if (this[nameof(VerticalOffset)])
  130. {
  131. UpdateVerticalOffset();
  132. this[nameof(VerticalOffset)] = false;
  133. }
  134. if (this[nameof(HorizontalOffset)])
  135. {
  136. UpdateHorizontalOffset();
  137. this[nameof(HorizontalOffset)] = false;
  138. }
  139. }
  140. internal unsafe override void DrawData()
  141. {
  142. CommandList.SetFramebuffer(MainSwapchainBuffer);
  143. CommandList.UpdateBuffer(vertexBuffer, 0, (IntPtr)_Dataptr, vertexBuffer.SizeInBytes);
  144. CommandList.SetVertexBuffer(0, vertexBuffer);
  145. if (RectColor != Color.Transparent)
  146. {
  147. CommandList.SetPipeline(linepipline);
  148. CommandList.SetGraphicsResourceSet(0, sharedSet);
  149. UpdateColor(RectColor.ColorConverToRGBA());
  150. CommandList.Draw(5);
  151. }
  152. if (BarColor != Color.Transparent)
  153. {
  154. if (UseCache)
  155. {
  156. CommandList.SetFramebuffer(_Framebuffer);
  157. if (_ClearCache)
  158. {
  159. CommandList.ClearColorTarget(0, RgbaFloat.Clear);
  160. _ClearCache = false;
  161. }
  162. CommandList.SetPipeline(tripipline);
  163. CommandList.SetGraphicsResourceSet(0, sharedSet);
  164. UpdateColor(BarColor.ColorConverToRGBA());
  165. for (uint i = 0; i < XBarCount + YBarCount; i++)
  166. {
  167. CommandList.Draw(4, 1, i * 4 + 5, 0);
  168. }
  169. _StashRenderer.Begin();
  170. _StashRenderer.ViewMatrix = Matrix4x4.CreateOrthographic(MainSwapchainBuffer.Width, MainSwapchainBuffer.Height, 0.01f, -100f);
  171. _StashRenderer.Draw(_FrameTextureBuffer, new RectangleF(MainSwapchainBuffer.Width / -2, MainSwapchainBuffer.Height / -2, MainSwapchainBuffer.Width, MainSwapchainBuffer.Height), Color.Empty, 1);
  172. _StashRenderer.End();
  173. CommandList.SetFramebuffer(MainSwapchainBuffer);
  174. _StashRenderer.DrawBatch(CommandList);
  175. }
  176. else
  177. {
  178. CommandList.SetPipeline(tripipline);
  179. CommandList.SetGraphicsResourceSet(0, sharedSet);
  180. UpdateColor(BarColor.ColorConverToRGBA());
  181. for (uint i = 0; i < XBarCount + YBarCount; i++)
  182. {
  183. CommandList.Draw(4, 1, i * 4 + 5, 0);
  184. }
  185. }
  186. }
  187. }
  188. private float horizontalOffset;
  189. private float verticalOffset;
  190. private bool useCache;
  191. public float HorizontalOffset
  192. {
  193. get => horizontalOffset;
  194. set
  195. {
  196. Set(ref horizontalOffset, value);
  197. }
  198. }
  199. public float VerticalOffset
  200. {
  201. get => verticalOffset;
  202. set
  203. {
  204. Set(ref verticalOffset, value);
  205. }
  206. }
  207. private void UpdateHorizontalOffset()
  208. {
  209. CommandList.UpdateBuffer(lineInfoBuffer, (uint)(Unsafe.SizeOf<RgbaFloat>() + Unsafe.SizeOf<Vector4>() + Unsafe.SizeOf<float>()), HorizontalOffset);
  210. }
  211. private void UpdateVerticalOffset()
  212. {
  213. CommandList.UpdateBuffer(lineInfoBuffer, (uint)(Unsafe.SizeOf<RgbaFloat>() + Unsafe.SizeOf<Vector4>()), VerticalOffset);
  214. }
  215. private void UpdateColor(RgbaFloat color)
  216. {
  217. CommandList.UpdateBuffer(lineInfoBuffer, 0, color);
  218. }
  219. private void UpdateBrightness()
  220. {
  221. CommandList.UpdateBuffer(lineInfoBuffer, (uint)(Unsafe.SizeOf<Vector4>() * 2 + Unsafe.SizeOf<float>() * 2), Brightness);
  222. }
  223. public float Brightness
  224. {
  225. get => _Brightness;
  226. set
  227. {
  228. float temp = Math.Clamp(value, 0.0f, 100.0f);
  229. Set(ref _Brightness, temp);
  230. }
  231. }
  232. public unsafe override void DisposeResources()
  233. {
  234. base.DisposeResources();
  235. vertexBuffer?.Dispose();
  236. Marshal.FreeHGlobal((IntPtr)_Dataptr);
  237. _Framebuffer?.Dispose();
  238. _FrameTextureBuffer?.Dispose();
  239. _StashRenderer?.Dispose();
  240. sharedLayout?.Dispose();
  241. sharedSet?.Dispose();
  242. proviewBuffer?.Dispose();
  243. lineInfoBuffer?.Dispose();
  244. linepipline?.Dispose();
  245. tripipline?.Dispose();
  246. }
  247. public int XBarCount { get; }
  248. public int YBarCount { get; }
  249. public unsafe void SetRectData(Vector2[] rectData)
  250. {
  251. fixed (Vector2* ptr = &rectData[0])
  252. {
  253. Buffer.MemoryCopy(ptr, _Dataptr, Math.Min(5, rectData.Length) * Unsafe.SizeOf<Vector2>(), Math.Min(5, rectData.Length) * Unsafe.SizeOf<Vector2>());
  254. }
  255. }
  256. public unsafe void SetBarData(Vector2[] barData)
  257. {
  258. fixed (Vector2* ptr = &barData[0])
  259. {
  260. Buffer.MemoryCopy(ptr, _Dataptr + 5, Math.Min((XBarCount + YBarCount) * 4, barData.Length) * Unsafe.SizeOf<Vector2>(), Math.Min((XBarCount + YBarCount) * 4, barData.Length) * Unsafe.SizeOf<Vector2>());
  261. }
  262. }
  263. public Color RectColor { get; set; }
  264. public Color BarColor { get; set; }
  265. public Boolean UseCache
  266. {
  267. get => useCache;
  268. set
  269. {
  270. if (useCache != value)
  271. {
  272. useCache = value;
  273. _ClearCache = true;
  274. }
  275. }
  276. }
  277. public void ClearCache()
  278. {
  279. _ClearCache = true;
  280. }
  281. }
  282. }