惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
雷峰网
雷峰网
Recent Announcements
Recent Announcements
月光博客
月光博客
G
Google Developers Blog
腾讯CDC
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
T
Tenable Blog
云风的 BLOG
云风的 BLOG
W
WeLiveSecurity
博客园 - 【当耐特】
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - 聂微东
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
人人都是产品经理
人人都是产品经理
P
Privacy International News Feed
MyScale Blog
MyScale Blog
K
Kaspersky official blog
T
The Blog of Author Tim Ferriss
Attack and Defense Labs
Attack and Defense Labs
Spread Privacy
Spread Privacy
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
aimingoo的专栏
aimingoo的专栏
I
Intezer
Vercel News
Vercel News
小众软件
小众软件
Simon Willison's Weblog
Simon Willison's Weblog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
Netflix TechBlog - Medium
P
Proofpoint News Feed
Latest news
Latest news
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tor Project blog
S
Security Affairs
P
Proofpoint News Feed
博客园 - 三生石上(FineUI控件)
博客园 - Franky
C
Cyber Attacks, Cyber Crime and Cyber Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
美团技术团队
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
Security @ Cisco Blogs
L
LINUX DO - 热门话题
Know Your Adversary
Know Your Adversary
Project Zero
Project Zero
D
Docker
L
Lohrmann on Cybersecurity
F
Full Disclosure

WebGL Fundamentals

WebGL Using 2 or More Textures WebGL Implementing DrawImage WebGL 2D Matrices WebGL Implementing A Matrix Stack WebGL 2D Rotation WebGL 2D Scale WebGL 2D Translation WebGL - Rasterization vs 3D libraries WebGL 3D - Cameras WebGL 3D Geometry - Lathe WebGL 3D - Directional Lighting WebGL 3D - Point Lighting WebGL 3D - Normal Mapping WebGL 3D - Spot Lighting WebGL - Orthographic 3D WebGL 3D Perspective Correct Texture Mapping WebGL 3D Perspective WebGL Textures WebGL and Alpha WebGL - Animation WebGL Anti-Patterns WebGL Attributes WebGL Boilerplate WebGL - Cross Origin Images WebGL Cross Platform Issues WebGL Cubemaps WebGL 3D - Data Textures WebGL - Drawing Multiple Things WebGL Drawing Without Data WebGL Environment Maps (reflections) WebGL Fog WebGL Framebuffers WebGL Fundamentals WebGL GPGPU WebGL How It Works WebGL Image Processing Continued WebGL Image Processing WebGL Indexed Vertices WebGL Optimization - Instanced Drawing WebGL - Less Code, More Fun WebGL Load Obj with Mtl WebGL Load Obj WebGL Matrices vs Math Matrices WebGL Multiple Views, Multiple Canvases WebGL Picking WebGL Planar and Perspective Projection Mapping WebGL Points, Lines, and Triangles WebGL Post Processing WebGL Precision Issues WebGL Pulling Vertices Accessing textures by pixel coordinate in WebGL2 A simple way to show the load on the GPU's vertex and fragment processing? Apply a displacement map and specular map Can anyone explain what this GLSL fragment shader is doing? Can I mute the warning about vertex attrib 0 being disabled? Create image warping effect in WebGL Creating a smudge/liquify effect How to draw Depth Sprites Determine min/max values for the entire image Don't blend a polygon that crosses itself Drawing 2D image with depth map to achieve pseudo-3D effect Drawing a heightmap Drawing layers with different points Drawing Many different models in a single draw call Drawing textured sprites with instanced drawing Efficient particle system in javascript? (WebGL) Emulating palette based graphics in WebGL FPS-like camera movement with basic matrix transformations Get the size of a point for collision checking GLSL shader to support coloring and texturing How can I compute for 500 points which of 1000 line segments is nearest to each point? How can I create a 16bit historgram of 16bit data How can I get all the uniforms and uniformBlocks How can I move the perspective vanishing point from the center of the canvas? How to Achieve Moving Line with Trail Effects How to bind an array of textures to a WebGL shader uniform? How to blend colors across 2 triangles How to combine more text drawing into fewer draw calls How to control the color between vertices How to create a torus How to detect clipped triangles in the framgment shader How to determine the average brightness in a scene? How to draw correctly textured trapezoid polygons How to fade the drawing buffer How to figure out how much GPU work to do without crashing WebGL How to get audio data into a shader How to get code completion for WebGL in Visual Studio Code How to get the 3d coordinates of a mouse click How to get pixelize effect in webgl? How to implement zoom from mouse in 2D WebGL How to import a heightmap in WebGL How to load images in the background with no jank How to make a smudge brush tool How to make WebGL canvas transparent How to optimize rendering a UI How to prevent texture bleeding with a texture atlas How to process particle positions How to read a single component with readPixels How to simulate a 3D texture in WebGL How to support both WebGL and WebGL2
How to render large scale images like 32000x32000
WebGLFundame · 2025-02-26 · via WebGL Fundamentals

Question:

I want to get a snapshot of my webgl canvas and I want a high resolution capture so I increased my canvas size. This automatically changes gl.draingBufferWidth and gl.draingBufferWidth. I then set viewport and then render the scene.

