zoukankan      html  css  js  c++  java
  • 【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”

    如果你们找不到地球图,就去我相册中下载一下吧

    或者随便找一个也行

     然后就可以得到第一张图

    第二章图的话,就是下面那个是金属材质的球,可以采用下面函数

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

    我们的代码,一般情况下会在每本书的后面做统一的整理公布

    感谢您的阅读,生活愉快~

  • 相关阅读:
    VSFTP日志文件详解
    RocketMQ多master多salve集群搭建
    数据持久化之bind Mounting
    数据持久化之Data Volume
    gitLab 分支保护设置
    docker容器的端口映射
    docker命令之link
    NFS客户端挂载失败之authenticated unmount request from
    docke网络之bridge、host、none
    docke通信之Linux 网络命名空间
  • 原文地址:https://www.cnblogs.com/lv-anchoret/p/10295137.html
Copyright © 2011-2022 走看看