GAMES101 闫令琪图形学 作业3

作业3

问题描述

在这里插入图片描述
重心坐标公式:
在这里插入图片描述

auto v = t.toVector4();

    // 构建包围盒
    float min_x = std::min(v[0][0], std::min(v[1][0], v[2][0]));
    float max_x = std::max(v[0][0], std::max(v[1][0], v[2][0]));
    float min_y = std::min(v[0][1], std::min(v[1][1], v[2][1]));
    float max_y = std::max(v[0][1], std::max(v[1][1], v[2][1]));
    //依次遍历包围盒所有像素
    for (int x = min_x; x <= max_x; x++)
    {
        for (int y = min_y; y <= max_y; y++)
        {   //判断当前点是否在三角形内
            if (insideTriangle(x + 0.5, y + 0.5, t.v))
            {
                //重心坐标公式  求 alpha, beta, gamma三点值
                auto [alpha, beta, gamma] = computeBarycentric2D(x + 0.5, y + 0.5, t.v);
                //v[i].w()为顶点视图空间深度值z。
                //Z是为当前像素插值的视图空间深度
                //zp是zNear和zFar之间的深度,用于z缓冲
                float Z = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
                float zp = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
                zp *= Z;
                //如果当前 深度值小 更新深度值 
                if (zp < depth_buf[get_index(x, y)])
                {
                    // 根据重心 插入属性 颜色 法线 纹理 材质坐标
                    auto interpolated_color = interpolate(alpha, beta, gamma, t.color[0], t.color[1], t.color[2], 1);
                    auto interpolated_normal = interpolate(alpha, beta, gamma, t.normal[0], t.normal[1], t.normal[2], 1).normalized();
                    auto interpolated_texcoords = interpolate(alpha, beta, gamma, t.tex_coords[0], t.tex_coords[1], t.tex_coords[2], 1);
                    auto interpolated_shadingcoords = interpolate(alpha, beta, gamma, view_pos[0], view_pos[1], view_pos[2], 1);

                    // 用来传递插值结果的结构体
                    fragment_shader_payload payload(interpolated_color, interpolated_normal, interpolated_texcoords, texture ? &*texture : nullptr);
                    payload.view_pos = interpolated_shadingcoords;
                    //不是直接将三角形的颜色传递到帧缓冲区,而是首先将颜色传递到着色器以获得最终的颜色
                    auto pixel_color = fragment_shader(payload);
                    // 更新深度
                    depth_buf[get_index(x, y)] = zp;
                    // 更新颜色
                    set_pixel(Eigen::Vector2i(x, y), pixel_color);
                }
            }
        }
    }

在这里插入图片描述
作业一
在这里插入图片描述

在这里插入图片描述
环境光:
在这里插入图片描述
漫反射:
在这里插入图片描述
高光
在这里插入图片描述

Eigen::Vector3f light_dir = light.position - point;// 光线距离
        Eigen::Vector3f view_dir = eye_pos - point;// 视线方向    
        float r = light_dir.dot(light_dir);// 衰减因子

        // La 环境光 颜色强度
        Eigen::Vector3f La = ka.cwiseProduct(amb_light_intensity);
        // Ld 漫反射  (I/(r*r))
        Eigen::Vector3f Ld = kd.cwiseProduct(light.intensity / r);//衰减
        Ld *= std::max(0.0f, normal.normalized().dot(light_dir.normalized()));
        // Ls 高光 
        Eigen::Vector3f h = (light_dir + view_dir).normalized();//半程向量
        Eigen::Vector3f Ls = ks.cwiseProduct(light.intensity / r);//衰减
        Ls *= std::pow(std::max(0.0f, normal.normalized().dot(h)), p);

        result_color += (La + Ld + Ls);

在这里插入图片描述
在这里插入图片描述
查找纹理颜色的接口:Vector3f getColor(float u, float v)

Eigen::Vector3f getColor(float u, float v)
    {
        // 坐标限定
        if (u < 0) u = 0;
        if (u > 1) u = 1;
        if (v < 0) v = 0;
        if (v > 1) v = 1;
        auto u_img = u * width;
        auto v_img = (1 - v) * height;
        auto color = image_data.at<cv::Vec3b>(v_img, u_img);
        return Eigen::Vector3f(color[0], color[1], color[2]);
    }
Eigen::Vector3f return_color = {0, 0, 0};
    if (payload.texture)
    {
        // 在当前片段的纹理坐标处获取纹理值
        return_color = payload.texture->getColor(payload.tex_coords.x(), payload.tex_coords.y());
    }
    
    Eigen::Vector3f texture_color;
    texture_color << return_color.x(), return_color.y(), return_color.z();
	//漫反射 反射出 纹理颜色
    Eigen::Vector3f kd = texture_color / 255.f;

在这里插入图片描述
在这里插入图片描述
实现凹凸映射

Eigen::Vector3f n = normal;// Let n = normal = (x, y, z)
    float x = normal.x();
    float y = normal.y();
    float z = normal.z();
    // Vector t = (x*y/sqrt(x*x+z*z),sqrt(x*x+z*z),z*y/sqrt(x*x+z*z))
    Eigen::Vector3f t{ x * y / std::sqrt(x * x + z * z), std::sqrt(x * x + z * z), z * y / std::sqrt(x * x + z * z) };
    // Vector b = n cross product t
    Eigen::Vector3f b = normal.cross(t);
    // Matrix TBN = [t b n]
    Eigen::Matrix3f TBN;
    TBN << t.x(), b.x(), n.x(),
           t.y(), b.y(), n.y(),
           t.z(), b.z(), n.z();

    float u = payload.tex_coords.x();
    float v = payload.tex_coords.y();
    float w = payload.texture->width;
    float h = payload.texture->height;
    
    // dU = kh * kn * (h(u+1/w,v)-h(u,v))
    // dV = kh * kn * (h(u,v+1/h)-h(u,v))
    float dU = kh * kn * (payload.texture->getColor(u + 1.0f / w, v).norm() - payload.texture->getColor(u, v).norm());
    float dV = kh * kn * (payload.texture->getColor(u, v + 1.0f / h).norm() - payload.texture->getColor(u, v).norm());
    
    // Vector ln = (-dU, -dV, 1)
    Eigen::Vector3f ln{ -dU,-dV,1.0f };
    // Normal n = normalize(TBN * ln)
    n = (TBN * ln).normalized();
 
    return n * 255.f;

在这里插入图片描述

在这里插入图片描述
凹凸贴图

// TODO: 在这里实现位移映射 同上
    // Let n = normal = (x, y, z)
    // Vector t = (x*y/sqrt(x*x+z*z),sqrt(x*x+z*z),z*y/sqrt(x*x+z*z))
    // Vector b = n cross product t
    // Matrix TBN = [t b n]
    // dU = kh * kn * (h(u+1/w,v)-h(u,v))
    // dV = kh * kn * (h(u,v+1/h)-h(u,v))
    // Vector ln = (-dU, -dV, 1)
    // Position p = p + kn * n * h(u,v)
    point += (kn * n * payload.texture->getColor(u, v).norm());
    // Normal n = normalize(TBN * ln)

在这里插入图片描述

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值