{"id":9295,"date":"2026-04-08T15:00:02","date_gmt":"2026-04-08T13:00:02","guid":{"rendered":"https:\/\/www.codecon.sk\/?p=9295"},"modified":"2026-05-25T15:26:53","modified_gmt":"2026-05-25T13:26:53","slug":"rendering-maps-at-scale-bridging-openlayers-and-pixijs","status":"publish","type":"post","link":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/","title":{"rendered":"Rendering Maps at Scale: Bridging OpenLayers and PixiJS"},"content":{"rendered":"<p><strong>The Problem<\/strong><br \/>\nWhen building a meteorological map application, you quickly run into a rendering wall. You need to display thousands of data points \u2014 wind barbs, temperature gradients, animated streamlines \u2014 all on an interactive map that users can pan, zoom, and step through time.<\/p>\n<p>SVG works fine for a few hundred elements, but falls apart at larger scales. Canvas 2D is faster, but redrawing everything on every frame becomes a bottleneck. The natural next step is the GPU.<\/p>\n<p>This post walks through how we extended <a href=\"https:\/\/openlayers.org\/\">OpenLayers<\/a> \u2014 a library for displaying interactive maps in the browser \u2014 with a custom WebGL rendering pipeline, using <a href=\"https:\/\/pixijs.com\/\">PixiJS<\/a> to handle the GPU side. PixiJS is a 2D rendering library that normally draws to its own canvas, but here we use it differently. It is less about the final visuals and more about the plumbing that makes it work.<\/p>\n<p>The full source code is on <a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\">GitHub<\/a>.<\/p>\n<p>Here is what the end result looks like \u2014 wind rendered as barbs and as streamlines:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-9314\" src=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.01-300x232.png\" alt=\"Wind barbs \u2014 each arrow shows wind direction and speed at a grid point\" width=\"548\" height=\"424\" srcset=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.01-300x232.png 300w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.01-1024x793.png 1024w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.01-768x595.png 768w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.01-1536x1190.png 1536w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.01.png 1748w\" sizes=\"auto, (max-width: 548px) 100vw, 548px\" \/><br \/>\n<em>Wind barbs \u2014 each arrow shows wind direction and speed at a grid point<\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-9315\" src=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.14-300x232.png\" alt=\"Wind streamlines \u2014 continuous lines that follow the wind flow\" width=\"550\" height=\"425\" srcset=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.14-300x232.png 300w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.14-1024x793.png 1024w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.14-768x595.png 768w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.14-1536x1190.png 1536w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.33.14.png 1758w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><br \/>\n<em>Wind streamlines \u2014 continuous lines that follow the wind flow<\/em><\/p>\n<p><strong>1. Keeping Concerns Separate<br \/>\n<\/strong>OpenLayers structures its rendering around three abstractions: a <strong>source<\/strong> that fetches data, a <strong>layer<\/strong> that owns the source, and a <strong>renderer<\/strong> that draws pixels. We extend all three.<\/p>\n<p>To keep the code manageable, we split the <strong>renderer<\/strong> into two classes. The renderer handles OpenLayers&#8217; lifecycle \u2014 it knows about frames, caching, and when to trigger a redraw. The <strong>detail<\/strong> class does the actual drawing and has no knowledge of OpenLayers at all.<\/p>\n<p>The detail class follows a simple interface ( <a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\/blob\/main\/src\/app\/core\/map\/renderer-detail.ts\">renderer-detail.ts<\/a> ):<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-9316\" src=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.42.10-300x76.png\" alt=\"renderer-detail\" width=\"919\" height=\"233\" srcset=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.42.10-300x76.png 300w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.42.10-1024x260.png 1024w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.42.10-768x195.png 768w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.42.10.png 1030w\" sizes=\"auto, (max-width: 919px) 100vw, 919px\" \/>Each concrete layer type \u2014 like <a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\/blob\/main\/src\/app\/core\/map\/windbarb-layer.ts\">WindbarbLayer<\/a> \u2014 only needs to wire these pieces together. The drawing complexity lives in its detail class. See also <a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\/blob\/main\/src\/app\/core\/map\/custom-layer.ts\">custom-layer.ts<\/a>, c<a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\/blob\/main\/src\/app\/core\/map\/custom-source.ts\">ustom-source.ts<\/a> and <a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\/blob\/main\/src\/app\/core\/map\/custom-layer-renderer.ts\">custom-layer-renderer.ts<\/a>.<\/p>\n<p><strong>2. Injecting PixiJS into an Existing WebGL Context<br \/>\n<\/strong>Normally PixiJS creates and owns a <span style=\"color: #000080;\">&lt;canvas&gt;<\/span> element. Here we flip that: we create the <span style=\"color: #000080;\">WebGL2RenderingContext<\/span> ourselves and hand it to PixiJS. This way we stay in control of the canvas, and PixiJS just borrows it ( <a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\/blob\/main\/src\/app\/core\/map\/pixi-layer-detail.ts\">pixi-layer-detail.ts<\/a> ):<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-9317\" src=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.48.53-300x183.png\" alt=\"\" width=\"926\" height=\"565\" srcset=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.48.53-300x183.png 300w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.48.53-1024x624.png 1024w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.48.53-768x468.png 768w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.48.53.png 1136w\" sizes=\"auto, (max-width: 926px) 100vw, 926px\" \/><\/p>\n<p>This gives us the full PixiJS scene graph \u2014 <span style=\"color: #000080;\">Container, Graphics, Mesh, Shader, Texture<\/span> \u2014 on a context we share with our own GLSL shaders. PixiJS takes care of buffer uploads and texture binding. We stay in control of the canvas.<\/p>\n<p><strong>3. The Offscreen Render Queue<br \/>\n<\/strong>This is where the main performance gains come from.<\/p>\n<p>WebGL rendering only needs to happen when <em>data changes<\/em>. Panning and zooming are just coordinate changes \u2014 they do not need the GPU to redraw anything. So we separate the two:<\/p>\n<ol>\n<li>When data changes, render onto an <span style=\"color: #000080;\">OffscreenCanvas<\/span> and save the result as an <span style=\"color: #000080;\">ImageBitmap<\/span><\/li>\n<li>On every frame after that (pan, zoom, resize), draw that saved image onto the visible canvas using a simple coordinate transform<\/li>\n<\/ol>\n<p>The key design decisions in <a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\/blob\/main\/src\/app\/core\/map\/offscreen-renderer-queue.ts\">offscreen-renderer-queue.ts<\/a> :<br \/>\n<strong>&#8211; One shared offscreen canvas for all layers.<\/strong> Multiple layers cannot use the same WebGL context at the same time, so they share a single canvas and take turns.<br \/>\n<strong>&#8211; Jobs run one at a time, never at the same time.<\/strong> We use RxJS <span style=\"color: #000080;\">concatMap<\/span> to make sure render jobs are processed one after another.<br \/>\n<strong>&#8211; Pixels are handed off without copying.\u00a0<\/strong><span style=\"color: #000080;\">transferRoImageBitmap()<\/span> gives ownership of the pixel buffer to the bitmap directly.<\/p>\n<p>Once a frame is rendered and saved, every pan or zoom is just a single <span style=\"color: #000080;\">ctx.drawImage()<\/span> call \u2014 no GPU work at all. On top of this, an LRU cache ( <a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\/blob\/main\/src\/app\/core\/map\/lru-cache.ts\">lru-cache.ts<\/a> ) stores previously rendered frames so stepping back and forth through forecast time steps requires no GPU work either.<\/p>\n<p><strong>4. Encoding Grid Data as GPU Textures<br \/>\n<\/strong>Wind data is stored as two separate grids: <strong>U<\/strong> (the east-west component) and <strong>V<\/strong> (the north- south component). Together they describe both the direction and speed of wind at every point. For example, a strong U value with a small V value means the wind is blowing mostly east or west.<\/p>\n<p>Weather grid data \u2014 say, wind U\/V components across a 200\u00d7150 grid \u2014 arrives as JavaScript <span style=\"color: #000080;\">Float64Array<\/span>s. Sending 30,000 individual float values to the GPU as vertex attributes is not practical.<\/p>\n<p>Instead, we pack the data into a GPU texture. Each grid point becomes one pixel, with the U and V wind components packed into the four color channels (R, G, B, A), two bytes each. The vertex shader then reads each wind value by looking up that pixel in the texture. The decode is one line of GLSL ( <a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\/blob\/main\/src\/app\/core\/map\/windbarb-renderer-detail.ts\">windbarb-renderer-detail.ts<\/a> ):<img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-9320\" src=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.59.50-300x39.png\" alt=\"grid\" width=\"907\" height=\"118\" srcset=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.59.50-300x39.png 300w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.59.50-1024x132.png 1024w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.59.50-768x99.png 768w, https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/Snimka-obrazovky-2026-04-02-o-14.59.50.png 1132w\" sizes=\"auto, (max-width: 907px) 100vw, 907px\" \/>The GPU reads and processes all 30,000 wind values in parallel, with no per-frame CPU work. The full encoding logic lives in <a href=\"https:\/\/github.com\/iblsoft\/codecon-2026-open-layers-gpu-shader-rendering\/blob\/main\/src\/app\/core\/map\/data-texture.ts\">data-texture.ts<\/a> .<\/p>\n<p><strong>Putting It All Together<br \/>\n<\/strong>Here is the flow from new data arriving to pixels on screen:<br \/>\n<strong>1. Source params change<\/strong> \u2192 new grid data is fetched from the weather API<br \/>\n<strong>2. Data arrives<\/strong> \u2192 the detail class updates the GPU texture and renders to an <span style=\"color: #000080;\">ImageBitmap<\/span> via the offscreen queue<br \/>\n<strong>3. Image is cached<\/strong> \u2192 stored in the LRU cache by time step, viewport size, and position<br \/>\n<strong>4. Map moves<\/strong> \u2192 OpenLayers calls <span style=\"color: #000080;\">renderFrame()<\/span> on every interaction, which is just a fast <span style=\"color: #000080;\">drawImage()<\/span> with a position transform<\/p>\n<p>Steps 1\u20133 are async and only run when data changes. Step 4 runs on every animation frame and is cheap.<\/p>\n<p><strong>Closing Thoughts<br \/>\n<\/strong>This setup is not specific to weather data. The same approach works for any layer type where you need GPU rendering on an interactive map: point clouds, heatmaps, custom vector overlays.<\/p>\n<p>The setup takes some effort, but once it is in place, adding a new layer type means writing one detail class and a few shaders<br \/>\n\u2014 the rest takes care of itsef<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How we wired a WebGL rendering pipeline into a geospatial map using PixiJS and OpenLayers<\/p>\n","protected":false},"author":5,"featured_media":10002,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[88],"tags":[89,90,92,91],"class_list":["post-9295","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codecon","tag-bratislava","tag-codecon","tag-inspiration","tag-partners"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Rendering Maps at Scale: Bridging OpenLayers and PixiJS &#8212; CODECON<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Rendering Maps at Scale: Bridging OpenLayers and PixiJS &#8212; CODECON\" \/>\n<meta property=\"og:description\" content=\"How we wired a WebGL rendering pipeline into a geospatial map using PixiJS and OpenLayers\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/\" \/>\n<meta property=\"og:site_name\" content=\"CODECON\" \/>\n<meta property=\"article:published_time\" content=\"2026-04-08T13:00:02+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-05-25T13:26:53+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/rendering.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"2048\" \/>\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Eva Kalinov\u00e1\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Eva Kalinov\u00e1\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/\"},\"author\":{\"name\":\"Eva Kalinov\u00e1\",\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/#\\\/schema\\\/person\\\/815e94ce93756757859939501e018711\"},\"headline\":\"Rendering Maps at Scale: Bridging OpenLayers and PixiJS\",\"datePublished\":\"2026-04-08T13:00:02+00:00\",\"dateModified\":\"2026-05-25T13:26:53+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/\"},\"wordCount\":932,\"image\":{\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.codecon.sk\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/rendering.webp\",\"keywords\":[\"#bratislava\",\"#codecon\",\"#inspiration\",\"#partners\"],\"articleSection\":[\"CODECON\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/\",\"url\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/\",\"name\":\"Rendering Maps at Scale: Bridging OpenLayers and PixiJS &#8212; CODECON\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.codecon.sk\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/rendering.webp\",\"datePublished\":\"2026-04-08T13:00:02+00:00\",\"dateModified\":\"2026-05-25T13:26:53+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/#\\\/schema\\\/person\\\/815e94ce93756757859939501e018711\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.codecon.sk\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/rendering.webp\",\"contentUrl\":\"https:\\\/\\\/www.codecon.sk\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/rendering.webp\",\"width\":2048,\"height\":1024,\"caption\":\"rendering blog\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Domovsk\u00e1 str\u00e1nka\",\"item\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Rendering Maps at Scale: Bridging OpenLayers and PixiJS\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/\",\"name\":\"CODECON\",\"description\":\"Najv\u00e4\u010d\u0161ie komunitn\u00e9 stretnutie v\u00fdvoj\u00e1rov na Slovensku\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.codecon.sk\\\/en\\\/#\\\/schema\\\/person\\\/815e94ce93756757859939501e018711\",\"name\":\"Eva Kalinov\u00e1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Rendering Maps at Scale: Bridging OpenLayers and PixiJS &#8212; CODECON","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/","og_locale":"en_US","og_type":"article","og_title":"Rendering Maps at Scale: Bridging OpenLayers and PixiJS &#8212; CODECON","og_description":"How we wired a WebGL rendering pipeline into a geospatial map using PixiJS and OpenLayers","og_url":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/","og_site_name":"CODECON","article_published_time":"2026-04-08T13:00:02+00:00","article_modified_time":"2026-05-25T13:26:53+00:00","og_image":[{"width":2048,"height":1024,"url":"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/rendering.webp","type":"image\/webp"}],"author":"Eva Kalinov\u00e1","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Eva Kalinov\u00e1","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/#article","isPartOf":{"@id":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/"},"author":{"name":"Eva Kalinov\u00e1","@id":"https:\/\/www.codecon.sk\/en\/#\/schema\/person\/815e94ce93756757859939501e018711"},"headline":"Rendering Maps at Scale: Bridging OpenLayers and PixiJS","datePublished":"2026-04-08T13:00:02+00:00","dateModified":"2026-05-25T13:26:53+00:00","mainEntityOfPage":{"@id":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/"},"wordCount":932,"image":{"@id":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/#primaryimage"},"thumbnailUrl":"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/rendering.webp","keywords":["#bratislava","#codecon","#inspiration","#partners"],"articleSection":["CODECON"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/","url":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/","name":"Rendering Maps at Scale: Bridging OpenLayers and PixiJS &#8212; CODECON","isPartOf":{"@id":"https:\/\/www.codecon.sk\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/#primaryimage"},"image":{"@id":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/#primaryimage"},"thumbnailUrl":"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/rendering.webp","datePublished":"2026-04-08T13:00:02+00:00","dateModified":"2026-05-25T13:26:53+00:00","author":{"@id":"https:\/\/www.codecon.sk\/en\/#\/schema\/person\/815e94ce93756757859939501e018711"},"breadcrumb":{"@id":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/#primaryimage","url":"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/rendering.webp","contentUrl":"https:\/\/www.codecon.sk\/wp-content\/uploads\/2026\/04\/rendering.webp","width":2048,"height":1024,"caption":"rendering blog"},{"@type":"BreadcrumbList","@id":"https:\/\/www.codecon.sk\/en\/rendering-maps-at-scale-bridging-openlayers-and-pixijs\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Domovsk\u00e1 str\u00e1nka","item":"https:\/\/www.codecon.sk\/en\/"},{"@type":"ListItem","position":2,"name":"Rendering Maps at Scale: Bridging OpenLayers and PixiJS"}]},{"@type":"WebSite","@id":"https:\/\/www.codecon.sk\/en\/#website","url":"https:\/\/www.codecon.sk\/en\/","name":"CODECON","description":"Najv\u00e4\u010d\u0161ie komunitn\u00e9 stretnutie v\u00fdvoj\u00e1rov na Slovensku","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.codecon.sk\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.codecon.sk\/en\/#\/schema\/person\/815e94ce93756757859939501e018711","name":"Eva Kalinov\u00e1"}]}},"_links":{"self":[{"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/posts\/9295","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/comments?post=9295"}],"version-history":[{"count":3,"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/posts\/9295\/revisions"}],"predecessor-version":[{"id":9993,"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/posts\/9295\/revisions\/9993"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/media\/10002"}],"wp:attachment":[{"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/media?parent=9295"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/categories?post=9295"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.codecon.sk\/en\/wp-json\/wp\/v2\/tags?post=9295"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}