games101 作业三

注意下面几张PPT:(bump mapping和displacement mapping都是按照注释来弄的,我也没整明白

Blinn-phong模型:

重心坐标插值:

bump mapping:

displacement mapping:

rasterize_triangle:

static bool mySymbol(float x){
    return x > 0;
}

static bool insideTriangle(int x, int y, const Vector3f* _v)
{   
    auto A = _v[0];
    auto B = _v[1];
    auto C = _v[2];
    auto P = Vector2f(x,y);

    auto PA = Vector2f(A[0]-P[0],A[1]-P[1]);
    auto PB = Vector2f(B[0]-P[0],B[1]-P[1]);
    auto PC = Vector2f(C[0]-P[0],C[1]-P[1]);
    
    auto PA_PB = PA[0]*PB[1]-PA[1]*PB[0];
    auto PB_PC = PB[0]*PC[1]-PB[1]*PC[0];
    auto PC_PA = PC[0]*PA[1]-PC[1]*PA[0];

    return mySymbol(PA_PB) == mySymbol(PB_PC) == mySymbol(PC_PA);
    
}

//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos) 
{
    auto v = t.toVector4();
    
    // 找bounding box
    int left=INT32_MAX,right=INT32_MIN,top=INT32_MIN,buttom=INT32_MAX;

    for (int i = 0; i < 3; i++)
    {
        float x = t.v[i][0];
        float y = t.v[i][1];
        
        left = left > floor(x) ? floor(x):left;
        right = right < ceil(x) ? ceil(x):right;

        buttom = buttom > floor(y) ? floor(y):buttom;
        top = top < ceil(y) ? ceil(y):top;
        
    }
    
    for (int x = left; x <= right; x++)
    {
        for (int y = buttom; y <= top; y++)
        {
            bool isInside = insideTriangle(x+0.5,y+0.5,t.v);
            if(isInside){
                auto[alpha, beta, gamma] = computeBarycentric2D(x, y, 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;

                bool shouldBePainted = depth_buf[get_index(x,y) ] >  zp;
                if(shouldBePainted){
                    // 更新 z_buffer
                    depth_buf[get_index(x,y) ] =  zp;
                    
                    // 插值
                    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.normalized(), interpolated_texcoords, texture ? &*texture : nullptr);
                    
                    payload.view_pos = interpolated_shadingcoords;
   
                    auto pixel_color = fragment_shader(payload);

                    set_pixel(Eigen::Vector2i(x, y), pixel_color);
                }
                
            }
        }
        
    }
 
}

get_projection_matrix:

Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
{
    Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();

    float n = zNear;
	float f = zFar;
    
    eye_fov = eye_fov * MY_PI / 180.0;
	float t = tan(eye_fov/2) * -abs(n);
    float b = -t;

	float r = aspect_ratio * t;
    float l = -r;

    Eigen::Matrix4f M_ortho_1,M_ortho_2,M_ortho;
	M_ortho_2 << 	2/(r-l), 0.0, 0.0, 0.0,
					0.0, 2/(t-b), 0.0, 0.0,
					0.0, 0.0, 2/(n-f), 0.0,
					0.0, 0.0, 0.0, 		1.0;

	M_ortho_1 << 	1.0, 0.0, 0.0, -(r+l)/2,
					0.0, 1.0, 0.0, -(t+b)/2,
					0.0, 0.0, 1.0, -(n+f)/2,
					0.0, 0.0, 0.0, 1.0;
	M_ortho = M_ortho_2 * M_ortho_1;

	Eigen::Matrix4f M_persp_ortho;
	M_persp_ortho << n, 0.0, 0.0, 0.0,
					0.0, n, 0.0, 0.0,
					0.0, 0.0, n+f, -n*f,
					0.0, 0.0, 1.0, 0.0;
	M_ortho = M_ortho_2 * M_ortho_1;

    projection = M_ortho * M_persp_ortho * projection;

    return projection;

}

phong_fragment_shader:

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)
    {
        Eigen::Vector3f light_dir = light.position - point;
        Eigen::Vector3f view_dir = eye_pos - point;
		// 衰减因子
		float r2 = light_dir.dot(light_dir);

        auto ambient = ka.cwiseProduct(amb_light_intensity);
        auto diffuse = kd.cwiseProduct((light.intensity / r2) * max(0.0f,normal.normalized().dot(light_dir.normalized())));

        Eigen::Vector3f h = (light_dir + view_dir).normalized();
        auto specular = ks.cwiseProduct(light.intensity / r2 * pow(max(0.0f,normal.normalized().dot(h)),p));
        
        result_color += ambient + diffuse + specular;
    }

    return result_color * 255.f;
}

displacement_fragment_shader:

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)


	float x = normal.x();
	float y = normal.y();
	float z = normal.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) };
	Eigen::Vector3f b = normal.cross(t);
	Eigen::Matrix3f TBN;
	TBN << t.x(), b.x(), normal.x(),
		t.y(), b.y(), normal.y(),
		t.z(), b.z(), normal.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.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());

	Eigen::Vector3f ln{ -dU,-dV,1.0f };

    point += (kn * normal * payload.texture->getColor(u , v).norm());
	normal = TBN * ln;
    normal = normal.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 light_dir = light.position - point;
        Eigen::Vector3f view_dir = eye_pos - point;
		// 衰减因子
		float r2 = light_dir.dot(light_dir);

        auto ambient = ka.cwiseProduct(amb_light_intensity);
        auto diffuse = kd.cwiseProduct((light.intensity / r2) * max(0.0f,normal.normalized().dot(light_dir.normalized())));

        Eigen::Vector3f h = (light_dir + view_dir).normalized();
        auto specular = ks.cwiseProduct(light.intensity / r2 * pow(max(0.0f,normal.normalized().dot(h)),p));
        
        result_color += ambient + diffuse + specular;
    }

    return result_color * 255.f;
}

bump_fragment_shader:

Eigen::Vector3f bump_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 bump 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)
    // Normal n = normalize(TBN * ln)

    float x = normal.x();
	float y = normal.y();
	float z = normal.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) };
	Eigen::Vector3f b = normal.cross(t);
	Eigen::Matrix3f TBN;
	TBN << t.x(), b.x(), normal.x(),
		t.y(), b.y(), normal.y(),
		t.z(), b.z(), normal.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.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());

	Eigen::Vector3f ln{ -dU,-dV,1.0f };

	normal = TBN * ln;
	// 归一化
	Eigen::Vector3f result_color = normal.normalized();
    return result_color * 255.f;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值