作业3 光栅化渲染(Blinn-Phong etc)

作业3简单介绍

作业3 Pipeline and Shading 作业3介绍 作业三 发现了许多问题

1. 前两次作业三角形原来画反了

这里其实是坐标的问题,因为我们的zNear和zFar传入的是整数,但实际上,相机照的地方是z的负轴,说实话,有一点不懂,如果不做点改变,会颠倒180°。网上的方法大都是求t的时候添加一个负号。也有把传入的值改为负号的,但是这样虽然是正了,但是作业三shading的时候,得到的牛是牛的屁股,因为规定的z-buffer和实际上的z值反了,这里z轴的值应该就是存的深度信息,所以我们看到了后面的值,这里呢,也有一个改法,某个地方填个负号就好了。

2.第二次写的时候框架还是有些不懂

虽然给了注释,但是还是好多注释看不懂,图形学咋学,感觉懂了点然后又不懂。

code: 光栅化代码,这里用了重心坐标对颜色、纹理、法线、视口进行了插值。

 auto[alpha, beta, gamma] = computeBarycentric2D(x+0.5, y+0.5, t.v);
                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)]) {
                    depth_buf[get_index(x,y)] = zp;
                    auto interpolated_color = interpolate(alpha,beta,gamma,t.color[0],t.color[1],t.color[2],1.0);
                    auto interpolated_normal = interpolate(alpha,beta,gamma,t.normal[0],t.normal[1],t.normal[2],1.0).normalized();
                    auto interpolated_texcoords = interpolate(alpha,beta,gamma,t.tex_coords[0],t.tex_coords[1],t.tex_coords[2],1.0);
                    auto interpolated_shadingcoords = interpolate(alpha,beta,gamma,view_pos[0],view_pos[1],view_pos[2],1.0);

                    fragment_shader_payload payload( interpolated_color, interpolated_normal, interpolated_texcoords, texture ? &*texture : nullptr);
                    payload.view_pos = interpolated_shadingcoords;
                    auto pixel_color = fragment_shader(payload);
                    Eigen::Vector2i point;
                    point << x,y;
                    set_pixel(point, pixel_color*(cnt*1.0/4.0));
                }

这里代码就不放完了,循环里是Blinn-Phong,计算三种光最后加到颜色里。

纹理贴图就是把纹理的颜色加进来了,具体看代码和作业;

bump凹凸贴图和Displacement位移贴图感觉还不咋懂,这俩好像差不多,另外还有一个地方,就是Texture里getColor需要修改,不然会段错误,主要是防止越界吧。感觉可以把OpenGL一起学习。

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} };

	if (payload.texture)
    {
        // TODO: Get the texture value at the texture coordinates of the current fragment
         return_color = payload.texture->getColor(payload.tex_coords.x(), payload.tex_coords.y()); 

    }
    
    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)
    float x = normal.x(), y = normal.y(), z = normal.z();
    Eigen::Vector3f n = {x,y,z};
    Eigen::Vector3f t = {x*y/sqrt(x*x+z*z),sqrt(x*x+z*z),z*y/sqrt(x*x+z*z)};
    Eigen::Vector3f b = normal.cross(t);
    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;
    
    float dU = kh * kn * (payload.texture->getColor(u+1.0/w,v).norm()-payload.texture->getColor(u,v).norm());
    float dV = kh * kn * (payload.texture->getColor(u,v+1.0/h).norm()-payload.texture->getColor(u,v).norm());

    point = point + kn * normal * payload.texture->getColor(u,v).norm();
    Eigen::Vector3f ln(-dU,-dV,1.0);
    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.
        Eigen::Vector3f II = (light.position-point).normalized();
        Eigen::Vector3f eye = (eye_pos-point).normalized();
        Eigen::Vector3f h = (II+eye).normalized();
        double r_2 = (light.position-point).dot(light.position-point);
        Eigen::Vector3f L_d = kd.cwiseProduct(light.intensity/r_2) * std::max(0.0f,normal.dot(II));
        Eigen::Vector3f L_s = ks.cwiseProduct(light.intensity/r_2) * std::pow(std::max(0.0f,normal.dot(h)),p);
        result_color+=L_d;
        result_color+=L_s;
        Eigen::Vector3f L_a = ka.cwiseProduct(amb_light_intensity);
        result_color+=L_a;
    }
    return result_color * 255.f;
}