PBRT_V2 总结记录 ImageTexture

ImageTexture 类

// ImageTexture Declarations
template <typename Tmemory, typename Treturn>
    class ImageTexture : public Texture<Treturn> {
public:
    // ImageTexture Public Methods
    ImageTexture(TextureMapping2D *m, const string &filename, bool doTri,
                 float maxAniso, ImageWrap wm, float scale, float gamma);
    Treturn Evaluate(const DifferentialGeometry &) const;
    ~ImageTexture();
    static void ClearCache() {
        typename std::map<TexInfo, MIPMap<Tmemory> *>::iterator iter;
        iter = textures.begin();
        while (iter != textures.end()) {
            delete iter->second;
            ++iter;
        }
        textures.erase(textures.begin(), textures.end());
    }
private:
    // ImageTexture Private Methods
    static MIPMap<Tmemory> *GetTexture(const string &filename,
        bool doTrilinear, float maxAniso, ImageWrap wm, float scale, float gamma);
    static void convertIn(const RGBSpectrum &from, RGBSpectrum *to,
                          float scale, float gamma) {
        *to = Pow(scale * from, gamma);
    }
    static void convertIn(const RGBSpectrum &from, float *to,
                          float scale, float gamma) {
        *to = powf(scale * from.y(), gamma);
    }
    static void convertOut(const RGBSpectrum &from, Spectrum *to) {
        float rgb[3];
        from.ToRGB(rgb);
        *to = Spectrum::FromRGB(rgb);
    }
    static void convertOut(float from, float *to) {
        *to = from;
    }

    // ImageTexture Private Data
    MIPMap<Tmemory> *mipmap;
    TextureMapping2D *mapping;
    static std::map<TexInfo, MIPMap<Tmemory> *> textures;
};

类的作用:

(ImageTexture  保存".exr" ".tga" ".pfm" 文件数据,并且 ImageTexture 有两个模板,一个是决定 存成数据类型的,一个是决定 返回数据类型的  )

The ImageTexture class stores a 2D array of point-sampled values of a texture function.
It uses these samples to reconstruct a continuous image function that can be evaluated
at an arbitrary (s , t) position.
These sample values are often called texels, since they
are similar to pixels in an image but are used in the context of a texture.

The ImageTexture class is different from other textures in the system in that it is parameterized
on both the data type of the texels it stores in memory as well as the data
type of the value that it returns.
Making this distinction allows us to create, for example,
ImageTextures that store RGBSpectrum values in memory, but always return Spectrum values.
In this way, when the system is compiled with full-spectral rendering enabled, the
memory cost to store full SampledSpectrum texels doesn’t necessarily need to be paid.

1. 构造函数

template <typename Tmemory, typename Treturn>
ImageTexture<Tmemory, Treturn>::ImageTexture(TextureMapping2D *m,
        const string &filename, bool doTrilinear, float maxAniso,
        ImageWrap wrapMode, float scale, float gamma) {
    mapping = m;
    mipmap = GetTexture(filename, doTrilinear, maxAniso,
                        wrapMode, scale, gamma);
}

MIPMap<Tmemory> *mipmap;
TextureMapping2D *mapping;

作用:

(在构造函数中,利用MIPMap进行存储图片数据)

The caller provides the ImageTexture with the filename of an image map, parameters that
control the filtering of the map for antialiasing, and parameters that make it possible to
scale and gamma-correct the texture values.

For an ImageTexture that stores RGBSpectrum values in memory, its MIPMap stores the
image data using three floating-point values for each sample.
This can be a somewhat
wasteful representation, since a single image map may have millions of texels and may
not need the full 32 bits of accuracy from the floats used to store RGB values for each of
them.

The ImageTexture constructor calls the static
ImageTexture::GetTexture() method to get a MIPMap representation of the desired texture.

2. static MIPMap<Tmemory> *GetTexture(const string &filename,
        bool doTrilinear, float maxAniso, ImageWrap wm, float scale, float gamma);

template <typename Tmemory, typename Treturn>
    std::map<TexInfo,
             MIPMap<Tmemory> *> ImageTexture<Tmemory, Treturn>::textures;

