Suppose I'm making a VkSampler, or possibly a set of VkSamplers, that I'm planning on using with several textures. Each texture has multiple mip levels, and the number of mip levels varies from texture to texture. I want all sampler options to be the same for all the textures, with the possible exception of maxLod.
I don't actually want maxLod to block any particular mip levels from being used; I only want all of each texture's levels to be used in an ordinary, non-erroneous way. So can I just throw in an absurdly high upper bound and use the same sampler for all the textures:
VkSamplerCreateInfo samplerCreateInfo;
...
samplerCreateInfo.minLod = 0;
samplerCreateInfo.maxLod = 1048576;
...or do I need to create a different sampler for each texture and set maxLod for the sampler to that texture's unique maximal mip index?
I think the answer is probably that I can count on reasonable clamping to happen even if my sampler's maxLod is very high - even if I then explicitly pass a uselessly high value to textureLod in a shader - but I'm not totally sure I've correctly interpreted the relevant sections in the Vulkan and GLSL specifications.
No, you can make maxLod as large as you want. If there were cases where it would be "too high", they would be listed as Valid Usage requirements. According to the spec, the only requirements are that it be greater than or equal to minLod, and if unnormalizedCoordinates is true then it must be zero. Beyond that, it is only used to clamp the computed lod. The actual mipmap level accessed is the computed lod (clamped to maxLod), further clamped to the number of mipmaps levels actually available in the texture.
In spec language, maxLod is used to limit the value of λ (Level of Detail Operation). Then the mipmap level accessed, is d' = levelbase + clamp(λ, 0, levelCount - 1) (Image Level(s) Selection). So if maxLod is larger than levelCount - 1, it won't affect the outcome.
Related
What value does the LOD parameter take for texturelod? The spec I found doesn't mention it at all. Is it a percentage or an index value with a percent. If the later is the case, is there a way to get the number of mipmaps the texture has so that I would be able to use a percentage?
The LOD parameter specifies the mipmap level, rounded to the nearest whole number. Remember that OpenGL specifies mipmap levels, such that 0 is the largest, with increasing numbers going smaller.
However, the LOD specified here will always be relative to the current GL_TEXTURE_BASE_LEVEL of the texture. So if you use textureLod(..., 0), and the base level is set to mipmap 2, then you will select from mipmap level 2. You also cannot select mipmaps outside of the GL_TEXTURE_MAX_LEVEL range; the system will automatically clamp the specified parameter appropriately.
What value does the LOD parameter take for texturelod? The spec I found doesn't mention it at all. Is it a percentage or an index value with a percent. If the later is the case, is there a way to get the number of mipmaps the texture has so that I would be able to use a percentage?
The LOD parameter specifies the mipmap level, rounded to the nearest whole number. Remember that OpenGL specifies mipmap levels, such that 0 is the largest, with increasing numbers going smaller.
However, the LOD specified here will always be relative to the current GL_TEXTURE_BASE_LEVEL of the texture. So if you use textureLod(..., 0), and the base level is set to mipmap 2, then you will select from mipmap level 2. You also cannot select mipmaps outside of the GL_TEXTURE_MAX_LEVEL range; the system will automatically clamp the specified parameter appropriately.
I have a feeling this is one of those situations that will depend on the driver implementation since this scenario is not described in the OpenGL specification. However, I'm hoping that someone will know if using GL_(LINEAR/NEAREST)_ MIPMAP_* without generating MIP maps would be treated the same as using GL_(LINEAR/NEAREST)?
Define "without any active MIP textures"? I'm not sure how you would, since there's no such thing as a "mip texture" (a texture contains mipmaps, but mipmaps are not textures).
If you mean that you did not create a full mipmap pyramid, then it depends on how you set up your GL_TEXTURE_BASE/MAX_LEVELs. If you properly used these to tell OpenGL you only had one mipmap level, then you'll be fine. If you used glTexStorage to create your texture's storage, and you only told it to create one mipmap, again you'll be fine.
But if none of those apply, then OpenGL defaults to the least useful thing (per its usual idiocy): it sets the GL_TEXTURE_MAX_LEVEL level to 1000. Which means it's going to expect you to have defined mipmaps.
According to (desktop) OpenGL, a texture with mipmap filtering where the BASE/MAX_LEVELs refer to mipmaps that are not defined is not "texture complete". OpenGL defines that the value you get for a texture access against a non-complete texture is (0, 0, 0, 1).
In short, set your BASE/MAX_LEVEL properly and you won't have to worry. ALWAYS DO THIS.
In my experience, all the non-generated mipmap levels will default to black.
So if you have a texture displayed at 1:1 resolution, and progressively zoom out, it will fade to black as soon as the 1rst mipmap is used.
I think this is the behaviour at least on NVIDIA and AMD; I never tried on powervr (since you're mentioning opengl-es).
I have a seamlessly tilable texture.
In the fragmentshader i calculate the texturecoordinates UVproc procedurally using a function that jumps from 1.0 to 0.0 at some point (here the texture should repeat nicely).
the problem is that at this seam, the lookup seems to return pixelvalues from the smallest mipmap level.
If i debugoutput
out = vec4(dFdx(UVproc.x), dFdy(UVproc.y),0,1);
then i can see that at those pixels the finite differences of these texturecoordinates are very high and therefore a small mipmap level is accessed (makes sense - as there is a jump from 1 to 0 at those pixels, the finite differences will be big).
If i manually just access mipmaplevel 0 using textureLod() then i don't have this problem, but i also loose mipmapping and everything gets grainy.
so the question is:
How can I avoid visible mipmap related seams if texturecoordinates (in the range 0-1) are procedurally calculated in the fragment shader?
You should use gradient texture sampling, manually setting the derivatives. Here's a function for it:
gvec textureGrad(gsampler sampler, vec texCoord, gradvec dTdx, gradvec dTdy);
Hey, I have a texture loaded with glTextImage2D.
I want to get the texture's size after it was loaded to the VRAM, what do I need to do?
My internal format is RGBA and the texture's format varies.
This might be helpful to you and you can probably infer the actual memory usage from it. However, I believe this still is rather an approximation:
http://www.geeks3d.com/20100531/programming-tips-how-to-know-the-graphics-memory-size-and-usage-in-opengl/
(query the total memory usage of OpenGL using NVIDIA or ATI specific extensions)
Also note that from my experience, approximating the memory usage by rough calculation was usually sufficient. Textures "should" be stored either 1,2 or 4 components without any significant overhead. Therefore for a WxH RGBA texture, calculate W*H*4. If you store float textures (i.e. GL_RGBA32F), calculate W*H*4*4. For Mip-Maps, add (1/3) additional memory consumption. Be aware however, that - at least to my knowledge - texture memory can also fragment, possibly leaving you with less available memory as estimated.
Use GetTexLevelParameter, which can give you (for each level):
Width and height *
Depth
Internal format *
Compressed format and relative size
(*) Uses these parameters for computing the texture size (for the specified level).
The single texture memory usage is dependent on the generated mipmaps. Indeed to compute correctly the memory used by a single texture you have to determine the mipmaps related to the textures, and then sum the memory usage for each level.
The mipmap count is determined by the OpenGL specification depending on the texture target: texture arrays elements has their own mipmaps set, each cube face texture has its own mipmap set.
The dimension of the mipmaps are halfed for each level, untill they goes to 1. In the case the dimension are not power of two, they are rounded to the lower integer.