Very simple optimization. Instead of graphics use sprites with single white rectangle as their basetexture. Then apply tint to them to color the sprite. That way the squares can be rendered as a batch. That should be good enough for 150*200 squares (30k sprites). But for 1000 x 1000 (1M squares) you need to go deep into webgl rendering or have some other optimization strategy. Or would those squares be all visible at the same time? If not, then that would be doable by separating logic from rendering and only rendering a subsection of the whole area.
And here's a little rundown about different graphic objects:
- Graphics: Dynamically drawn content. Use when you need to draw lines, shapes etc. Be aware that updating graphics every frame might be costly depending on the complexity.
- Sprites: Sprites are basically just to tell what texture to draw and where, with this rotation, tint and scale. Sprites are among the cheapest objects in pixi.
- Textures: Textures are a region of baseTexture. They tell you what part of a baseTexture should be drawn. When using spritesheets the difference between texture and baseTexture is very noticable. When using just regular images then usually textures point just to a baseTexture and say that I want to render that whole thing.
- Basetexture: Basetextures represent a single image in memory.
- Mesh: Meshes are renderables that have customizable vertices. You could think that sprite is also a mesh that has 4 vertex points (topleft, topright, bottomright and bottomleft). With Meshes you can control how your polygons get formed. There are some premade mesh classes that provide premade useful meshes: SimpleRope, SimpleMesh and SimplePlane. Those abstract some of the complexity away.
And when to use them:
Graphics: Dynamic drawn content.
Sprites: Images with basic affine transformations (scale, rotation, position) and basic color transformation (tint, alpha).
Textures & BaseTexture: Pretty much always if you have some images to use. Very often these get handled automatically.
Mesh: When you need deformations.
Also here's a short instruction on shaders:
Modern computer graphics cards have a pipeline where you tell what program (vertex + fragment shader) you want to use, what vertices it gets as input and what uniforms (+ other stuff that I wont go into at this point). Then for each vertex it runs the vertex shader program. This basically calculates where on the screen should the point be. Then for the polygons formed by these vertices it runs the fragment shader for each pixel that is inside the polygon. The fragment shader returns the color value for that pixel. The uniforms mentioned beforehand are values that stay the same for both vertex and fragment shader on all vertex & pixel values. They are used to give values that are needed to calculate the output values. In sprite fragment shader "tint" is an uniform that is multiplied with the texture value.
So basically your gpu renders wegbl like this (simplified): list of points to draw -> vertex shader -> find out what pixels are affected -> fragment shader -> pixel to screen.