template <typename Tmemory, typename Treturn> MIPMap<Tmemory> *
ImageTexture<Tmemory, Treturn>::GetTexture(const string &filename,
        bool doTrilinear, float maxAniso, ImageWrap wrap,
        float scale, float gamma) {

    // Look for texture in texture cache
    TexInfo texInfo(filename, doTrilinear, maxAniso, wrap, scale, gamma);
    if (textures.find(texInfo) != textures.end())
        return textures[texInfo];

    int width, height;
    RGBSpectrum *texels = ReadImage(filename, &width, &height);
    MIPMap<Tmemory> *ret = NULL;
    if (texels) {
        // Convert texels to type _Tmemory_ and create _MIPMap_
        Tmemory *convertedTexels = new Tmemory[width*height];
        for (int i = 0; i < width*height; ++i)
            convertIn(texels[i], &convertedTexels[i], scale, gamma);
        ret = new MIPMap<Tmemory>(width, height, convertedTexels, doTrilinear,
                                  maxAniso, wrap);
        delete[] texels;
        delete[] convertedTexels;
    }
    else {
        // Create one-valued _MIPMap_
        Tmemory *oneVal = new Tmemory[1];
        oneVal[0] = powf(scale, gamma);
        ret = new MIPMap<Tmemory>(1, 1, oneVal);
        delete[] oneVal;
    }
    textures[texInfo] = ret;
    PBRT_LOADED_IMAGE_MAP(const_cast<char *>(filename.c_str()), width, height, sizeof(Tmemory), ret);
    return ret;
}

细节:

a.

TexInfo texInfo(filename, doTrilinear, maxAniso, wrap, scale, gamma);
if (textures.find(texInfo) != textures.end())
    return textures[texInfo];

作用:

(先检查缓存是否存在相同的 texture,如果存在的话,就直接返回,如果不存在才进行加载)

An image map may require a significant amount of memory; because the user may
reuse a texture many times within a scene, pbrt maintains a table of image maps that
have been loaded so far, so that they are only loaded into memory once even if they are used in more than one ImageTexture.

If the image map does need to be loaded from disk, ReadImage() handles the lowlevel
details of this process and returns an array of texel values.

TexInfo is a simple structure that holds the image map’s filename and filtering parameters;
all of these must match for a MIPMap to be reused in another ImageTexture.

struct TexInfo {
    TexInfo(const string &f, bool dt, float ma, ImageWrap wm, float sc, float ga)
        : filename(f), doTrilinear(dt), maxAniso(ma), wrapMode(wm), scale(sc), gamma(ga) { }
    string filename;
    bool doTrilinear;
    float maxAniso;
    ImageWrap wrapMode;
    float scale, gamma;
    bool operator<(const TexInfo &t2) const {
        if (filename != t2.filename) return filename < t2.filename;
        if (doTrilinear != t2.doTrilinear) return doTrilinear < t2.doTrilinear;
        if (maxAniso != t2.maxAniso) return maxAniso < t2.maxAniso;
        if (scale != t2.scale) return scale < t2.scale;
        if (gamma != t2.gamma) return gamma < t2.gamma;
        return wrapMode < t2.wrapMode;
    }
};

b.

    int width, height;
    RGBSpectrum *texels = ReadImage(filename, &width, &height);
    MIPMap<Tmemory> *ret = NULL;
    if (texels) {
        // Convert texels to type _Tmemory_ and create _MIPMap_
        Tmemory *convertedTexels = new Tmemory[width*height];
        for (int i = 0; i < width*height; ++i)
            convertIn(texels[i], &convertedTexels[i], scale, gamma);
        ret = new MIPMap<Tmemory>(width, height, convertedTexels, doTrilinear,
                                  maxAniso, wrap);
        delete[] texels;
        delete[] convertedTexels;
    }

作用:

( ReadImage 这个方法读取图片文件之后,是直接返回一个 RGBSpectrum 数组,因为 ImageTexture的存储格式是一个模板,所以,需要利用 convertIn 来把 RGBSpectrum  转换为 对应的模板格式)

Because the image-loading routine returns an array of RGBSpectrum values for the texels,
it is necessary to convert these values to the particular type Tmemory of texel that this
MIPMap is storing
(e.g., float) if the type of Tmemory isn’t RGBSpectrum. The per-texel
conversion is handled by the utility routine ImageTexture::convertIn(). This conversion

is wasted work in the common case where the MIPMap is storing RGBSpectrum values, but
the flexibility it gives is worth this relatively small cost in efficiency

c.

static void convertIn(const RGBSpectrum &from, RGBSpectrum *to,
    float scale, float gamma) {
    *to = Pow(scale * from, gamma);
}

