【GAMES101学习笔记】hw03 - 着色03(纹理映射)

1. 源代码

1.1 phong_fragment_shader()

Blinn-Phong 模型计算 Fragment Color

Eigen::Vector3f phong_fragment_shader(const fragment_shader_payload& payload)
{
    Eigen::Vector3f ka = Eigen::Vector3f(0.005, 0.005, 0.005);
    Eigen::Vector3f kd = payload.color;
    Eigen::Vector3f ks = Eigen::Vector3f(0.7937, 0.7937, 0.7937);

    auto l1 = light{{20, 20, 20}, {500, 500, 500}};
    auto l2 = light{{-20, 20, 0}, {500, 500, 500}};

    std::vector<light> lights = {l1, l2};
    Eigen::Vector3f amb_light_intensity{10, 10, 10};
    Eigen::Vector3f eye_pos{0, 0, 10};

    float p = 150;

    Eigen::Vector3f color = payload.color;
    Eigen::Vector3f point = payload.view_pos;
    Eigen::Vector3f normal = payload.normal;

    Eigen::Vector3f result_color = {0, 0, 0};
    for (auto& light : lights)
    {
        // TODO: For each light source in the code, calculate what the *ambient*, *diffuse*, and *specular* 
        // components are. Then, accumulate that result on the *result_color* object.

        auto light_vec = light.position - point;
        auto view_vec = eye_pos - point;
        auto radius2 = light_vec.dot(light_vec);
        auto light_vec_norm = light_vec.normalized();
        auto view_vec_norm = view_vec.normalized();

        // ambient term
        result_color += ka.cwiseProduct(amb_light_intensity);
        // diffuse term
        result_color += kd.cwiseProduct(light.intensity) / radius2
                        * std::max(0.0f, light_vec_norm.dot(normal));
        // specular term
        auto h_vec = (light_vec_norm + view_vec_norm).normalized();
        result_color += ks.cwiseProduct(light.intensity) / radius2
                        * std::pow(std::max(0.0f, h_vec.dot(normal)), p);
    }

    // for debugging
    // std::clog << result_color << std::endl;

    return result_color * 255.f;
}

1.2 texture_fragment_shader()

将纹理颜色参数视作公式中的 k d k_d kd

Eigen::Vector3f texture_fragment_shader(const fragment_shader_payload& payload)
{
    Eigen::Vector3f return_color = {0, 0, 0};
    if (payload.texture)
    {
        // TODO: Get the texture value at the texture coordinates of the current fragment
        return_color = payload.texture->getColor(payload.tex_coords(0), payload.tex_coords(1));
    }
    Eigen::Vector3f texture_color;
    texture_color << return_color.x(), return_color.y(), return_color.z();

    Eigen::Vector3f ka = Eigen::Vector3f(0.005, 0.005, 0.005);
    Eigen::Vector3f kd = texture_color / 255.f;
    Eigen::Vector3f ks = Eigen::Vector3f(0.7937, 0.7937, 0.7937);

    auto l1 = light{{20, 20, 20}, {500, 500, 500}};
    auto l2 = light{{-20, 20, 0}, {500, 500, 500}};

    std::vector<light> lights = {l1, l2};
    Eigen::Vector3f amb_light_intensity{10, 10, 10};
    Eigen::Vector3f eye_pos{0, 0, 10};

    float p = 150;

    Eigen::Vector3f color = texture_color;
    Eigen::Vector3f point = payload.view_pos;
    Eigen::Vector3f normal = payload.normal;

    Eigen::Vector3f result_color = {0, 0, 0};

    for (auto& light : lights)
    {
        // TODO: For each light source in the code, calculate what the *ambient*, *diffuse*, and *specular* 
        // components are. Then, accumulate that result on the *result_color* object.

        // copied from function *phong_fragment_shader*
        auto light_vec = light.position - point;
        auto view_vec = eye_pos - point;
        auto radius2 = light_vec.dot(light_vec);
        auto light_vec_norm = light_vec.normalized();
        auto view_vec_norm = view_vec.normalized();

        // ambient term
        result_color += ka.cwiseProduct(amb_light_intensity);
        // diffuse term
        result_color += kd.cwiseProduct(light.intensity) / radius2
                        * std::max(0.0f, light_vec_norm.dot(normal));
        // specular term
        auto h_vec = (light_vec_norm + view_vec_norm).normalized();
        result_color += ks.cwiseProduct(light.intensity) / radius2
                        * std::pow(std::max(0.0f, h_vec.dot(normal)), p);

    }

    return result_color * 255.f;
}

1.3 displacement_fragment_shader()

实现 displacement mapping(位移贴图)

Eigen::Vector3f displacement_fragment_shader(const fragment_shader_payload& payload)
{
    
    Eigen::Vector3f ka = Eigen::Vector3f(0.005, 0.005, 0.005);
    Eigen::Vector3f kd = payload.color;
    Eigen::Vector3f ks = Eigen::Vector3f(0.7937, 0.7937, 0.7937);

    auto l1 = light{{20, 20, 20}, {500, 500, 500}};
    auto l2 = light{{-20, 20, 0}, {500, 500, 500}};

    std::vector<light> lights = {l1, l2};
    Eigen::Vector3f amb_light_intensity{10, 10, 10};
    Eigen::Vector3f eye_pos{0, 0, 10};

    float p = 150;

    Eigen::Vector3f color = payload.color; 
    Eigen::Vector3f point = payload.view_pos;
    Eigen::Vector3f normal = payload.normal;

    float kh = 0.2, kn = 0.1;
    
    // TODO: Implement displacement mapping here
    // 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)
    // Normal n = normalize(TBN * ln)

    // copied from function *bump_fragment_shader*
    // map to local coord. system
    Eigen::Vector3f n = normal;
    Eigen::Vector3f t;
    t << n.x()*n.y()/std::sqrt(n.x()*n.x()+n.z()*n.z()),
         std::sqrt(n.x()*n.x()+n.z()*n.z()),
         n.z()*n.y()/std::sqrt(n.x()*n.x()+n.z()*n.z());
    Eigen::Vector3f b = n.cross(t);
    Eigen::Matrix3f TBN;
    TBN << t, b, n;

    // finite difference
    float u = payload.tex_coords(0), v = payload.tex_coords(1);
    float w = payload.texture->width;
    float h = payload.texture->height;
    // w: width of texture
    float dU = kh * kn * ( payload.texture->getColor(u+1.0f/w, v).norm() - payload.texture->getColor(u, v).norm() );
    // h: height of texture
    float dV = kh * kn * ( payload.texture->getColor(u+1, v+1.0f/h).norm() - payload.texture->getColor(u, v).norm() );
    Eigen::Vector3f ln = {-dU, -dV, 1.0f};
    // displacement
    point += kn * n * payload.texture->getColor(u, v).norm();
    normal = (TBN * ln).normalized();

    Eigen::Vector3f result_color = {0, 0, 0};

    for (auto& light : lights)
    {
        // TODO: For each light source in the code, calculate what the *ambient*, *diffuse*, and *specular* 
        // components are. Then, accumulate that result on the *result_color* object.

        // copied from function *phong_fragment_shader*
        auto light_vec = light.position - point;
        auto view_vec = eye_pos - point;
        auto radius2 = light_vec.dot(light_vec);
        auto light_vec_norm = light_vec.normalized();
        auto view_vec_norm = view_vec.normalized();

        // ambient term
        result_color += ka.cwiseProduct(amb_light_intensity);
        // diffuse term
        result_color += kd.cwiseProduct(light.intensity) / radius2
                        * std::max(0.0f, light_vec_norm.dot(normal));
        // specular term
        auto h_vec = (light_vec_norm + view_vec_norm).normalized();
        result_color += ks.cwiseProduct(light.intensity) / radius2
                        * std::pow(std::max(0.0f, h_vec.dot(normal)), p);
    }

    return result_color * 255.f;
}

2. 结果展示

screenShot.png

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值