HelloQuad.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. using AtomicEngine;
  2. public class Program
  3. {
  4. public static void Main(string[] args)
  5. {
  6. Application.Run<HelloQuad>(args);
  7. }
  8. }
  9. public class HelloQuad : AppDelegate
  10. {
  11. // Scene reference kept here so it won't be collected by the GC
  12. Scene scene;
  13. Camera camera;
  14. Graphics graphics;
  15. Viewport viewport;
  16. Texture2D texture;
  17. VertexBuffer vertexBuffer;
  18. public override void Start()
  19. {
  20. // We get the variables we are going to use in this example
  21. Renderer renderer = GetSubsystem<Renderer>();
  22. graphics = GetSubsystem<Graphics>();
  23. viewport = renderer.GetViewport(0);
  24. // We create a new Scene
  25. scene = new Scene();
  26. // The Octree should be added to the root scene node (mandatory?)
  27. scene.CreateComponent<Octree>();
  28. // We tell the current viewport to display the scene we just created
  29. viewport.Scene = scene;
  30. // We create a new camera on the scene, called "Camera"
  31. // - Scene.CreateChild(string name) returns a new Node with that name.
  32. // - Node.CreateComponent<ComponentType>() returns a component attached to that Node
  33. camera = scene.CreateChild("Camera").CreateComponent<Camera>();
  34. // We can access the Node any component is attached to using Component.Node
  35. camera.Node.Position = new Vector3(0.5f, 0.5f, 0.0f);
  36. // Remember, 'camera' is a Camera component, so we access it directly here
  37. camera.Orthographic = true;
  38. camera.OrthoSize = 1.5f;
  39. // We tell the Viewport to use our newly created camera to display our scene
  40. viewport.Camera = camera;
  41. // We create an XML from string so this code is fully self-contained
  42. XMLFile xml = new XMLFile();
  43. xml.FromString("<renderpath><command type=\"sendevent\"/></renderpath>");
  44. // We create a new RenderPath. A Viewport comes by default with some events, and you can use viewport.GetRenderPath().Clone()
  45. // to clone the default RenderPath and Append instructions to it instead (see AtomicBlaster for effects)
  46. RenderPath renderpath = new RenderPath();
  47. renderpath.Append(xml);
  48. // We repace the viewport's default renderpath by the one we just created
  49. viewport.SetRenderPath(renderpath);
  50. // We subscribe to the RenderPathEvent. Here we pass an anonymous function that just absorbs the argument and calls Render()
  51. SubscribeToEvent<RenderPathEvent>(e => { Render(); });
  52. // Here we setup our shaders, here we are using the BasicVColUnlitAlpha and selecting only DIFFMAP (diffuse texture pass)
  53. // See this link: github.com/AtomicGameEngine/AtomicGameEngine/tree/master/Resources/CoreData/Techniques
  54. ShaderVariation pixelShader = graphics.GetShader(ShaderType.PS, "Basic", "DIFFMAP");
  55. ShaderVariation vertexShader = graphics.GetShader(ShaderType.VS, "Basic", "DIFFMAP");
  56. graphics.SetShaders(vertexShader, pixelShader);
  57. // This vertex shader parameter just applies no transformation (Identity Matrix means no transformation) so the vertices
  58. // display in world coordinates what allow us to use the camera properly
  59. graphics.SetShaderParameter(ShaderParams.VSP_MODEL, Matrix3x4.IDENTITY);
  60. // We set the pixel shader diffuse color to be white. You can change this to 'tint' the texture similar to vertex colors
  61. // but this applies to the whole material
  62. graphics.SetShaderParameter(ShaderParams.PSP_MATDIFFCOLOR, Color.White);
  63. // We set cull mode to NONE so our geometry won't be culled (ignored), for this example we don't really need any culling
  64. graphics.SetCullMode(CullMode.CULL_NONE);
  65. // We create a texture from literal data so this code is fully self-contained, you can safely skip the lines below
  66. // In your real projects you're most likely going to load textures from the disk using Texture.Load
  67. Image image = new Image();
  68. image.SetSize(16, 16, 3);
  69. Color z = Color.Yellow;
  70. Color M = Color.Blue;
  71. Color k = Color.Black;
  72. Color[,] imageData =
  73. {
  74. { k,k,k,k,k,k,k,k,k,k,k,k,k,k,k,k },
  75. { k,z,z,z,z,z,z,z,z,z,z,z,z,z,M,k },
  76. { k,z,z,z,z,z,z,M,M,z,z,z,z,z,z,k },
  77. { k,z,z,z,z,z,z,M,M,z,z,z,z,z,z,k },
  78. { k,z,z,z,z,z,M,z,z,M,z,z,z,z,z,k },
  79. { k,z,z,z,z,z,M,z,z,M,z,z,z,z,z,k },
  80. { k,z,z,z,z,M,z,z,z,z,M,z,z,z,z,k },
  81. { k,z,z,z,z,M,z,z,z,z,M,z,z,z,z,k },
  82. { k,z,z,z,M,z,z,z,z,z,z,M,z,z,z,k },
  83. { k,z,z,z,M,z,z,z,z,z,z,M,z,z,z,k },
  84. { k,z,z,M,M,M,M,M,M,M,M,M,M,z,z,k },
  85. { k,z,z,M,z,z,z,z,z,z,z,z,M,z,z,k },
  86. { k,z,M,z,z,z,z,z,z,z,z,z,z,M,z,k },
  87. { k,z,M,z,z,z,z,z,z,z,z,z,z,M,z,k },
  88. { k,z,z,z,z,z,z,z,z,z,z,z,z,z,z,k },
  89. { k,k,k,k,k,k,k,k,k,k,k,k,k,k,k,k },
  90. };
  91. for (int x = 0; x < 16; x++)
  92. {
  93. for (int y = 0; y < 16; y++)
  94. {
  95. image.SetPixel(x, 15 - y, imageData[y, x]);
  96. }
  97. }
  98. texture = new Texture2D();
  99. texture.SetData(image);
  100. // We call this function that creates the quad geometry
  101. CreateQuad();
  102. }
  103. // We use unsafe code only to access the vertex buffer data
  104. private unsafe void CreateQuad()
  105. {
  106. // We create a new VertexBuffer object, it holds our vertices and is passed to the GPU
  107. vertexBuffer = new VertexBuffer();
  108. // We set its size and the elements it's containing, the 3rd optional argument (dynamic) should be 'true' if you're planning
  109. // to update the VertexBuffer constantly, that will improve performance in those cases.
  110. vertexBuffer.SetSize(6, Constants.MASK_POSITION | Constants.MASK_TEXCOORD1, false);
  111. // Here we lock the vertexBuffer what returns a pointer (IntPtr) to its data (vertexData here), I'm using a code block for clarity
  112. System.IntPtr vertexData = vertexBuffer.Lock(0, 6, true);
  113. {
  114. // We can cast the data pointer to whatever data type we want, here we are only using floats but ideally you will want
  115. // to cast it to an object (struct) with properly offsetted fields and maybe unions for things like colors
  116. float* vout = (float*) vertexData;
  117. // Our first vertex, here we set the x position of it
  118. *vout++ = 0;
  119. // Here we set the y position
  120. *vout++ = 0;
  121. // Here we set the z position (depth in this case, useful for sorting in orthographic projection)
  122. *vout++ = 0;
  123. // Here we set it's texture x coordinate, commonly called u;
  124. *vout++ = 0;
  125. // Here we set it's texture y coordinate, commonly called v;
  126. // UVs are simply cartesian coordinates: 0,0 is bottom-left; 1,1 is top-right
  127. *vout++ = 0;
  128. // Each of these blocks is a vertex, same concept apply:
  129. *vout++ = 0; // x
  130. *vout++ = 1; // y
  131. *vout++ = 0; // z
  132. *vout++ = 0; // u
  133. *vout++ = 1; // v
  134. *vout++ = 1;
  135. *vout++ = 1;
  136. *vout++ = 0;
  137. *vout++ = 1;
  138. *vout++ = 1;
  139. *vout++ = 0;
  140. *vout++ = 0;
  141. *vout++ = 0;
  142. *vout++ = 0;
  143. *vout++ = 0;
  144. *vout++ = 1;
  145. *vout++ = 1;
  146. *vout++ = 0;
  147. *vout++ = 1;
  148. *vout++ = 1;
  149. *vout++ = 1;
  150. *vout++ = 0;
  151. *vout++ = 0;
  152. *vout++ = 1;
  153. *vout++ = 0;
  154. }
  155. // Don't forget to unlock the VertexBuffer after you modify it
  156. vertexBuffer.Unlock();
  157. }
  158. void Render()
  159. {
  160. // We clear the whole screen white before drawing anything
  161. graphics.Clear(Constants.CLEAR_COLOR, Color.White);
  162. // The 3 lines below don't have to be set every frame in this specific example, but you'll most likely be changing the often
  163. viewport.View.SetCameraShaderParameters(camera);
  164. // We set the Texture to be used in the next draw call
  165. graphics.SetTexture((uint)TextureUnit.TU_DIFFUSE, texture);
  166. // We set the VertexBuffer to be used on the next draw call
  167. graphics.SetVertexBuffer(vertexBuffer);
  168. // We finally call Draw passing the primitive type our VertexBuffer uses, TRIANGLE_LIST basically means that each 2 vertex
  169. // in the buffer should have a face (triangle) between them
  170. graphics.Draw(PrimitiveType.TRIANGLE_LIST, 0, 6);
  171. }
  172. }