static void convertIn(const RGBSpectrum &from, float *to,
    float scale, float gamma) {
    *to = powf(scale * from.y(), gamma);
}

作用:

(convertIn 除了 转换 类型,还有其他的选项,例如 scale 和 gamma correct ,

converIn也可能会执行 gamma correct ,其实这里就类似图片的sRGB,

sRGB,它使用的encoding gamma大约是0.45(也就是1/2.2), display gamma为2.5的设备工作的。这样,end-to-end gamma就是0.45 * 2.5 = 1.125了。 )

Per-texel conversion is done using C++ function overloading. For every type to which
we would like to be able to convert these values, a separate ImageTexture::convertIn()
function must be provided. In the loop over texels earlier, C++’s function overloading
mechanism will select the appropriate instance of ImageTexture::convertIn() based on
the destination type.

In addition to converting types, these functions optionally scale and gamma correct the
texel values to map them to a desired range.

Gamma correction is particularly important
to handle carefully: computer displays have the property(属性) that most of them don’t exhibit
a linear relationship between the pixel values to be displayed and the radiance that they
emit.
Thus, an artist may create a texture map where, as seen on an LCD display, one part
of the image appears twice as bright as another. However, the corresponding pixel values
won’t in fact have a 2:1 relationship. (Conversely, pixels that do have a 2:1 relationship
don’t lead to pixels with a 2:1 brightness ratio.)

This discrepancy(不符) is a problem for a renderer using such an image as a texture map,
since the renderer usually expects a linear relationship between texel values and the
quantity that they represent. In practice, the relationship between pixel values and display
brightness is well modeled with a power curve with the exponent of a value gamma.
(Gamma values between 1.5 and 2.2 are typical.)
Gamma correction, as performed in
convertIn(), can be used to restore(恢复) an approximately linear relationship between texel
values and the values they are intended to represent.

d.

        // Create one-valued _MIPMap_
        Tmemory *oneVal = new Tmemory[1];
        oneVal[0] = powf(scale, gamma);
        ret = new MIPMap<Tmemory>(1, 1, oneVal);
        delete[] oneVal;

作用:

(如果读取图片失败的话,就创建1个 只有1个像素的 image)

If the texture file wasn’t found or was unreadable, an image map with a single sample
with a value of one is created so that the renderer can continue to generate an image
of the scene without needing to abort execution.
The ReadImage() function will issue a
warning message in this case.

3. 

    static void ClearCache() {
        typename std::map<TexInfo, MIPMap<Tmemory> *>::iterator iter;
        iter = textures.begin();
        while (iter != textures.end()) {
            delete iter->second;
            ++iter;
        }
        textures.erase(textures.begin(), textures.end());
    }

作用:

(清理 缓存 Texture)

After the image is rendered and the system is cleaning up, the ClearCache() method is
called to free the memory for the entries in the texture cache.

4. 

template <typename Tmemory, typename Treturn> Treturn
ImageTexture<Tmemory,
             Treturn>::Evaluate(const DifferentialGeometry &dg) const {
    float s, t, dsdx, dtdx, dsdy, dtdy;
    mapping->Map(dg, &s, &t, &dsdx, &dtdx, &dsdy, &dtdy);
    Tmemory mem = mipmap->Lookup(s, t, dsdx, dtdx, dsdy, dtdy);
    Treturn ret;
    convertOut(mem, &ret);
    return ret;
}

    static void convertOut(const RGBSpectrum &from, Spectrum *to) {
        float rgb[3];
        from.ToRGB(rgb);
        *to = Spectrum::FromRGB(rgb);
    }
    static void convertOut(float from, float *to) {
        *to = from;
    }

作用:

(Evaluate 先利用 mapping 计算自己的 uv 纹理坐标,再利用uv纹理坐标 去直接 在 mipmap 上查找 值,并且在 mipmap->Lookup中做 过滤,实现抗锯齿,之后再把查到的 值 的类型 进行转换为 返回值模板类型)

The ImageTexture::Evaluate() routine does the usual texture coordinate computation
and then hands the image map lookup to the MIPMap
, which does the image filtering
work for antialiasing. The returned value is still of type Tmemory; another conversion step
similar to ImageTexture::convertIn() above converts to the returned type Treturn.

猜你喜欢

转载自blog.csdn.net/aa20274270/article/details/83746635
今日推荐