CustomRenderer.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using AtomicEngine;
  5. namespace AtomicBlaster
  6. {
  7. [StructLayout(LayoutKind.Sequential)]
  8. struct PositionColorUVVertex
  9. {
  10. public float X, Y, Z;
  11. public uint Color;
  12. public float U, V;
  13. };
  14. class Batch
  15. {
  16. public Texture2D Texture;
  17. public uint VertexCount = 0;
  18. public PositionColorUVVertex[] Vertices = new PositionColorUVVertex[256];
  19. }
  20. static class CustomRenderer
  21. {
  22. // 250k max vertices
  23. const uint maxVertices = 256 * 1024;
  24. static uint totalVertex = 0;
  25. static VertexBuffer vertexBuffer;
  26. static ShaderVariation pixelShader;
  27. static ShaderVariation vertexShader;
  28. static SortedDictionary<float, Dictionary<Texture2D, Batch>> layerBatches = new SortedDictionary<float, Dictionary<Texture2D, Batch>>();
  29. public static void Initialize()
  30. {
  31. var graphics = AtomicNET.GetSubsystem<Graphics>();
  32. pixelShader = graphics.GetShader(ShaderType.PS, "Atomic2D");
  33. vertexShader = graphics.GetShader(ShaderType.VS, "Atomic2D");
  34. vertexBuffer = new VertexBuffer();
  35. vertexBuffer.SetSize(maxVertices, Constants.MASK_POSITION | Constants.MASK_COLOR | Constants.MASK_TEXCOORD1, true);
  36. }
  37. public static void Begin()
  38. {
  39. totalVertex = 0;
  40. // reset batches
  41. foreach (var layer in layerBatches)
  42. {
  43. foreach (var batch in layer.Value.Values)
  44. {
  45. batch.VertexCount = 0;
  46. }
  47. }
  48. }
  49. struct DrawItem
  50. {
  51. public Texture2D Texture;
  52. public uint StartVertex;
  53. public uint VertexCount;
  54. }
  55. unsafe public static void End()
  56. {
  57. List<DrawItem> drawList = new List<DrawItem>();
  58. if (totalVertex == 0)
  59. return;
  60. IntPtr vertexData = vertexBuffer.Lock(0, totalVertex, true);
  61. if (vertexData == IntPtr.Zero)
  62. return;
  63. uint startVertex = 0;
  64. PositionColorUVVertex* vout = (PositionColorUVVertex*)vertexData;
  65. foreach (var layer in layerBatches)
  66. {
  67. foreach (var batch in layer.Value.Values)
  68. {
  69. if (totalVertex + batch.VertexCount >= maxVertices)
  70. {
  71. throw new System.InvalidOperationException("Ran out of vertices");
  72. }
  73. if (batch.VertexCount == 0)
  74. continue;
  75. for (uint i = 0; i < batch.VertexCount; i++, vout++)
  76. {
  77. *vout = batch.Vertices[i];
  78. //vout->X -= 1280.0f / 2.0f;
  79. //vout->Y -= 720.0f / 2.0f;
  80. //vout->X /= 1280.0f / 2.0f;
  81. //vout->Y /= 720.0f / 2.0f;
  82. }
  83. var item = new DrawItem();
  84. item.Texture = batch.Texture;
  85. item.StartVertex = startVertex;
  86. item.VertexCount = batch.VertexCount;
  87. startVertex += batch.VertexCount;
  88. drawList.Add(item);
  89. }
  90. }
  91. vertexBuffer.Unlock();
  92. var renderer = AtomicNET.GetSubsystem<Renderer>();
  93. var graphics = AtomicNET.GetSubsystem<Graphics>();
  94. var view = renderer.GetViewport(0).View;
  95. var camera = renderer.GetViewport(0).Camera;
  96. if (view == null || camera == null)
  97. return;
  98. var vp = graphics.Viewport;
  99. graphics.SetShaders(vertexShader, pixelShader);
  100. graphics.SetBlendMode(BlendMode.BLEND_ADDALPHA);
  101. graphics.SetCullMode(CullMode.CULL_NONE);
  102. graphics.SetFillMode(FillMode.FILL_SOLID);
  103. graphics.SetDepthTest(CompareMode.CMP_ALWAYS);
  104. camera.Zoom = .027f;
  105. camera.OrthoSize = 20f;
  106. camera.AspectRatio = 1280.0f / 720.0f;
  107. camera.Node.Position = new Vector3(1280.0f / 2.0f, 720.0f / 2.0f, 0.0f);
  108. view.SetCameraShaderParameters(camera, true);
  109. graphics.SetShaderParameter(ShaderParams.VSP_MODEL, Matrix3x4.IDENTITY);
  110. graphics.SetVertexBuffer(vertexBuffer);
  111. foreach (var item in drawList)
  112. {
  113. graphics.SetTexture((int) TextureUnit.TU_DIFFUSE, item.Texture);
  114. graphics.Draw(PrimitiveType.TRIANGLE_LIST, item.StartVertex, item.VertexCount);
  115. }
  116. // graphics.SetTexture(0, null);
  117. }
  118. public static void Draw(Texture2D texture, Vector2 position, Color color, float rotation, Vector2 origin, float scale, float layerDepth)
  119. {
  120. var w = texture.Width * scale;
  121. var h = texture.Height * scale;
  122. DrawInternal(texture,
  123. new Vector4(position.X, position.Y, w, h),
  124. color,
  125. rotation,
  126. origin * scale,
  127. layerDepth);
  128. }
  129. public static void Draw(Texture2D texture, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, float layerDepth)
  130. {
  131. var w = texture.Width * scale.X;
  132. var h = texture.Height * scale.Y;
  133. DrawInternal(texture,
  134. new Vector4(position.X, position.Y, w, h),
  135. color,
  136. rotation,
  137. origin * scale,
  138. layerDepth);
  139. }
  140. public static void DrawLine(Vector2 start, Vector2 end, Color color, float thickness = 2f)
  141. {
  142. Vector2 delta = end - start;
  143. Draw(Art.Pixel, start, color, delta.ToAngle(), new Vector2(0, 0.5f), new Vector2(delta.Length, thickness), 0f);
  144. }
  145. static void DrawInternal(Texture2D texture, Vector4 destinationRectangle, Color color, float rotation, Vector2 origin, float depth)
  146. {
  147. Dictionary<Texture2D, Batch> batches;
  148. if (!layerBatches.TryGetValue(depth, out batches))
  149. {
  150. batches = new Dictionary<Texture2D, Batch>();
  151. layerBatches[depth] = batches;
  152. }
  153. Batch batch;
  154. if (!batches.TryGetValue(texture, out batch))
  155. {
  156. batch = new Batch();
  157. batch.Texture = texture;
  158. batches[texture] = batch;
  159. }
  160. if (totalVertex + 6 >= maxVertices)
  161. {
  162. throw new System.InvalidOperationException("Ran out of vertices");
  163. }
  164. totalVertex += 6;
  165. if (batch.VertexCount + 6 >= batch.Vertices.Length)
  166. {
  167. Array.Resize(ref batch.Vertices, batch.Vertices.Length * 2);
  168. }
  169. if (rotation == 0f)
  170. {
  171. Set(batch.Vertices, ref batch.VertexCount, destinationRectangle.X - origin.X,
  172. destinationRectangle.Y - origin.Y,
  173. destinationRectangle.Z,
  174. destinationRectangle.W,
  175. color,
  176. _texCoordTL,
  177. _texCoordBR,
  178. depth);
  179. }
  180. else
  181. {
  182. Set(batch.Vertices, ref batch.VertexCount, destinationRectangle.X,
  183. destinationRectangle.Y,
  184. -origin.X,
  185. -origin.Y,
  186. destinationRectangle.Z,
  187. destinationRectangle.W,
  188. (float)Math.Sin(rotation),
  189. (float)Math.Cos(rotation),
  190. color,
  191. _texCoordTL,
  192. _texCoordBR,
  193. depth);
  194. }
  195. }
  196. static Vector2 _texCoordTL = new Vector2(0, 0);
  197. static Vector2 _texCoordBR = new Vector2(1, 1);
  198. static PositionColorUVVertex vertexTL = new PositionColorUVVertex();
  199. static PositionColorUVVertex vertexTR = new PositionColorUVVertex();
  200. static PositionColorUVVertex vertexBL = new PositionColorUVVertex();
  201. static PositionColorUVVertex vertexBR = new PositionColorUVVertex();
  202. // Portions Copyright (C) The MonoGame Team
  203. static public void Set(PositionColorUVVertex[] vertices, ref uint vertexCount, float x, float y, float dx, float dy, float w, float h, float sin, float cos, Color color, Vector2 texCoordTL, Vector2 texCoordBR, float depth)
  204. {
  205. uint ucolor = color.ToUInt();
  206. vertexTL.X = x + dx * cos - dy * sin;
  207. vertexTL.Y = y + dx * sin + dy * cos;
  208. vertexTL.Z = depth;
  209. vertexTL.Color = ucolor;
  210. vertexTL.U = texCoordTL.X;
  211. vertexTL.V = texCoordTL.Y;
  212. vertexTR.X = x + (dx + w) * cos - dy * sin;
  213. vertexTR.Y = y + (dx + w) * sin + dy * cos;
  214. vertexTR.Z = depth;
  215. vertexTR.Color = ucolor;
  216. vertexTR.U = texCoordBR.X;
  217. vertexTR.V = texCoordTL.Y;
  218. vertexBL.X = x + dx * cos - (dy + h) * sin;
  219. vertexBL.Y = y + dx * sin + (dy + h) * cos;
  220. vertexBL.Z = depth;
  221. vertexBL.Color = ucolor;
  222. vertexBL.U = texCoordTL.X;
  223. vertexBL.V = texCoordBR.Y;
  224. vertexBR.X = x + (dx + w) * cos - (dy + h) * sin;
  225. vertexBR.Y = y + (dx + w) * sin + (dy + h) * cos;
  226. vertexBR.Z = depth;
  227. vertexBR.Color = ucolor;
  228. vertexBR.U = texCoordBR.X;
  229. vertexBR.V = texCoordBR.Y;
  230. vertices[vertexCount++] = vertexTL;
  231. vertices[vertexCount++] = vertexTR;
  232. vertices[vertexCount++] = vertexBL;
  233. vertices[vertexCount++] = vertexTR;
  234. vertices[vertexCount++] = vertexBR;
  235. vertices[vertexCount++] = vertexBL;
  236. }
  237. static public void Set(PositionColorUVVertex[] vertices, ref uint vertexCount, float x, float y, float w, float h, Color color, Vector2 texCoordTL, Vector2 texCoordBR, float depth)
  238. {
  239. uint ucolor = color.ToUInt();
  240. vertexTL.X = x;
  241. vertexTL.Y = y;
  242. vertexTL.Z = depth;
  243. vertexTL.Color = ucolor;
  244. vertexTL.U = texCoordTL.X;
  245. vertexTL.V = texCoordTL.Y;
  246. vertexTR.X = x + w;
  247. vertexTR.Y = y;
  248. vertexTR.Z = depth;
  249. vertexTR.Color = ucolor;
  250. vertexTR.U = texCoordBR.X;
  251. vertexTR.V = texCoordTL.Y;
  252. vertexBL.X = x;
  253. vertexBL.Y = y + h;
  254. vertexBL.Z = depth;
  255. vertexBL.Color = ucolor;
  256. vertexBL.U = texCoordTL.X;
  257. vertexBL.V = texCoordBR.Y;
  258. vertexBR.X = x + w;
  259. vertexBR.Y = y + h;
  260. vertexBR.Z = depth;
  261. vertexBR.Color = ucolor;
  262. vertexBR.U = texCoordBR.X;
  263. vertexBR.V = texCoordBR.Y;
  264. vertices[vertexCount++] = vertexTL;
  265. vertices[vertexCount++] = vertexTR;
  266. vertices[vertexCount++] = vertexBL;
  267. vertices[vertexCount++] = vertexTR;
  268. vertices[vertexCount++] = vertexBR;
  269. vertices[vertexCount++] = vertexBL;
  270. }
  271. }
  272. }