Why can't I cap mipmap level?

For a long time now I’ve been really wishing I could get the ability to cap mipmap levels.

The current mipmap system generates all the way to mip 9 for any texture - essentially to where the texture ends up as a solid color by mip 9.

This does NOT work for tile atlases. For a 512x512 resolution texture, with tiles at a resolution of 32x32 (as they are for my voxel engine), mip 5 is the point where each tile is a solid color.

You can’t do any better than that. If you go to mip 6+, it starts combining several tiles together into a solid color and you end up with terrible colorations at farther view distances.

The simple solution would be to let me say that I want it to go no further than mip 5. Ignore 6 through 9.

Is it that simple? Is there something that makes this really difficult? Do you think I can expect Unity to do something like this in the future, or is it something that is simply not viable due to how different platforms handle things?

I am not a fan of the alternatives provided:

-Sure I can pad my tile sheet, but that really makes my UV calculations a nightmare.
-Sure I can pad them with the width of a tile, but then I can only put half the number of tiles per sheet.
-Sure I can use mipmapBias, but that seems to only increase the distance required to trigger a mip for all levels - which ruins it for the low mips that should trigger closer to the player.
-Antialiasing does not remove the aliasing at a level I require, though it certainly helps. And I’m talking very expensive super sampling AA, not the lousy AA Unity provides by default. Super sampling is not viable on some platforms and machines.

Are there any other solutions that aren’t awful?

As a note, this was posted in the feedback section back in 2013:

http://feedback.unity3d.com/suggestions/maximum-mipmap-level

And there’s still nothing done about it. For something so seemingly simple, why can’t anything get done about this?

Edit: can this get moved to the Graphics section? I suppose it belongs there more than it belongs here.

You could create your own asset with the number of mipmaps you want, did you know that? At least I’m pretty sure.

I mean it would be sweet if there were some more mipmap generation controls built in…but…

I have not been able to find a way to do it on the Mac. If someone here could give me some resources showing how to do this on a Mac, it would be great.

From the manual: http://cdn.imgtec.com/sdk-documentation/PVRTexTool.User+Manual.pdf

Generates MIP maps for the current texture. An optional unsigned integer
can be added to specify the number of MIP map levels which should be
generated; otherwise a full chain is created.
Usage:

m
Example:

m 9

1 Like

Interesting, I did not come across this tool somehow.

I’ve created my texture with the five mipmap levels I want and imported it into Unity.

How do I set filter mode to Point now? I seem to be unable to edit this .pvr texture within Unity. Can I do it via script?

Check page 32 in that manual. http://cdn.imgtec.com/sdk-documentation/PVRTexTool.User+Manual.pdf

Unity uses that tool to do all of it’s generation, it feeds it commands. You are just giving it your own! :slight_smile:

No matter how I encode it, I get this:

2306171--155361--GrayedOut.png

It’s grayed out and I can’t change anything.
I am new to this whole realm so I really don’t know what I’m doing.

I did not do anything through script, though. Maybe I’m supposed to perform a step through there as well? The link posted for the answers page showed an additional step, but I am unsure if it is relevant for my use case.

I simply want to import it in the editor and then set filter mode to point.

Oh, I was thinking of filter for generating mip maps, not AF.

You can try doing it in scripting: Unity - Scripting API: FilterMode

I finally got it to work, but turns out Unity just fills missing mip maps with pure black - so now you see pure black in the distance…

Seems this is on Unity, unless I messed it up somehow.

Unity just added Texture Array support for Unity 5.4 on the roadmap. This problem may be solved in another way, then :slight_smile:

I know this is really old and im sure everyone will have long moved on but I spent a while stuck on this, I saw TextureArray support as quite cool but also kinda contrary to the lightweight nature of a texture atlas.

I wanted a way to cap the mipmap level in Unity something I could plug into an existing shader for a deferred pipeline, this is probably not elegant and im fascinated if anyone has insight on how this compares to a texture atlas performance wise but anyway here is something for the next person who searches on this topic:

SubShader {
Tags { “RenderType”=“AlphaTest” }
CGPROGRAM
#pragma surface surf Lambert nofog

sampler2D _MainTex;
// Unity will provide the textures dimensions here for you
uniform float4 _MainTex_TexelSize;

// I used a GL mipmap function from
// opengl - How to access automatic mipmap level in GLSL fragment shader texture? - Stack Overflow
// Does not take into account GL_TEXTURE_MIN_LOD/GL_TEXTURE_MAX_LOD/GL_TEXTURE_LOD_BIAS,
// nor implementation-specific flexibility allowed by OpenGL spec
float mip_map_level(in float2 texture_coordinate) // in texel units
{
float2 dx_vtc = ddx(texture_coordinate);
float2 dy_vtc = ddy(texture_coordinate);
float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
float mml = 0.5 * log2(delta_max_sqr);
return max(0, mml); // Thanks @Nims
}

void surf (Input IN, inout SurfaceOutput o) {
float mipmapLevel = mip_map_level(IN.uv_MainTex * _MainTex_TexelSize.z);

if (mipmapLevel > 4) {
mipmapLevel = 4;
}

fixed4 c = tex2Dlod(_MainTex, float4(IN.uv_MainTex, 0, mipmapLevel));

The output was better than expected but I cant speak for the efficiency of this workaround.

Happy coding! :slight_smile: