Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // -----------------------------------------------------------------------------
- /*
- * This method creates a mipmap hierarchy for
- * the texture.
- *
- * This is done by iteratively reducing the
- * dimenison of a mipmap level and averaging
- * pixel values until the size of a mipmap
- * level is [1, 1].
- *
- * The original data of the texture is stored
- * in mip_levels[0].
- *
- * You can allocale memory for a new mipmap level
- * with dimensions (size_x, size_y) using
- * mip_levels.emplace_back(new Image(size_x, size_y));
- */
- void ImageTexture::
- create_mipmap()
- {
- /* this are the dimensions of the original texture/image */
- int size_x = mip_levels[0]->getWidth();
- int size_y = mip_levels[0]->getHeight();
- cg_assert((size_x % 2 == 0) && !(size_x & (size_x - 1)));
- cg_assert((size_y % 2 == 0) && !(size_y & (size_y - 1)));
- int level = 0;
- while (size_x > 1 && size_y > 1) {
- level++;
- int redx = size_x > 1 ? 2 : 1;
- int redy = size_y > 1 ? 2 : 1;
- size_x = size_x /redx;
- size_y = size_y /redy;
- mip_levels.emplace_back(new Image(size_x, size_y));
- for (int x = 0; x < size_x; x++) {
- for ( int y = 0; y < size_y; y++){
- glm::vec4 px1 = mip_levels[level -1]->getPixel(x*redx, y*redy);
- glm::vec4 px2 = mip_levels[level -1]->getPixel(x*redx+1, y*redy);
- glm::vec4 px3 = mip_levels[level -1]->getPixel(x*redx, y*redy+1);
- glm::vec4 px4 = mip_levels[level -1]->getPixel(x*redx+1, y*redy+1);
- glm::vec4 avgpx = (px1 + px2 + px3 + px4)/ 4.f ;
- mip_levels[level]->setPixel(x, y, avgpx);
- }
- }
- }
- }
- /*
- * Compute the dimensions of the pixel footprint's AABB in uv-space.
- *
- * First intersect the four rays through the pixel corners with
- * the tangent plane at the given intersection.
- *
- * Then the given code computes uv-coordinates for these
- * intersection points.
- *
- * Finally use the uv-coordinates and compute the AABB in
- * uv-space.
- *
- * Return width (du) and height (dv) of the AABB.
- *
- */
- glm::vec2 Object::
- compute_uv_aabb_size(const Ray rays[4], Intersection const& isect)
- {
- // TODO: compute intersection positions
- glm::vec3 intersection_positions[4] = {
- isect.position, isect.position, isect.position, isect.position
- };
- for (int i = 0; i < 4; ++i) {
- // todo: compute intersection positions using a ray->plane
- // intersection
- Ray r = rays[i];
- float t = 0;
- if (intersect_plane(r.origin,r.direction, isect.position, isect.normal, &t)) {
- if( t>0) {
- intersection_positions[i] = r.origin + t * r.direction;
- }
- }
- }
- // compute uv coordinates from intersection positions
- glm::vec2 intersection_uvs[4];
- get_intersection_uvs(intersection_positions, isect, intersection_uvs);
- // TODO: compute dudv = length of sides of AABB in uv space
- float minx = intersection_positions[0].x;
- float maxx = intersection_positions[0].x;
- float miny = intersection_positions[0].y;
- float maxy = intersection_positions[0].y;
- for (int i = 0; i < 4; i++){
- minx = std::min(minx, intersection_uvs[i].x);
- maxx = std::max(maxx, intersection_uvs[i].x);
- miny = std::min(miny, intersection_uvs[i].y);
- maxy = std::max(maxy, intersection_uvs[i].y);
- }
- return glm::vec2(maxx-minx, maxy-miny);
- }
- /*
- * Implement trilinear filtering at a given uv-position.
- *
- * Transform the AABB dimensions dudv in st-space and
- * take the maximal coordinate as the 1D footprint size T.
- *
- * Determine mipmap levels i and i+1 such that
- * texel_size(i) <= T <= texel_size(i+1)
- *
- * Hint: use std::log2(T) for that.
- *
- * Perform bilinear filtering in both mipmap levels and
- * linearly interpolate the resulting values.
- *
- */
- glm::vec4 ImageTexture::
- evaluate_trilinear(glm::vec2 const& uv, glm::vec2 const& dudv) const
- {
- float T = std::max(dudv.x * mip_levels[0]->getWidth(), dudv.y * mip_levels[0]->getHeight());
- float level = std::max(0.f, log2(T));
- if (level >= mip_levels.size() - 1) {
- return evaluate_bilinear(mip_levels.size() - 1, uv);
- }
- float fak = level - floor(level);
- return (1-fak) * evaluate_bilinear(floor(level), uv) + fak * evaluate_bilinear(ceil(level), uv);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement