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”

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

    或者随便找一个也行

     然后就可以得到第一张图

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

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

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

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

  • 相关阅读:
    There is an overlap in the region chain修复
    There is an overlap in the region chain
    region xx not deployed on any region server
    python 中的re模块,正则表达式
    TCP粘包问题解析与解决
    yield from
    Git push提交时报错Permission denied(publickey)...Please make sure you have the correct access rights and the repository exists.
    mysql 中Varchar 与char的区别
    Mysql 字符集及排序规则
    请实现一个装饰器,限制该函数被调用的频率,如10秒一次
  • 原文地址:https://www.cnblogs.com/lv-anchoret/p/10295137.html
Copyright © 2011-2022 走看看