Skip to content

Recitation 04 Texture Mapping

jiju edited this page Oct 10, 2023 · 2 revisions

Objectives

Texture mapping is an important step in rendering photorealistic images. In most of the cases, the process deals with wrapping (or mapping) a texture image around(onto) a given 3D surface to be rendered. While some geometric shapes such as sphere, and cylinder have inherent mapping functions, finding an appropriate texture mapping function for real world objects with complex geometries remains a challenge. Usually texture (uv) coordinates are provided for object (e.g.,triangle mesh) vertices which are then interpolated to get the texture coordinates of triangle fragments(interior points of triangles). In this recitation, you will learn and implement bilinear interpolation based texture mapping for rendering a floor (two triangles) in ray tracing. alt text

Bilinear Interpolation

In texture mapping, when uv coordinates are not mapped to the exact centers of texels, we interpolate the texture value using the values of four neighboring pixels. Bilinear interpolation is commonly used. First we express the texture-space sample point in terms of (real-valued) texel coordinates, then we read the values of the four neighboring texels and interpolate them in horizontal and vertical directions to get the texture value (as shown in Figure 2). alt text

Getting Started

Please clone GraphicsLab into some folder. For this example, it will be cloned into the Desktop (~/Deskop). You can do this by opening git bash terminal and entering the following (alternatively, you can download the source code zip archive to the Desktop and extract it):

git clone https://github.com/jijup/GraphicsLab ~/Desktop/GraphicsLab

Once it is cloned (or unzipped), build the solution using CMake. Please follow the instructions from here.

Starter Code

The code provided to you renders a grass covered floor to the screen. It does this by ray tracing two triangles where if a ray intersects with the triangle, then the intersection point (closest to the camera) is set to a color value from the grass texture, otherwise the point is set to white. In the given code, one ray is generated per pixel, and is used to determine the color of the pixel. Multiple texture images such as sand, water, rock etc. are given under Textures folder. You may try different textures by changing the argument intex.loadTexture() and render the floor.

Specific Tasks

Task 1: Texture Coordinate Interpolation

The first task for you is to compute the texture(uv) coordinates of the Intersection point. A method called getTextureCoords() can be found in Triangle.cpp. Your task is to write the code for texture coordinate interpolation. To do so, first get the Barycentric coordinates of the Intersection point. Then use the barycentric coordinates to interpolate the texture coordinates of the triangle vertices. Note that the texture coordinates are avaibale for each triangle, text_coord1, text_coord2, text_coord3. Use first elements of texture coordinates to compute uv[0] and the second elements to compute uv[1].

Vec2 Triangle::getTextCoord(const Vec3& point) {
    Vec3 baryCoords = -------------;

    Vec2 uv;

    uv[0] = ----------------;
    uv[1] = ----------------;  
        
    return uv;
}

Task 2: Bilinear Interpolation

The second task for you is to implement bilinear interplation to determine the texture values. We will get the uv corrresponding to Intersection point using getTextureCoords() of the Triangle class. We will use thus obtained uv values to get the color value for the Intersection point. You will find an incomplete method called texture_lookup_bilinear() in Texture.cpp. The method is for implementing bilinear interpolation. You have to complete the code. You may use the following code (given in Figure 3) and the discussion on bilinear interpolation in one of the above sections while completing the method. alt text

cv::Vec3b Texture::texture_lookup_bilinear(const Vec2& uv) {
    float uv0 = --------;
    float uv1 = --------;
	
    int i0 = floor(uv0);
    int j0 = floor(uv1);

    //Bound the values between 0 and height/width
    i0 = clamp_w(i0);
    j0 = clamp_h(j0);

    //Next higher pixels in u and v directions
    int i1 = (i0 < height - 1) ?  i0 + 1 : i0;   
    int j1 = (j0 < width - 1) ?  j0 + 1 :  j0;
    
    //Parameters for interpolation
    float au =  --------;
    float av =  --------;    
    float bu = 1.0f - au;
    float bv = 1.0f - av;

    //Get the texture colrs of the four pixels    
    cv::Vec3b pixel00 = get_pixel(i0, j0);
    cv::Vec3b pixel01 = get_pixel(i0, j1);
    cv::Vec3b pixel10 = get_pixel(i1, j0);
    cv::Vec3b pixel11 = get_pixel(i1, j1);


    //Find the interpolated color
    cv::Vec3b pixelColor;    
    pixelColor[0] = -------------------;
    pixelColor[1] = -------------------;
    pixelColor[2] = -------------------;
    
    return pixelColor;
}

	

Important Notes

Please place Texture directory in the same directory where your executable is generated (e.g., build/texturing/Debug or build/texturing/Release).