1. 程式人生 > >PBRT_V2 總結記錄 ImageTexture

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.