如何使用textureLod对GLSL中的MIP级别进行采样?

eh57zj3b  于 2022-09-26  发布在  其他
关注(0)|答案(2)|浏览(386)

如何使用textureLod()对GLSL中的MIP级别进行采样?

据我所知,mipmap LOD只能通过顶点着色器“显式*”访问(尽管不确定420版是否支持它,因为大多数文档已经过时)。其次,您需要通过设置纹理参数来定义mipmap的细节层次,如GL_纹理_MAX_LEVELGL_TEXTURE_BASE_LEVEL**。

在我的代码中,我在调用glCompressedTexImage2D后定义了这些纹理参数:

glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, min_filter);
glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, mag_filter);
glTexParameteri(texture_type, GL_TEXTURE_MAX_LEVEL, 9);
glTexParameteri(texture_type, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap_s);
glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, wrap_t);

接下来,我为每个绑定每个纹理样本(类型,如反照率贴图等)使用此代码:

glActiveTexture(GL_TEXTURE0 + unit);    // Set active texture type
glBindTexture(GL_TEXTURE_2D, id);   // Bind the texture object

最后,下面是我的着色器代码:

顶点:


# version 420 core

out vec3 _texcoord;
out vec4 _albedo_lod;

uniform sampler2D albedo;   // Albedo and specular map

void main()
{
    _texcoord = texcoord;
    _albedo_lod = textureLod(albedo, vec2(_texcoord.st), 2.0);
}

使用附加的片段:


# version 420 core

layout(location = 0) out vec4 gAlbedo;  // Albedo texel colour

in vec3 _texcoord;
in vec4 _albedo_lod;

void main()
{
    gAlbedo = _albedo_lod;  // Assign albedo
}

现在,由于某种原因,无论我输入什么LOD值,结果总是这样:

似乎是最后一个MIP级别(不管我输入了什么值)。请记住,我将10个MIP级别打包为一个**.dds文件。然而,当我通过纹理参数GL_TEXTURE_BASE_LEVEL**手动设置基本MIP级别时,它起作用了。

因此,总而言之,为什么它不能使用textureLod在GLSL中采样正确的MIP级别?这在版本420中是否有些过时?

**EDIT:**DDS文件加载代码如下:

// This function imports a dds file and returns the dds data as a struct
inline GLuint LoadDds(std::vector<std::string> file, size_t &img_width, size_t &img_height, size_t &num_mips, GLvoid* data, GLint wrap_s, GLint wrap_t, GLint min_filter, GLint mag_filter, size_t texture_type, bool anistropic_filtering)
{

    // Create one OpenGL texture
    GLuint textureID;
    glGenTextures(1, &textureID);

    // "Bind" the newly created texture : all future texture functions will modify this texture
    glBindTexture(texture_type, textureID);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    for (unsigned int i = 0; i < file.size(); i++)  // For each image...
    {
        FILE *fp;

        unsigned char header[124];
        unsigned int height;
        unsigned int width;
        unsigned int linearSize;
        unsigned int mipMapCount;
        unsigned int fourCC;
        unsigned int components;
        unsigned int format;
        unsigned int bufsize;
        unsigned char* buffer;

        /* try to open the file */
        errno_t err;
        err = fopen_s(&fp, file[i].c_str(), "rb");
        if (fp == NULL)
            return 0;

        /* verify the type of file */
        char filecode[4];
        fread(filecode, 1, 4, fp);
        if (strncmp(filecode, "DDS ", 4) != 0)
        {
            fclose(fp);
            return 0;
        }

        /* get the surface desc */
        fread(&header, 124, 1, fp);

        height = *(unsigned int*)&(header[8]);
        width = *(unsigned int*)&(header[12]);
        linearSize = *(unsigned int*)&(header[16]);
        mipMapCount = *(unsigned int*)&(header[24]);
        fourCC = *(unsigned int*)&(header[80]);
        bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
        buffer = (unsigned char*)malloc(bufsize * sizeof(unsigned char));

        fread(buffer, 1, bufsize, fp);

        /* close the file pointer */
        fclose(fp);

        components = (fourCC == FOURCC_DXT1) ? 3 : 4;
        switch (fourCC)
        {
        case FOURCC_DXT1:
            format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
            break;
        case FOURCC_DXT3:
            format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
            break;
        case FOURCC_DXT5:
            format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
            break;
        default:
            free(buffer);
            return 0;
        }

        unsigned int blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;

        unsigned int offset = 0;
        for (unsigned int level = 0; level < mipMapCount && (width || height); ++level)
        {
            unsigned int size = ((width + 3) / 4) * ((height + 3) / 4) * blockSize;
            glCompressedTexImage2D(texture_type != GL_TEXTURE_CUBE_MAP ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, level, format, width, height,
                0, size, buffer + offset);

            if ((level < 1) && (i < 1))     // Only assign input variable values from first image
            {
                img_width = width;  // Assign texture width
                img_height = height;    // Assign texture height
                data = buffer;  // Assign buffer data
                num_mips = mipMapCount;     // Assign number of mips
            }

            offset += size;
            width /= 2;
            height /= 2;
        }

        if (anistropic_filtering)   // If anistropic_filtering is true...
        {
            GLfloat f_largest;  // A contianer for storing the amount of texels in view for anistropic filtering
            glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &f_largest);     // Query the amount of texels for calculation
            glTexParameterf(texture_type, GL_TEXTURE_MAX_ANISOTROPY_EXT, f_largest);    // Apply filter to texture
        }

        if (!mipMapCount)
            glGenerateMipmap(texture_type); // Generate mipmap

        free(buffer);   // Free buffers from memory
    }

    // Parameters
    glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, min_filter);
    glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, mag_filter);
    glTexParameteri(texture_type, GL_GENERATE_MIPMAP, GL_TRUE);
    glTexParameteri(texture_type, GL_TEXTURE_MAX_LEVEL, 9);
    glTexParameteri(texture_type, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap_s);
    glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, wrap_t);

    // Set additional cubemap parameters
    if (texture_type == GL_TEXTURE_CUBE_MAP)
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, wrap_s);

    return textureID;   // Return texture id
}

下面是使用NVIDIA的DDS插件生成的每个mipmap级别的图像:

tkclm6bt

tkclm6bt1#

由于逐顶点采样,这似乎正是预期的行为。

你说MIP级别参数没有影响,但从我所能看到的,只有当像素密度低于顶点密度并且值开始平均时,差异才应该是明显的。然而,如果你不存储整个mipchain,这可能永远不会发生,因为最低的分辨率可能仍然有足够的清晰度(我真的不能从屏幕截图中分辨出来,我只能猜测模型的镶嵌)。

但是,因为您是手动生成mipchain的,所以您可以很容易地为每个级别测试不同的平面颜色,并查看它们是否确实被正确获取(实际上,如果您不确定导入器,可能也值得首先在像素着色器中尝试)。

epggiuax

epggiuax2#

您需要将GL_TEXTURE_MIN_FILTER设置为GL_LINEAR_MIPMAP_LINEAR或其他mipmap模式。

相关问题