My code works correctly in low resolution (under 4000*4000) but in higher resolutions there are many problems.

If the resolution is a bit higher the snapshot not does not completely show. See attached file. If the resolution increases more nothing is shown. And finally at some resolutions my instance of webgl is destroyed and I have to restart the browser to get webgl running again

Is there any way to get a snapshot from webgl canvas with a high-resolution ? Can I use another solution?

Answer:

4000x4000 pixel is 4000x4000x4 or 64meg of memory. 8000x8000 is 256meg of memory. Browser's don't like allocating that large chunks of memory and often set limits on the page. So for example you have an 8000x8000 WebGL canvas which requires 2 buffers. The drawingbuffer AND the texture being displayed on the page. The drawingbuffer might be anti-aliases. If it's 4x MSAA then it would require a gig of memory just for that buffer. Then you take a screenshot so another 256meg of memory. So yes, the browser for one reason or another is likely to kill your page.

On top of that WebGL has it's own limits in size. You can look up that limit which is effectively MAX_TEXTURE_SIZE or MAX_VIEWPORT_DIMS. You can see from those about 40% of machines can't drawing larger than 4096 (although if you filter to desktop only it's much better). That number only means what the hardware can do. It's still limited by memory.

One way to kind of maybe solve this issue is to draw the image in parts. How you do that will depend on your app. If you're using a fairly standard perspective matrix for all your rendering you can use slightly different math to render any portion of the view. Most 3d math libraries have a perspective function and most of them also have a corresponding frustum function that is slightly more flexible.

Here's a fairly standard style WebGL simple sample that draws a cube using a typical perspective function

And here's the same code rendering at 400x200 in eight 100x100 parts using a typical frustum function instead of perspective

If you run the snippet above you'll see it's generating 8 images

The important parts are this

First we need to decide on the total size we want

const totalWidth = 400;
const totalHeight = 200;

Then we'll make a function that will render any smaller portion of that size

function renderPortion(totalWidth, totalHeight, partX, partY, partWidth, partHeight) {
   ...

We'll set the canvas to the size of the part

  gl.canvas.width = partWidth;
  gl.canvas.height = partHeight;

  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

And then compute what we need to pass to the frustum function. First we compute the rectangle at zNear that a perspective matrix would make given our field of view, aspect, and zNear values

  // corners at zNear for total image
  const zNearTotalTop = Math.tan(fov) * 0.5 * zNear;
  const zNearTotalBottom = -zNearTotalTop;
  const zNearTotalLeft = zNearTotalBottom * aspect;
  const zNearTotalRight = zNearTotalTop * aspect;

  // width, height at zNear for total image
  const zNearTotalWidth = zNearTotalRight - zNearTotalLeft;
  const zNearTotalHeight = zNearTotalTop - zNearTotalBottom;

Then we compute the corresponding area at zNear for the part of that we want to render and pass those to frustum to generate a projection matrix.

  const zNearPartLeft = zNearTotalLeft + partX * zNearTotalWidth / totalWidth;   const zNearPartRight = zNearTotalLeft + (partX + partWidth) * zNearTotalWidth / totalWidth;
  const zNearPartBottom = zNearTotalBottom + partY * zNearTotalHeight / totalHeight;
  const zNearPartTop = zNearTotalBottom + (partY + partHeight) * zNearTotalHeight / totalHeight;

  const projection = m4.frustum(zNearPartLeft, zNearPartRight, zNearPartBottom, zNearPartTop, zNear, zFar);

Then we just render like normal

Finally on the outside we have a loop to use the function we just generated to render as many parts as we want at whatever resolution we want.

const totalWidth = 400;
const totalHeight = 200;
const partWidth = 100;
const partHeight = 100;

for (let y = 0; y < totalHeight; y += partHeight) {
  for (let x = 0; x < totalWidth; x += partWidth) {
    renderPortion(totalWidth, totalHeight, x, y, partWidth, partHeight);
    const img = new Image();
    img.src = gl.canvas.toDataURL();
    // do something with image.
  }
}

This will let you render to any size you want but you'll need some other way to assemble the images into one larger image. You may or may not be able to do that in the browser. You could try making a giant 2D canvas and drawing each part into it (that assumes 2d canvas doesn't have the same limits as WebGL). To do that there's no need to make the images, just draw the webgl canvas into the 2d canvas.

Otherwise you might have to send them to a server you create to assemble the image or depending on your use case let the user save them and load them all into an image editing program.

Or if you just want to display them the browser will probably do better with 16x16 1024x1024 images than one 16kx16k image. In that case you probably want to call canvas.toBlob instead of using dataURLs and then call URL.createObjectURL for each blob. That way you won't have these giant dataURL strings sitting around.

Example:

If you want the user to be able to download a 16386x16386 image instead of 256 1024x1024 images then yet one more solution is to use the part rendering code above and for each row (or rows) of images write their data to a blobs to manually generate a PNG. This blog post covers manually generating PNGs from data and this answer suggests how to do it for very large data.

update:

Just for fun I wrote this library to help generate giant pngs in the browser.

The question and quoted portions thereof are CC BY-SA 4.0 by MHA15 from here