# T3 Using Images as Textures (MS3)

### Use Sphere u, v texture Coordinates

Add a private static member function in class sphere to calcuate the spherical texture coordinates

```cpp
class sphere : public hittable {
  private:
    point3 center;
    double radius;
    shared_ptr<material> mat; 
    aabb bbox;  

    // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    static void get_sphere_uv(const point3& p, double& u, double& v) {
        // p: a given point on the sphere of radius one, centered at the origin.
        // u: returned value [0,1] of angle around the Y axis from X=-1.
        // v: returned value [0,1] of angle from Y=-1 to Y=+1.
        //     <1 0 0> yields <0.50 0.50>       <-1  0  0> yields <0.00 0.50>
        //     <0 1 0> yields <0.50 1.00>       < 0 -1  0> yields <0.50 0.00>
        //     <0 0 1> yields <0.25 0.50>       < 0  0 -1> yields <0.75 0.50>

        auto theta = std::acos(-p.y());
        auto phi = std::atan2(-p.z(), p.x()) + pi;

        u = phi / (2*pi);
        v = theta / pi;
    }
    // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    
    // ...
};
```

#### Update sphere::hit() to use get\_sphere\_uv()

```cpp
    bool hit(const ray& r, interval ray_t, hit_record& rec) const override {
        // ...

        rec.t = root;
        rec.p = r.at(rec.t);
        rec.normal = (rec.p - center) / radius;
        vec3 outward_normal = (rec.p - center) / radius;
        rec.set_face_normal(r, outward_normal);
        get_sphere_uv(outward_normal, rec.u, rec.v); // <<<<<<<<<<<<<<<<<<<<<<<<<<<
        rec.mat = mat; 

        return true;
    }
```

### Use Images as Textures

**Note: This chapter is slightly different from Prof. Shirley's tutorial.**

**We are using images in a similar way to our Semester 1.**

#### Use stb\_image.h

We have been using stb\_image.h from semester 1.

It is similar to use it here

Download stb\_image.h from github

{% embed url="<https://github.com/nothings/stb/blob/master/stb_image.h>" %}

Copy stb\_image.h to include/stb in your root folder.

Check your CMakeLists.txt to ensure the include directory is set

```
# specify include directories
target_include_directories(ray01 PRIVATE include)
```

#### Add class image\_texture in texture.h

Do not forget to add rtw\_stb\_image.h in the header section

```cpp
#include "rtw_stb_image.h" // <<<<<<<<<<<<<<<<<<<<<<<

// ...

class image_texture : public texture {
  public:
    image_texture(const char* filename) : image(filename) {}

    color value(double u, double v, const point3& p) const override {
        // If we have no texture data, then return solid cyan as a debugging aid.
        if (image.height() <= 0) return color(0,1,1);

        // Clamp input texture coordinates to [0,1] x [1,0]
        u = interval(0,1).clamp(u);
        v = 1.0 - interval(0,1).clamp(v);  // Flip V to image coordinates

        auto i = int(u * image.width());
        auto j = int(v * image.height());
        auto pixel = image.pixel_data(i,j);

        auto color_scale = 1.0 / 255.0;
        return color(color_scale*pixel[0], color_scale*pixel[1], color_scale*pixel[2]);
    }

  private:
    rtw_image image;
};

```

#### Create and use the images folder

Create a images folder in your root folder

Add instructions at the end of your CMakeLists.txt to copy those images to your build folder

```cmake
# copy the images folder 
add_custom_command(
        TARGET ray01 POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
		"${CMAKE_CURRENT_SOURCE_DIR}/images"
                "$<TARGET_FILE_DIR:ray01>/images"         
        )
```

#### Download earthmap.jpg

Download earthmap.jpg from <https://raytracing.github.io/images/earthmap.jpg> and save it in the images folder.

#### Add rtw\_stb\_image.h in your source folder

You don't need to study this file, we just use it directly.

You can directly download the file from <https://github.com/RayTracing/raytracing.github.io/blob/release/src/TheNextWeek/rtw_stb_image.h>

I changed #include "external/stb\_image.h" to my #include "stb/stb\_image.h".

If you are following Prof. Shirley's tutorial totally, you can stick to the original version.

```cpp
#ifndef RTW_STB_IMAGE_H
#define RTW_STB_IMAGE_H

// ...


#define STB_IMAGE_IMPLEMENTATION
#define STBI_FAILURE_USERMSG
//#include "external/stb_image.h"
#include "stb/stb_image.h" // << ======================

#include <cstdlib>
#include <iostream>

class rtw_image {
   // ...
};

// ..

#endif
```

### Draw a textured sphere in main.cpp

```cpp
#include "rtweekend.h"

#include "bvh.h"  
#include "camera.h"
#include "hittable.h"
#include "hittable_list.h"
#include "material.h" 
#include "sphere.h"
#include "texture.h" 


void earth() {
    auto earth_texture = make_shared<image_texture>("earthmap.jpg");
    auto earth_surface = make_shared<lambertian>(earth_texture);
    auto globe = make_shared<sphere>(point3(0,0,0), 2, earth_surface);

    camera cam;

    cam.aspect_ratio      = 16.0 / 9.0;
    cam.image_width       = 400;
    cam.samples_per_pixel = 100;
    cam.max_depth         = 50;

    cam.vfov     = 20;
    cam.lookfrom = point3(0,0,12);
    cam.lookat   = point3(0,0,0);
    cam.vup      = vec3(0,1,0);

    cam.defocus_angle = 0;

    cam.render(hittable_list(globe));
}


int main() {
    earth();
}
```

### Build and Run

If successful, you can see a texture mapped globe. Mine looks too dark because there is no Gamma correction.

<figure><img src="https://3464970502-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3JUKGJZ67JX02QZdPhsy%2Fuploads%2FspNmtZPQEbHyWN0kOrmn%2Ff01e3f27-696c-4aa7-b0f6-67bfea2b7c26.png?alt=media&#x26;token=3248cc60-34f9-4aa4-91b1-aea3d736b700" alt="" width="470"><figcaption></figcaption></figure>

The following is the rendering with Gamma correction:

<figure><img src="https://3464970502-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3JUKGJZ67JX02QZdPhsy%2Fuploads%2FwQigUXcEKDwFRDQhr9s7%2F29c75829-3606-415e-8ef1-7cfc58299849.png?alt=media&#x26;token=f753ad53-a25d-49b3-afdc-6a49eb6209fe" alt="" width="457"><figcaption></figcaption></figure>
