Hiya, pretty new to VFX. I’m experiencing some strange lines up the sides of the cylinder mesh. Do i need to have more sides on the cylinder?
This is an artifact of mip mapping.
GPUs calculate the mip level based on how much the texture UV changes from one screen pixel to the ones directly next to it. If the distance max change in UV in any direction is less than the width of a texel, it uses the largest mip (aka, the original texture). If it’s more than a texel width distance it calculates the appropriate mip level such that the mip map’s resolution will be roughly 1 texel between screen pixels.
When surfaces approach being parallel to the view direction, the change between one pixel and the next can reach over the entire UV. This it true even on triangles that only show a small part of the overall texture, because the GPU is extrapolating the UV for the “next pixel” even if the triangle isn’t visible in more than one. So the mip level starts going to infinity and the mip drops to the smallest 1x1 mipmap regardless of the texture size.
There are a few fixes to this.
- Disable Mip Mapping on the texture: This is usually the first option you’ll find online. Don’t do this. It does work, but it will mean aliasing and possible performance problems.
- Enable Anisotropic Filtering: Not a 100% solution, but can minimize the effect significantly. I said above that the mip level is calculated from the max of much the UV changes in any direction. That’s true for point, bilinear, and trilinear filtering. Anisotropic filtering works roughly by calculating the min change in any direction for the mip level and then samples the texture multiple times along the max change direction (how many times is controlled by the Aniso level). It’s a little more complicated than that, and at the extreme grazing angles it’ll still drop the mip level to infinity, but it should be much less apparent.
- Shrink the mesh: The cylinder mesh being used should only cover the area that’s visible. The lines will still show along the sides, but will be significantly hidden by the rest of the effect. This is a good idea regardless of what kind of effect you’re doing, as otherwise you’re wasting a lot of GPU resources rendering stuff that’s invisible. An “invisible” transparent mesh is just as expensive as a visible one.
- Fresnel Fade: Use a custom shader that fades out the mesh when the triangles are getting close to parallel with the view. This is your basic Fresnel / outline / glow shader, and really it’s a dot product between the view direction and surface normal. For double sided surfaces use the abs() of the dot product. You can then use a smoothstep() to adjust the fade point to between something like 0.05 and 0.1 so most of the cylinder is still visible.
- Fade Mip To Color: Effectively the same as using a Fresnel glow, but you have less control and it’ll fade out when you’re far away too.
- Clamp Mip Level: You can calculate the mip level in a shader and clamp it to some level above the smallest mip. Unity technically supports textures without a full mip chain so you could limit the mip level on the texture asset itself, but this only for textures created from script and not by the built in importer which makes this a bit annoying to work with.
- Add More Particles!: Really, just add a lot more stuff to the effect so no one will notice.
Thank you so(!) much for the detailed answer! Really helped me understand the issue
I will try and start with solution 3, as i already thought about that
Again thank you so much.
@bgolus has a great answer. There is one more possible fix. In the texture’s advanced import settings there is also an option to “Border Mip Maps” that copies the border pixels into the borders of each mip level. It isn’t clear to me which pixel(s) gets copied, though.
@bgolus really good response. thanks for contributing to our education!
Whether or not Border Mip Maps fixes this depends on the content of the image. If the texture you’re using has color all the way to the edges, as it should for a horizontally repeating texture like this example, the 1x1 will end up very similar to the mip map w/o the Border Mip Maps enabled. So in this case it will not fix the problem.
For example, here’s a similar noisy glow texture like what’s being used above, and the 1x1 mip map with and without the Border Mip Maps enabled.
They look almost identical, and in this case the one with it enabled is slightly brighter!
But if you add a 1 pixel border around the entire image it will make the 1x1 mip disappear.
But this just adds a new issue, which is there’s an obvious black seam when the texture repeats, and it’s a line that “grows” with the mip map as it’s always 2 texels wide.
That’s why I didn’t mention it as a fix for this case. It works for more punctual fx textures, but not for any texture that needs to wrap.