如何确定在GLSL片段着色器中对纹理进行采样时使用的mipmap级别?
我知道我可以使用textureLod(...)
方法手动采样纹理的特定mipmap级别:
uniform sampler2D myTexture;
void main()
{
float mipmapLevel = 1;
vec2 textureCoord = vec2(0.5, 0.5);
gl_FragColor = textureLod(myTexture, textureCoord, mipmapLevel);
}
或者我可以使用texture(...)
uniform sampler2D myTexture;
void main()
{
vec2 textureCoord = vec2(0.5, 0.5);
gl_FragColor = texture(myTexture, textureCoord);
}
我更喜欢后者,因为我相信司机对合适的mipmap级别的判断比我自己的判断更多。
但我想知道在自动采样过程中使用了什么mipmap级别,以帮助我合理地对附近的像素进行采样。 GLSL中有没有办法访问有关自动纹理样本使用的mipmap级别的信息?
答案 0 :(得分:22)
以下是针对此问题的三种不同方法,具体取决于您可以使用哪些OpenGL功能:
正如Andon M. Coleman在评论中指出的那样,OpenGL 4.00及以上版本的解决方案很简单;只需使用textureQueryLod
功能:
#version 400
uniform sampler2D myTexture;
in vec2 textureCoord; // in normalized units
out vec4 fragColor;
void main()
{
float mipmapLevel = textureQueryLod(myTexture, textureCoord).x;
fragColor = textureLod(myTexture, textureCoord, mipmapLevel);
}
在早期版本的OpenGL(2.0+?)中,您可能能够加载扩展,以达到类似的效果。这种方法适用于我的情况。 注意:方法调用在扩展程序中的大写不同,与内置(queryTextureLod
vs queryTextureLOD
)不同。
#version 330
#extension GL_ARB_texture_query_lod : enable
uniform sampler2D myTexture;
in vec2 textureCoord; // in normalized units
out vec4 fragColor;
void main()
{
float mipmapLevel = 3; // default in case extension is unavailable...
#ifdef GL_ARB_texture_query_lod
mipmapLevel = textureQueryLOD(myTexture, textureCoord).x; // NOTE CAPITALIZATION
#endif
fragColor = textureLod(myTexture, textureCoord, mipmapLevel);
}
如果加载扩展程序不起作用,您可以使用genpfault提供的方法估算自动细节级别:
#version 330
uniform sampler2D myTexture;
in vec2 textureCoord; // in normalized units
out vec4 fragColor;
// 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 vec2 texture_coordinate) // in texel units
{
vec2 dx_vtc = dFdx(texture_coordinate);
vec2 dy_vtc = dFdy(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 main()
{
// convert normalized texture coordinates to texel units before calling mip_map_level
float mipmapLevel = mip_map_level(textureCoord * textureSize(myTexture, 0));
fragColor = textureLod(myTexture, textureCoord, mipmapLevel);
}
在任何情况下,对于我的特定应用程序,我最终只是计算主机端的mipmap级别,并将其传递给着色器,因为自动细节级别并不是我所需要的。
答案 1 :(得分:10)
来自here:
查看OpenGL 4.2 spec章节3.9.11公式3.21。基于导数矢量的长度计算mip映射水平:
float mip_map_level(in vec2 texture_coordinate) { vec2 dx_vtc = dFdx(texture_coordinate); vec2 dy_vtc = dFdy(texture_coordinate); float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)); return 0.5 * log2(delta_max_sqr); }