【Ray Tracing The Next Week 超詳解】 光線追蹤2-5


 

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);
    }

}
image_texture.hpp

 

因為圖片信息是有一維數組存儲的,每個元素的rgb是順序存儲的,所以每個像素點有三個值,所以求取對應位置索引的時候要用3乘

 

現在我們需要的是讀取並存儲圖像文件

我們采用stb圖片讀取處理庫,我們就用一個函數

我們要在庫引用之前先定義一個宏

#define STB_IMAGE_IMPLEMENTATION

然后#include “stb_image.h”

如果你們找不到地球圖,就去我相冊中下載一下吧

或者隨便找一個也行

 

 然后就可以得到第一張圖

第二章圖的話,就是下面那個是金屬材質的球,可以采用下面函數

 

 

如果有什么代碼不完整的可以在下面留言

我們的代碼,一般情況下會在每本書的后面做統一的整理公布

 

感謝您的閱讀,生活愉快~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM