Games101作业3:重心插值、着色模型

Assignment3

前置知识

Blinn-Phong

一种局部着色模型(不会生成阴影,因为不涉及多物体)

光源方向I和视角方向v均是从片元出发(指向光源或摄像机)

diffuse(漫反射):与视角无关,只与接受到的光的总量有关
L d = k d ( I / r 2 ) m a x ( 0 , n ∗ I ) L_d=k_d(I/r^2)max(0,n*I) Ld=kd(I/r2)max(0,nI)
specular(高光):与视角有关,用光源和视角的半角和法向量作比较
L s = k s ( I / r 2 ) m a x ( 0 , n ∗ h ) p L_s=k_s(I/r^2)max(0,n*h)^p Ls=ks(I/r2)max(0,nh)p
ambient(环境光):直接系数 * 颜色

Graphics Pipeline(实时渲染管线)

顶点阶段(Vertex Processing、Triangle Processing)

输入顶点信息(坐标)【MVP变换】,将坐标变换为顶点,再根据顶点间的对应关系将顶点连成三角形【屏幕空间】

->

光栅化(Rasterization)

将三角形离散成像素【三角形采样】,并用深度测试剔除某些像素

->

着色阶段(Fragment Processing、Framebuffer Operations)

根据不同着色方法决定像素的颜色【Shading】,最后输出

重心坐标插值(从顶点向像素)

重心坐标:三角形平面上的点都能用三个顶点的线性组合表示(三个系数之和为1);若点在三角形内,则需满足三个系数都是非负数

如何求三个系数:假设点在三角形内,将该点和三个点连起来,各个点的系数 = 对面的小三角形(不以自己做顶点的)/ 总三角形面积

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1erBSM8M-1645590206704)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\image-20220222195539800.png)]

求得系数之后,目标插值属性可直接用系数乘以三个点的对应属性得到

投影过后的重心坐标会变,所以在深度插值时应该用三维坐标插值(先将屏幕坐标投影回三维坐标),作业不要求

Texture(纹理)

纹理坐标uv反映了顶点坐标和纹理贴图之间的对应关系,将一张纹理图上的颜色着色到模型上(作为漫反射系数kd)

code

void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos)
{
	...
     if (insideTriangle(x + 0.5f, y + 0.5f, t.v))
     {
         ...
         if(z_interpolated < z_depth)
         {
             z_depth = z_interpolated;
			// TODO: Interpolate the attributes:
			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;
				//  Use: Instead of passing the triangle's color directly to the frame buffer, pass the color to the shaders first to get the final color;
				auto pixel_color = fragment_shader(payload);
				set_pixel(Vector2i(x, y), pixel_color);  //  这里参数变了
         }
     }
}

Eigen::Vector3f phong_fragment_shader(const fragment_shader_payload& payload)
{
    ...
    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.
        Vector3f ambient = ka * amb_light_intensity;

        Vector3f lightDir = light.position - point;
        Vector3f lightEnergy = light.intensity / std::sqrt(lightDir.dot(lightDir));

        Vector3f viewDir = eye_pos - point;
        Vector3f diffuse = kd * lightEnergy * std::max(.0f, normal.dot(lightDir));
    
        Vector3f halfDir = (viewDir + lightDir).normalized();
        Vector3f specular = ks * lightEnergy * std::pow(std::max(.0f, normal.dot(halfDir)), p);
        result_color += (ambient + diffuse + specular);
    }
    ...
}

//	displacement_fragment_shader和bump_fragment_shader直接照着伪代码改就行,就不放上来了

注意事项

纹理的放大和缩小

放大会使纹理出现锯齿,可用抗锯齿手段或各种线性插值解决

缩小会更复杂,可用mipmap等解决(和作业联系不大,不展开了)

在之前项目中使用过的函数的参数发生变化

set_pixel()第一个参数从Vector3f变成Vector2f

OpenCV(4.5.1) Error: Assertion failed (!_src.empty()) in cv::cvtColor

是main()中读取模型和贴图路径的问题

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值