<p>Even the most modest modern GPU can breeze through 10 million triangles a frame and still hit acceptable frame rates, so performance of the vertex shader isn't likely to be an issue.</p>
<p>For example each square could be defined as a pair of triangles. And the entire works drawn as a single draw call. The rasterizer (which is run after the vertex shader) would discard and trim triangles that are not visible or are partially visible (when zoomed for example). And vertex attributes can provide identifying information so the fragment shader can perform appropriate shading on a per square basis.</p>
<p>Triangles are plainer so are inherently 2 dimensional, a 2D projection is applied to the 2D vertex position in the vertex shader, A fixed <code>z</code> value is set as the last step for setting the gl_postion. Which is then processed by the rasterizer.</p>
<p>This would allow the fragment shader to focus on drawing a single square, and to draw the lines between the squares as variable sized. It would also allow for soothing operations on the lines just by computing the distance to the nearest line and using a mix operation. This would solve the rather tricky situation of being fully zoomed out where 775x775 lines could essentially take over the entire scene.</p>
<p>So don't be afraid to go for a rasterized triangle based version of this, performance really shouldn't be an issue.</p>

CC BY-SA 4.0
2023-10-20T11:00:32.450Z
2023-10-20T11:00:32.450Z
pmw1234
<h2>Information</h2>
<p>I have to render a map, that is rendered as a 2d collection of squares of different color, separated by white lines horizontally and vertically. There may be ~600000 squares surrounded by white area, and the actual borders of the map are arbitrary, only one part of map will be visible at a time, so it must not be rendered fully at once (the map is scrollable). The map is interactive, so it must change the color of square when hovering (dark green square) and it is possible to select some rectangle area (purple square collection), zoom in zoom out + a minimap to quickly move from one point to another. There are blue squares that are owned, and they have borders like in images. As an addition there can be images attached to any owned rectangular area.</p>
<h2>Actual Implementation</h2>
<p>Below is the current implementation which is based on html canvases, and it is not as performant as I want, so I decided to use webgl for rendering.</p>
<p><a href="https://i.sstatic.net/UxyzB.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/UxyzB.png" alt="enter image description here" /></a></p>
<p><a href="https://i.sstatic.net/Mn3fO.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/Mn3fO.png" alt="enter image description here" /></a></p>
<p><a href="https://i.sstatic.net/URJfH.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/URJfH.png" alt="enter image description here" /></a></p>
<h2>What I've Tried / Research</h2>
<p>I tried using ThreeJS to achieve this, but I think it is mostly 3d oriented and also it has many unwanted functionality that I will not use, so I decided to go with bare minimum. I've tried to write some fragment shaders, and achieved some functionality (selected area, hovered object). I am quite new to WebGL/OpenGL, I've read somewhere that it is possible to pass buffer to fragment shader as a texture, and I was thinking about forming a buffer  of UInt8 from whole map (even the empty area, for shader to be able to correctly draw borders) and passing it to fragment shader, which will distinguish the state by number of each element and draw the squares accordingly. But then I realized that even before adding images functionality much load will be offloaded to fragment shader, and it was not clear will the fragment shader be able to handle all this much load alone. Doing some research I found out that it is possible to use points and their size parameter to achieve this, and I think that it could be beneficial to split some of work to vertex shader, instead of doing everything in fragment shader.</p>
<h2>What I want to achieve</h2>
<p>I want to be able to render this map on nearly every device, because in my opinion current hardware is able to do this kind of work very efficiently and very performant. I understand that it is very dependent on implementation, so here are my questions:</p>
<h2>Question</h2>
<p>Will it give some performance improvements or will it be worse to offload this type of work to vertex shader and draw each square as a point? What abilities of WebGL or techniques can I use (or are mostly used) to handle this kind of situation? How can I achieve performant rendering in case when there are multiple images?</p>

<opengl><rendering><shader><glsl><webgl>
How to correctly handle rendering of ~600000, arbitrary colored 2D squares with WebGL?
h4ckthepl4net
# How to correctly handle rendering of ~600000, arbitrary colored 2D squares with WebGL?

(Asked by: username_0 on 2023-10-20)

## Information

I have to render a map, that is rendered as a 2d collection of squares of different color, separated by white lines horizontally and vertically. There may be ~600000 squares surrounded by white area, and the actual borders of the map are arbitrary, only one part of map will be visible at a time, so it must not be rendered fully at once (the map is scrollable). The map is interactive, so it must change the color of square when hovering (dark green square) and it is possible to select some rectangle area (purple square collection), zoom in zoom out + a minimap to quickly move from one point to another. There are blue squares that are owned, and they have borders like in images. As an addition there can be images attached to any owned rectangular area.

## Actual Implementation

Below is the current implementation which is based on html canvases, and it is not as performant as I want, so I decided to use webgl for rendering.

[![enter image description here](https://i.sstatic.net/UxyzB.png)](https://i.sstatic.net/UxyzB.png)

[![enter image description here](https://i.sstatic.net/Mn3fO.png)](https://i.sstatic.net/Mn3fO.png)

[![enter image description here](https://i.sstatic.net/URJfH.png)](https://i.sstatic.net/URJfH.png)

## What I've Tried / Research

I tried using ThreeJS to achieve this, but I think it is mostly 3d oriented and also it has many unwanted functionality that I will not use, so I decided to go with bare minimum. I've tried to write some fragment shaders, and achieved some functionality (selected area, hovered object). I am quite new to WebGL/OpenGL, I've read somewhere that it is possible to pass buffer to fragment shader as a texture, and I was thinking about forming a buffer of UInt8 from whole map (even the empty area, for shader to be able to correctly draw borders) and passing it to fragment shader, which will distinguish the state by number of each element and draw the squares accordingly. But then I realized that even before adding images functionality much load will be offloaded to fragment shader, and it was not clear will the fragment shader be able to handle all this much load alone. Doing some research I found out that it is possible to use points and their size parameter to achieve this, and I think that it could be beneficial to split some of work to vertex shader, instead of doing everything in fragment shader.

## What I want to achieve

I want to be able to render this map on nearly every device, because in my opinion current hardware is able to do this kind of work very efficiently and very performant. I understand that it is very dependent on implementation, so here are my questions:

## Question

Will it give some performance improvements or will it be worse to offload this type of work to vertex shader and draw each square as a point? What abilities of WebGL or techniques can I use (or are mostly used) to handle this kind of situation? How can I achieve performant rendering in case when there are multiple images?

**Tags:** opengl, rendering, shader, glsl, webgl


---

## 1 answers

### Answer by username_1 on 2023-10-20. Score: 0

Even the most modest modern GPU can breeze through 10 million triangles a frame and still hit acceptable frame rates, so performance of the vertex shader isn't likely to be an issue.

For example each square could be defined as a pair of triangles. And the entire works drawn as a single draw call. The rasterizer (which is run after the vertex shader) would discard and trim triangles that are not visible or are partially visible (when zoomed for example). And vertex attributes can provide identifying information so the fragment shader can perform appropriate shading on a per square basis.

Triangles are plainer so are inherently 2 dimensional, a 2D projection is applied to the 2D vertex position in the vertex shader, A fixed `z` value is set as the last step for setting the gl\_postion. Which is then processed by the rasterizer.

This would allow the fragment shader to focus on drawing a single square, and to draw the lines between the squares as variable sized. It would also allow for soothing operations on the lines just by computing the distance to the nearest line and using a mix operation. This would solve the rather tricky situation of being fully zoomed out where 775x775 lines could essentially take over the entire scene.

So don't be afraid to go for a rasterized triangle based version of this, performance really shouldn't be an issue.


---

