GAMES101-LAB3

一、作业总览

本次作业框架添加了Object Loader(用于加载三维模型), Vertex Shader 与Fragment Shader,并且支持了纹理映射。

需要完成的任务:

  1. 修改函数rasterize_triangle(const Triangle& t) in rasterizer.cpp
    • 在此处实现与作业2类似的插值算法,实现法向量、颜色、纹理颜色的插值。
  2. 修改函数get_projection_matrix() in main.cpp
    • 将你自己在之前的实验中实现的投影矩阵填到此处,此时你可以运行./Rasterizer output.png normal来观察法向量实现结果。
  3. 修改函数phong_fragment_shader() in main.cpp
    • 实现Blinn-Phong 模型计算Fragment Color.
  4. 修改函数texture_fragment_shader() in main.cpp
    • 在实现Blinn-Phong的基础上,将纹理颜色视为公式中的kd,实现Texture Shading Fragment Shader.
  5. 修改函数bump_fragment_shader() in main.cpp
    • 在实现Blinn-Phong 的基础上,仔细阅读该函数中的注释,实现Bump mapping.
  6. 修改函数displacement_fragment_shader() in main.cpp
    • 在实现Bump mapping 的基础上,实现displacement mapping.

二、参考代码

2.1 rasterize_triangle(const Triangle& t)

  • 类似作业2的插值
void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos) 
{// TODO: From your HW3, get the triangle rasterization code.auto v = t.toVector4();// TODO : Find out the bounding box of current triangle.int bounding_box_x_left = std::min(v[0].x(), std::min(v[1].x(), v[2].x()));int bounding_box_x_right = std::max(v[0].x(), std::max(v[1].x(), v[2].x()));int bounding_box_y_left = std::min(v[0].y(), std::min(v[1].y(), v[2].y()));int bounding_box_y_right = std::max(v[0].y(), std::max(v[1].y(), v[2].y()));// TODO: Inside your rasterization loop://    * v[i].w() is the vertex view space depth value z.//    * Z is interpolated view space depth for the current pixel//    * zp is depth between zNear and zFar, used for z-bufferfor(int x = bounding_box_x_left; x <= bounding_box_x_right; x++){for(int y = bounding_box_y_left; y <= bounding_box_y_right; y++){if(insideTriangle(x, y, t.v)){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;if(zp < depth_buf[get_index(x, y)]){// 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);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;//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(Eigen::Vector2i(x, y), pixel_color);}}}}
}

2.2 get_projection_matrix()

  • 投影矩阵,详细内容参考LAB1
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
{// TODO: Use the same projection matrix from the previous assignmentEigen::Matrix4f projection = Eigen::Matrix4f::Identity();// TODO: Implement this function// Create the projection matrix for the given parameters.// Then return it.Eigen::Matrix4f persp_matrix;//透视矩阵 Eigen::Matrix4f translate_matrix;//移动矩阵Eigen::Matrix4f scale_matirx;//缩放矩阵persp_matrix << zNear, 0, 0, 0,0, zNear, 0, 0,0, 0, zNear + zFar, -zNear * zFar,0, 0, 1, 0;float halfAngle = eye_fov / 2 / 180 * MY_PI;float height = -2 * std::tan(halfAngle) * zNear;//没有负号则三角形上下颠倒float width = height * aspect_ratio;translate_matrix << 1, 0, 0, 0,0, 1, 0, 0, 0, 0, 1, -(zNear + zFar) / 2,0, 0, 0, 1;scale_matirx << 2 / width, 0, 0, 0,0, 2 / height, 0, 0,0, 0, 2 / (zNear - zFar), 0,0, 0, 0, 1;projection = scale_matirx * translate_matrix * persp_matrix;return projection;
}

2.3 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){// 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 l = (light.position - point).normalized();auto v = (eye_pos - point).normalized();auto h = (l + v).normalized();//距离平方auto r_square = (light.position - point).squaredNorm();//cwiseProduct: 逐元素进行乘法auto La = ka.cwiseProduct(amb_light_intensity);auto Ld = kd.cwiseProduct(light.intensity / r_square) * MAX(0, normal.dot(l)); auto Ls = ks.cwiseProduct(light.intensity / r_square) * (pow (MAX(0, normal.dot(h)), p));result_color = La + Ld + Ls;}return result_color * 255.f;
}

2.4 texture_fragment_shader()

  • 在实现Blinn-Phong的基础上,将纹理颜色视为公式中的kd,实现Texture Shading Fragment Shader.
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 fragmentfloat u = payload.tex_coords.x();float v = payload.tex_coords.y();//获得u,v对应的纹理颜色return_color = payload.texture->getColor(u, v);}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.auto l = (light.position - point).normalized();auto v = (eye_pos - point).normalized();auto r_square = (light.position - point).squaredNorm();auto h = (l + v).normalized();auto La = ka.cwiseProduct(amb_light_intensity);auto Ld = kd.cwiseProduct(light.intensity / r_square) * MAX(0, normal.dot(l));auto Ls = ks.cwiseProduct(light.intensity / r_square) * pow( MAX(0, normal.dot(h)), p);result_color += La + Ld + Ls;}return result_color * 255.f;
}

2.5 bump_fragment_shader()

  • 在实现Blinn-Phong 的基础上,实现Bump mapping.

    • 法线贴图可以定义表面上任何不同位置的相对高度
      • 相对高度发生变化,导致法线发生变化,导致shading发生变化(出现明暗对比)
      • 逻辑上的高度改变
  • 对于二维:
    在这里插入图片描述

    • 通过凹凸贴图算切线(1, dp);
    • 求法线(-dp, 1)
  • 对于三维:
    在这里插入图片描述

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)auto x = normal.x();auto y = normal.y();auto z = normal.z();Vector3f t(x*y / sqrt(x*x+z*z), sqrt(x*x+z*z), z*y/sqrt(x*x+z*z));Vector3f b(normal.cross(t));Matrix3f TBN;TBN << t.x(), b.x(), normal.x(),t.y(), b.y(), normal.y(),t.z(), b.z(), normal.z();auto u = payload.tex_coords.x();auto v = payload.tex_coords.y();auto w = payload.texture->width;auto h = payload.texture->height;auto du = kh * kn * ( (payload.texture->getColor(u + 1.0f / w, v) - payload.texture->getColor(u, v)).norm() );auto dv = kh * kn * ( (payload.texture->getColor(u, v + 1.0 / h) - payload.texture->getColor(u, v)).norm() );Vector3f ln(-du, -dv, 1);normal = TBN * ln;Vector3f result_color = normal.normalized();return result_color * 255.f;
}

2.6 displacement_fragment_shader()

  • 在实现Bump mapping 的基础上,实现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)auto x = normal.x();auto y = normal.y();auto z = normal.z();Vector3f t(x*y / sqrt(x*x+z*z), sqrt(x*x+z*z), z*y/sqrt(x*x+z*z));Vector3f b(normal.cross(t));Matrix3f TBN;TBN << t.x(), b.x(), normal.x(),t.y(), b.y(), normal.y(),t.z(), b.z(), normal.z();auto u = payload.tex_coords.x();auto v = payload.tex_coords.y();auto w = payload.texture->width;auto h = payload.texture->height;auto du = kh * kn * ( (payload.texture->getColor(u + 1.0f / w, v) - payload.texture->getColor(u, v)).norm() );auto dv = kh * kn * ( (payload.texture->getColor(u, v + 1.0 / h) - payload.texture->getColor(u, v)).norm() );Vector3f ln{-du, -dv, 1.0f};// 目标点位置发生变化point = point + kn * normal * (payload.texture->getColor(u, v).norm());normal = TBN * ln;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.auto l = (light.position - point).normalized();auto v = (eye_pos - point).normalized();auto r_square = (light.position - point).squaredNorm();auto h = (l + v).normalized();auto La = ka.cwiseProduct(amb_light_intensity);auto Ld = kd.cwiseProduct(light.intensity / r_square) * MAX(0, normal.dot(l));auto Ls = ks.cwiseProduct(light.intensity / r_square) * pow( MAX(0, normal.dot(h)), p);result_color += La + Ld + Ls;}return result_color * 255.f;
}

三、编译

mkdir build
cd ./build
cmake …
make

texture: 使用代码中的texture shader.
使用举例: ./Rasterizer output.png texture

normal: 使用代码中的normal shader.
使用举例: ./Rasterizer output.png normal

phong: 使用代码中的blinn-phong shader.
使用举例: ./Rasterizer output.png phong

bump: 使用代码中的bump shader.
使用举例: ./Rasterizer output.png bump

displacement: 使用代码中的displacement shader.
使用举例: ./Rasterizer output.png displacement

当你修改代码之后,你需要重新make 才能看到新的结果


附件

作业3压缩包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/319476.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

金和OA jc6 ntko-upload 任意文件上传漏洞

产品简介 金和网络是专业信息化服务商&#xff0c;为城市监管部门提供了互联网监管解决方案&#xff0c;为企事业单位提供组织协同OA系统升开发平台&#xff0c;电子政务一体化平台智慧电商平合等服务 漏洞概述 金和OA jc6系统ntkoUpload接口处存在任意文件上传漏洞&#xf…

21. Mysql 事件或定时任务,解放双手,轻松实现自动化

文章目录 概念常见操作事件调度器操作查看事件创建事件删除事件启动与关闭事件 精选示例构造实时数据定时统计数据 总结参考资料 概念 Mysql 事件是一种在特定时间点自动执行的数据库操作&#xff0c;也可以称呼为定时任务&#xff0c;它可以自动执行更新数据、插入数据、删除…

软件测试技术复习点

1 术语含义&#xff08;故障、错误、失效、测试用例&#xff09; 故障&#xff08;Fault&#xff09;&#xff1a;故障是软件中的静态缺陷&#xff1b; 故障屏蔽&#xff1a;软件中的某个故障可能被其他一个或多个故障屏蔽&#xff1b; 错误&#xff08;Error&#xff09;&…

在docekr中运行openwrt镜像

1镜像下载 地址&#xff1a; https://archive.openwrt.org/releases/23.05.1/targets/x86/64/ #linux 下下载命令为 wget https://archive.openwrt.org/releases/23.05.1/targets/x86/64/openwrt-23.05.1-x86-64-rootfs.tar.gz ./#加载镜像 docker import openwrt-23.05.1-x…

基于ElementUI封装的下拉树选择可搜索单选多选清空功能

效果&#xff1a; 组件代码 /*** 树形下拉选择组件&#xff0c;下拉框展示树形结构&#xff0c;提供选择某节点功能&#xff0c;方便其他模块调用* author wy* date 2024-01-03 * 调用示例&#xff1a;* <tree-select * :height"400" // 下拉框中树形高度* …

springboot+redisTemplate多库操作

单库操作 我做了依赖管理&#xff0c;所以就不写版本号了添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>配置文件 spring:redis:database: 2…

mac环境下安装部署mysql5.7

下载安装包 进入官网下载MySQL5.7的安装包 https://www.mysql.com/downloads/ 安装包下载完成后双击pkg文件进行安装&#xff0c;无脑点下一步即可&#xff0c;注意安装完成后记得保存最后弹出框的密码 进入系统偏好设置&#xff0c;找到mysql&#xff0c;开启mysql服务…

【python入门】day12:bug及其处理思路

bug的常见类型 粗心 / 没有好习惯 思路不清 lst[{rating:[9.7,2062397],id:1292052,type:[犯罪,剧情],title:肖申克的救赎,actors:[蒂姆罗宾斯,摩根弗里曼]},{rating:[9.6,1528760],id:1291546,type:[剧情,爱情,同性],title:霸王别姬,actors:[张国荣 ,张丰毅 , 巩俐 ,葛优]},{r…

1-sql注入的概述

文章目录 SQL注入的概述web应用程序三层架构&#xff1a; 1、SQL注入之语句数据库1.1 关系型数据库1.2 非关系型数据库1.3 **数据库服务器层级关系&#xff1a;**SQL语句语法: 2、SQL注入之系统库2.1 系统库释义 SQL注入的概述 SQL注入即是指web应用程序对用户输入数据的合法性…

【算法挨揍日记】day34——647. 回文子串、5. 最长回文子串

647. 回文子串 647. 回文子串 题目描述&#xff1a; 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&am…

2024年MySQL学习指南(二),探索MySQL数据库,掌握未来数据管理趋势

文章目录 前言4. DDL- 操作数据库4.1 查询4.2 创建数据库4.3 删除数据库4.4 使用数据库 5. DDL- 操作数据表5.1 数据类型5.2 查询表5.3 创建表5.4 删除表5.5 修改表 6. 实战案例详解 前言 接上一篇文章【2024年MySQL学习指南&#xff08;一&#xff09;】 4. DDL- 操作数据库 …

探秘Spring中的BeanDefinition:每个Bean都是一个独特的“小镇居民”

theme: orange 前言介绍 在Spring框架中&#xff0c;核心思想之一就是将应用程序中的各种组件&#xff0c;例如对象、服务、数据源等&#xff0c;都抽象为Spring Bean&#xff0c;并将它们注册到Spring容器中。这种注册的方式提供了一种基于IoC&#xff08;Inversion of Cont…