Chapter 5:Image Texture Mapping
先看效果:
我們之前的紋理是利用的是撞擊點p處的位置信息,比如大理石紋理
而我們今天的圖片映射紋理采用2D(u,v)紋理坐標來進行。
在圖像中使用縮放(u,v)的直接方法是將u和v四舍五入為整數,並將其作用於(i,j)像素。而,我們的紋理和物體的尺寸並不一致,所以我們需要將其規格化,然后再放大適應至物體尺寸。即,我們采用某個點在當前圖像中的比例,而不是具體的位置,例如,對於nx乘ny圖像中的像素(i,j),圖像紋理位置為:
u = i / (nx - 1)
v = j / (ny - 1)
對於intersect,我們還需要在相交碰撞記錄中返回u和v。對於球體,我們采用球面坐標。即:
如上坐標系采用光線追蹤慣用坐標系,設P點為單位球上一點
∠θ 為xOz平面與線段OP之間的夾角,θ∈0~π
∠φ 為線段OP在xOz平面的映射線與x軸正方向之間的夾角,φ∈0~2π
則:
x = cosφ· cosθ
z = sinφ· cosθ
y = sinθ
將θ和φ規格化到【0,1】,則如下:
u = φ/(2π)
v = θ/π
過程:
我們先將撞擊點的坐標映射到單位球面上(規格化),得到紋理坐標
然后材質紋理反射的時候將此規格化坐標帶入
根據圖片的規格展開得到圖片對應的位置,返回圖片對應處的rgb
可見,撞擊點處應該存儲關於圖片紋理坐標的信息
所以,我們先將撞擊點信息更新:
獲取紋理坐標
反射求取圖片對應出的像素值
我們來解決圖片紋理對應的value函數
下面是圖片紋理類

/// image_tex.hpp // ----------------------------------------------------- // [author] lv // [begin ] 2019.1 // [brief ] the image_texture-class for the ray-tracing project // from the 《ray tracing the next week》 // ----------------------------------------------------- #pragma once namespace rt { class image_texture: public texture { public: image_texture() { } image_texture(unsigned char* image, size_t a, size_t b); inline unsigned char* image()const { return _image; } inline size_t sizeX()const { return _sizeX; } inline size_t sizeY()const { return _sizeY; } public: virtual rtvec value(rtvar u, rtvar v, const rtvec& p)const override; private: unsigned char* _image; size_t _sizeX; size_t _sizeY; }; image_texture::image_texture(unsigned char* image, size_t a, size_t b) :_image(image) ,_sizeX(a) ,_sizeY(b) { } rtvec image_texture::value(rtvar u, rtvar v, const rtvec& p)const { int i = u*_sizeX; int j = (1 - v)*_sizeY - 0.001; if (i < 0)i = 0; if (j < 0)j = 0; if (i > _sizeX - 1)i = _sizeX - 1; if (j > _sizeY - 1)j = _sizeY - 1; rtvar r = int(_image[3 * i + 3 * _sizeX*j]) / 255.0; rtvar g = int(_image[3 * i + 3 * _sizeX*j + 1]) / 255.0; rtvar b = int(_image[3 * i + 3 * _sizeX*j + 2]) / 255.0; return rtvec(r, g, b); } }
因為圖片信息是有一維數組存儲的,每個元素的rgb是順序存儲的,所以每個像素點有三個值,所以求取對應位置索引的時候要用3乘
現在我們需要的是讀取並存儲圖像文件
我們采用stb圖片讀取處理庫,我們就用一個函數
我們要在庫引用之前先定義一個宏
#define STB_IMAGE_IMPLEMENTATION
然后#include “stb_image.h”
如果你們找不到地球圖,就去我相冊中下載一下吧
或者隨便找一個也行
然后就可以得到第一張圖
第二章圖的話,就是下面那個是金屬材質的球,可以采用下面函數
如果有什么代碼不完整的可以在下面留言
我們的代碼,一般情況下會在每本書的后面做統一的整理公布
感謝您的閱讀,生活愉快~