OpenGL: Large texture 'maps' versus multiple singular textures performance - opengl-es

I'm deciding if I want to create a map of multiple textures of my entire scene into several 1024x1024 texture atlases. Is it much of a gain at all to have fewer, larger textures so that you can make less GL render calls, albeit with the same number of overall triangles? Is this something that's common?
In my case, I'm targeting an iPad with about a 5,000 triangle scene with 16 textures. Given the distribution I'm looking at around 5x more calls to glDrawArrays if I don't combine.

Related

Is a large MTLTexture more performant than using multiple smaller MTLTextures?

I'm using Metal to display an image into a 2D plane. The image is being rendered as tiles to an IOSurface using Core Image. After each tile is rendered, the IOSurface is sent via XPC to the app, wrapped in an MTLTexture and its contents are copied to a master texture using a blit encoder. The IOSurface is then re-used if need-be.
I have full control over the tile sizes and texture sizes and I'm wondering if Metal prefers having a small number of large textures, a large number of small textures or if it just doesn't really matter.
There are some tradeoffs that I've already come across and the most notable one is that if I use smaller textures then the cost to (re)generate the mipmaps can be smaller. There's also the issue of textures having a maximum size of 16384, which implies that any image larger than that needs to be tiled anyways.
Consider the following:
Image dimensions used below are just for easy math, in real life I'm working with DSLR images, panoramas, stitched images, etc..
#1 - A single texture that covers the entire image:
Texture Type: MTLTextureType2D
Texture Size: 400 x 300 px
When Core Image renders a tile and I copy it into the texture, I have to regenerate the mipmaps for the entire texture, even though most of the texture's content did not change.
#2 - Using two textures:
Texture Type: MTLTextureType2DArray
Texture Array Count: 2
Texture Size: 200 x 300 px (x2)
With two tiles covering the image's content, I only have to regenerate the mipmaps for the "dirty" tile.
#3 - Using many textures:
Texture Type: MTLTextureType2DArray
Texture Array Length: 12
Texture Size: 100 x 100 px (x12)
In this scenario, I can minimize mipmap generation by matching the texture tile size to my rendering tile size, but it will require a large number of MTLTextures.
MTLTextureDescriptor.arrayLength is documented as being able to hold values between 1..2048, which suggests to me that using a large number of textures isn't such a bad thing.
A single texture is passed to my fragment shader and all it does is sample the color at the appropriate coordinates.
Using smaller-sized textures gives me a lot more fidelity in marking the "dirty" regions of the image that need invalidating, but I'm curious if the large number of textures is to be avoided or not.
My current attempts at measuring the performance are somewhat inclusive to me and I wonder if that's because this doesn't matter at all from Metal's perspective. Ultimately, the same amount of memory is needed (from my perspective) but I'd be interested to know if there are performance trade-offs I'm not aware of.

rendering millions of voxels using 3D textures with three.js

I am using three.js to render a voxel representation as a set of triangles. I have got it render 5 million triangles comfortably but that seems to be the limit. you can view it online here.
select the Dublin model at resolution 3 to see a lot of triangles being drawn.
I have used every trick to get it this far (buffer geometry, voxel culling, multiple buffers) but I think it has hit the maximum amount that openGL triangles can accomplish.
Large amounts of voxels are normally rendered as a set of images in a 3D texture and while there are several posts on how to hack 2d textures into 3D textures but they seem to have a maximum limit on the texture size.
I have searched for tutorials or examples using this approach but haven't found any. Has anyone used this approach before with three.js
Your scene is render twice, because SSAO need depth texture. You could use WEBGL_depth_texture extension - which have pretty good support - so you just need a single render pass. You can stil fallback to low-perf-double-pass if extension is unavailable.
Your voxel's material is double sided. It's may be on purpose, but it may create a huge overdraw.
In your demo, you use a MeshPhongMaterial and directional lights. It's a needlessly complex material. Your geometries don't have any normals so you can't have any lighting. Try to use a simpler unlit material.
Your goal is to render a huge amount of vertices, so assuming the framerate is bound by vertex shader :
try stuff like https://github.com/GPUOpen-Tools/amd-tootle to preprocess your geometries. Focusing on prefetch vertex cache and vertex cache.
reduce the bandwidth used by your vertex buffers. Since your vertices are aligned on a "grid", you could store vertices position as 3 Shorts instead of 3 floats, reducing your VBO size by 2. You could use a same tricks if you had normals since all normals should be Axis aligned (cubes)
generally reduce the amount of varyings needed by fragment shader
if you need more attributes than just vec3 position, use one single interleaved VBO instead of one per attrib.

How mipmaps affect static batching on 2D sprites

I am optimizing my 2D mobile game. There are many sprites with POT size all over the game and I have filled their Packing Tag to enable batching and also checked their Generate Mip Maps checkbox. All these sprites have uniform scales in the game and most of them are (1,1,1).
What I intend to do is to minimize the number of Batches in the game.
What I want to figure out is how mipmaps affect the number of batches in a 2D game?
This is what I have tried:
I copied two sprites several times with different but uniform scales and reported the number of batches.
The circle has POT size and mipmap enabled; The square is not, it's just a sprite; Both have the same packing tag, so they reside in different atlases.
Also checking or unchecking Static for these game objects does not change anything.
3 batches when two different sprites are drawn
7 batches when two different sprites are drawn but in a little bit different positions
1 batch when only one mipmap sprite is drawn
1 batch when only one non-mipmap sprite is drawn. the positions of the game objects are the same as 1st test case where there were 7 batches.

Which is more efficient and on which mobile phones - Texture size

I'm in the final stages of optimizing my game. I use three different texture sizes depending on how big the screen of the mobile is (big for H>1280, medium for H<=1280, and small for H<=640).
I want to know what's more efficient (FPSwise) for the medium screen size (640 < H <= 1280) a big 1024x1024 PNG texture or 2x512x512 PNG textures.
One texture means one texture change (setup) per render so that's good; but 1024 is big. The two 512 textures mean 2 texture changes per render , but on the other hand they are smaller. Which way is best?
POT textures do not need to be squares. They just need to have the power-of-two dimensions. So, you can use one 1024x512 texture and not need to switch textures during render.

How do I properly group polygons into arrays?

I want to render a scene in OpenGL ES, but I have a problem.
Because there is no immediate mode in ES, and simulating immediate mode with single-polygon buffers is slow, I can't just switch textures and skip invisible polygons, so I have to group my polygons.
Here are characteristics of different polygons:
Diffuse texture (mipmapped, lots of them).
Lightmap texture (packed, up to 64 textures).
Visibility.
At first I thought to group the polygons only by visibility area, but I couldn't find a way to use texture index arrays.
So, how do I properly make buffers of polygons to render?
I will make visibility groups with texture subgroups. Quake uses 64 128x128 lightmaps, I'm going to replace them with a single 1024x1024 lightmap, since modern hardware supports textures of such size.

Resources