Texture Atlases and Merge BufferGeometry

I’ve been playing around with texture atlases the past few days and have been having a bit of fun. One thing that I did which I’m not sure on how beneficial it was, was to combined my mesh diffuse, normal and specular maps into a single image. Was a fun project, works great.

What I am considering now is something that I’m sure will have a payoff. I have several meshes that use merged buffergeometry with multiple groups for material indexes. I originally did this as opposed to separate meshes thinking it would make a difference. Turns out… not so much. Each Mesh has as many drawcalls as it’s geometry has groups.

So, what I am thinking of is creating a texture atlas that contains the diffuse/normal and specular maps for each piece of merged geometry.

Before I start coding this out, will this even work? I am going to need to know at least the geometries current index value in order to determine which uv coordinate to sample right?

I know I can access the gl_VertexID according to https://www.khronos.org/opengl/wiki/Built-in_Variable_(GLSL), however since this is not accessible in the fragment shader (right?), would I need to create a varying variable in order to access this value within the fragment shader? Is there a better (or more common) way to do this?

Not sure if it’s worth all this work, but I am super curious.

I’m relatively new to shader programming so sorry if this is a dumb question.

I think this should be possible:

  1. merge the meshes with BufferGeometryUtils.mergeBufferGeometries(), using groups
  2. add a groupIndex attribute to the geometry, so all vertices for mesh N have value N
  3. delete the geometry’s groups
  4. in the vertex shader, use groupIndex to offset the UV attribute appropriately, storing the result in a varying vUVMesh
  5. sample the texture in the fragment shader
1 Like

Ah, ok I see. I will give it a shot.Thank you!

It seems this method does not work with Indexed BufferGeometry. Having trouble figuring out how to correctly assign a groupIndex per vertex based on the index array. Was hoping that assigning the uvIndex per Index would work as the vertex shader seems to understand indexes at least according to that article I referenced above.

I did get this to work when manually building the uv offset attribute (sort of, I approximated the groupIndex vertex cutoff point), so I was happy to see at least some action =]

Could you possibly create a small demo of using animated texture atlases when you ‘do’ figure this out? I would like to study it if possible. :slight_smile: Thank You!

I’m fairly confident that once I alter the desired geometry to be non indexed via BufferGeometry.toNonIndexed(), this will be a relative cake walk. I just have to modify a bit of code first to accommodate. I aim to have this completed this weekend. If successful, I will post some reference code.

Got this working. I’ll post some code in a bit, however following donmccurdy’s instructions works well (with non indexed buffer geometry).

I used this to attempt to optimize performance by reducing drawcalls. On my desktop (Ryzen 1600, GeForce GTX 1060), I actually noticed an improvement which was unexpected, however on mobile (Samsung Galaxy s7 edge) I seem to have taken a slight loss. I need to analyze this. My guess is that somehow gpu usage was increased due to the extra calculations (even though there should be less texture switching) which is overshadowing the cpu usage decrease from eliminating drawcalls by roughly 50%). Weird, I dunno.

1 Like

that would be great, thanks titansoftime! :slight_smile:

Were you still able to post something, @titansoftime ?

Here is an earlier example:

https://jsfiddle.net/titansoftime/o674d2qh/

It has added complexity of texture splatting and repeating textures, but should have all the info you need to implement a texture atlas.

I’ve implemented something similar i supose, it merges the hierarchy of an object with all meshes/subgeometries into one geometry, material and a texture atlas for each map type.

Asides of saving drawcalls the main reason was to get a full automatic merge for instancing. It handles the texture atlas layout of textures of different sizes, matching in a power of 2 layout and optionally scales their sizes down when generating, for example when used as LOD technique.

Since textures can be of different sizes, it seems more efficient to use an atlas per map-type, also since texture size is limited depending on GPU.

Here a little more to it, its part of a project i release soon.

@Fyrestar When is this being released?! and will it be open source?! :open_mouth: