虚拟机代码
本文参考的文章链接:
重心坐标插值推导
代码参考
理论

规范纹理坐标
Texture.hpp中的getColor()
规范纹理的坐标到[0,1]之间, 这一步不做,在虚拟机中运行到bump计算dV的时候会出现错误,以防万一,改下保险。

Eigen::Vector3f getColor(float u, float v){if(u>1) u = 1;if(u<0) u=0;if(v>1) v=1;if(v<0) v=0;auto u_img = u * width;auto v_img = (1 - v) * height;auto color = image_data.at<cv::Vec3b>(v_img, u_img);return Eigen::Vector3f(color[0], color[1], color[2]);}

心坐标插值法
根据重心坐标插值法得到插值的颜色,纹理坐标,法线,物体坐标,深度
公式推导可看找个链接
rasterize_triangle()

void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos)
{// transform matrixauto v = t.toVector4();// bounding boxfloat minx = std::min({v[0][0], v[1][0], v[2][0]});float miny = std::min({v[0][1], v[1][1], v[2][1]});float maxx = std::max({v[0][0], v[1][0], v[2][0]});float maxy = std::max({v[0][1], v[1][1], v[2][1]});// Interateminx = std::floor(minx);miny = std::floor(miny);maxx = std::ceil(maxx);maxy = std::ceil(maxy);for (int x = minx; x <= maxx;x++) {for (int y = miny; y <= maxy;y++) {if (insideTriangle((float) x + 0.5, (float) y + 0.5, t.v)) {//    * 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-bufferauto tp = computeBarycentric2D((float)x + 0.5, (float)y + 0.5, t.v);float alpha ,beta, gamma;std::tie(alpha, beta, gamma) = tp;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;// Use: fragment_shader_payload payload( interpolated_color, interpolated_normal.normalized(), interpolated_texcoords, texture ? &*texture : nullptr);// Use: 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;// Use: auto pixel_color = fragment_shader(payload);if (zp<depth_buf[get_index(x, y)]) {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 );auto interpolated_texcoords = interpolate(alpha,beta,gamma,t.tex_coords[0],t.tex_coords[1],t.tex_coords[2], 1.0);// obeject coordinateauto 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.normalized(), interpolated_texcoords, texture ? &*texture : nullptr);payload.view_pos = interpolated_shadingcoords;auto pixel_color = fragment_shader(payload);depth_buf[get_index(x,y)] = zp;// using coordinate from originalset_pixel(Eigen::Vector2i(x, y), pixel_color);}}}}// TODO: From your HW3, get the triangle rasterization code.// 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-buffer// 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;// TODO: Interpolate the attributes:// auto interpolated_color// auto interpolated_normal// auto interpolated_texcoords// auto interpolated_shadingcoords// Use: fragment_shader_payload payload( interpolated_color, interpolated_normal.normalized(), interpolated_texcoords, texture ? &*texture : nullptr);// Use: 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;// Use: auto pixel_color = fragment_shader(payload);}

phong光照模型
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.// ambientEigen::Vector3f ambient = ka.cwiseProduct(amb_light_intensity);// diffuse// lightdirEigen::Vector3f lightdir = light.position - point;float r2 = lightdir.dot(lightdir);Eigen::Vector3f diffuse = kd.cwiseProduct(light.intensity/r2);diffuse *= std::max(0.0f, lightdir.normalized().dot(normal.normalized()));// specularEigen::Vector3f eyedir = eye_pos - point;Eigen::Vector3f specular = ks.cwiseProduct(light.intensity/r2);specular *= std::pow(std::max(0.0f, normal.normalized().dot((eyedir + lightdir).normalized())), p);result_color += ambient + diffuse  + specular;}return result_color * 255.f;
}

纹理贴图
就是将kd用纹理颜色代替,而不是一个单调的RGB色,说白了就是将 一张“布”铺在一个物体的表面
texture_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 fragment// get texCoordinate color 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){// get  lightdirEigen::Vector3f lightdir = light.position - point;// get viewdirEigen::Vector3f viewdir = eye_pos - point;// get decay/corrode parametersfloat r2 = lightdir.dot(lightdir);// ambientEigen::Vector3f ambient = ka.cwiseProduct(amb_light_intensity);// diffuseEigen::Vector3f diffuse = kd.cwiseProduct(light.intensity/r2);diffuse *= std::max(0.0f, lightdir.normalized().dot(normal.normalized()));// specularEigen::Vector3f h = lightdir + viewdir;Eigen::Vector3f specular = ks.cwiseProduct(light.intensity/r2);specular*= std::pow(std::max(0.0f, h.normalized().dot(normal.normalized())),p);result_color += ambient + specular + diffuse;         }return result_color * 255.f;
}

模型法线展示
normal_fragment_shader()

Eigen::Vector3f normal_fragment_shader(const fragment_shader_payload& payload)
{Eigen::Vector3f return_color = (payload.normal.head<3>().normalized() + Eigen::Vector3f(1.0f, 1.0f, 1.0f)) / 2.f;Eigen::Vector3f result;result << return_color.x() * 255, return_color.y() * 255, return_color.z() * 255;return result;
}

法线贴图(凹凸贴图)
这里用颜色来显示出被扰动的法线,可以和normal_fragment_shader的结果做对比,normal_fragment_shader的法线就是一个三角形碎片使用一个方向的法线
单独说下里面的参数含义:
1,kh kn :x方向和y方向梯度的一个权重因子
2,du, dv :TBN空间中法线的 x y , (-du,dv,1.0)组成TBN空间中的法线。
3,TBN:从切线空间变换到世界空间
4,TODO里面已经给出了公式,具体咋推导不太清楚

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).normalized();// 归一化Eigen::Vector3f result_color = normal;return result_color * 255.f;}

法线贴图 + phong光照模型
就是将上面可视化出来的法线贴图的法线分布图 和光照模型一起运用起来,也可以添加纹理的操作
displacement_fragment_shader()

Eigen::Vector3f displacement_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// get texCoordinate color 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);*/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 };// Position p = p + kn * n * h(u,v)normal = (TBN * ln).normalized();point += kn * normal * payload.texture->getColor(u, v).norm();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 ambient = ka.cwiseProduct(amb_light_intensity);// diffuse// lightdirEigen::Vector3f lightdir = light.position - point;float r2 = lightdir.dot(lightdir);Eigen::Vector3f diffuse = kd.cwiseProduct(light.intensity/r2);diffuse *= std::max(0.0f, lightdir.normalized().dot(normal.normalized()));// specularEigen::Vector3f eyedir = eye_pos - point;Eigen::Vector3f specular = ks.cwiseProduct(light.intensity/r2);specular *= std::pow(std::max(0.0f, normal.normalized().dot((eyedir + lightdir).normalized())), p);result_color += ambient + diffuse  + specular;}return result_color * 255.f;
}


和纹理一起用

双线性插值
步骤
1,找到某个点周围的4个点
2,对四个点进行水平的两次插值,
3,对水平插值出来的两个点进行垂直方向的插值

图解:


在Texture类中添加 getColorBilinear()方法,其写法就是参照上面的公式

 Eigen::Vector3f getColorBilinear(float u, float v){if(u>1) u = 1;if(u<0) u=0;if(v>1) v=1;if(v<0) v=0;float u_img = u * width;float v_img = (1 - v) * height;float u_min = std::floor(u_img);float v_min = std::floor(v_img);float u_max = std::ceil(u_img);float v_max = std::ceil(v_img);auto U01 = image_data.at<cv::Vec3b>(u_min,v_min);auto U11 = image_data.at<cv::Vec3b>(u_max,v_min);auto U00 = image_data.at<cv::Vec3b>(u_min,v_max);auto U10 = image_data.at<cv::Vec3b>(u_max,v_max);float h = (u_img -u_min)/(u_max-u_min);float ve = (v_img-v_min)/(v_max-v_min);auto bottom = U00 + h * (U10 - U00);auto top = U01 + h * (U11 - U01);auto Vertical = bottom + ve *(top-bottom);return Eigen::Vector3f(Vertical[0], Vertical[1], Vertical[2]);}

效果图:
使用的是100 x 100的纹理图像

纹理图像(100 X100)

game101作业3相关推荐

  1. LeetCode简单题之在既定时间做作业的学生人数

    题目 给你两个整数数组 startTime(开始时间)和 endTime(结束时间),并指定一个整数 queryTime 作为查询时间. 已知,第 i 名学生在 startTime[i] 时开始写作业 ...

  2. 作业函数的定义与调用

    作业函数的定义与调用 在 OneFlow 中,将训练.预测任务封装在一个函数中,统称为作业函数(job function),作业函数联系用户的业务逻辑与 OneFlow 管理的计算资源. 在 OneF ...

  3. 华东理工大学计算机应用基础,最新华东理工大学计算机应用基础网上作业及全部答案...

    精品文档 华东理工大学计算机应用基础网上作业及全部答案 2012计算机应用基础答案: 一.选择题 1.文件夹是用来对应用程序.文件进行分组的,以下说法中()正确.答:一个文件夹内可以包含文件.应用程序 ...

  4. 《小团团团队》第五次作业:项目需求分析改进与系统设计

    项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 实验九 团队作业5-团队项目需求改进与系统设计 团队名称 小团团团队 作业学习目标 (1)掌握面向对象需求分析方法:(2) ...

  5. 2017级面向对象程序设计 作业三

    Deadline:2018-05-13 22:00pm 题目升级 一栋10层的大楼(楼层编号1-10),设3台无限载重的电梯,初始时电梯停在1层.其中:1号电梯只能停留在奇数层,2号电梯可以各层都停留 ...

  6. 201621123068 作业08-集合

    1. 本周学习总结 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的<contains>源代码 答:源代码 public boolean contains ...

  7. 代码管理和版本管理的作业流程以及规范是怎样的?

    代码管理和版本管理的作业流程以及规范是怎样的? 代码管理和版本管理的作业流程以及规范是怎样的?下面以文档的形式进行详细分析,希望能够给予测试人员一些帮助和指导. 本文目的 本文试图提供一套有效进行代码 ...

  8. 结队项目——第一次作业

    By: 031502220 计算机二班 李自强031502344 计算机三班 郑世强 Table of Contents 一 需求分析:二 具体设计:三 系统功能说明:四 产品优劣势分析:五 PSP: ...

  9. 第三次作业+105032014085

    对修正后第2次作业+105032014141的单元测试 1.修正后的流程图 2.测试用例设计 3.单元测试框架 1 import static org.junit.Assert.*; 2 3 impo ...

最新文章

  1. java获取注解的属性值_反射+自定义注解,实现获取注解标记的属性
  2. ffmpeg avformat_open_input always returns “Protocol not found”
  3. @Singleton能保证单例吗
  4. 了解万用表历史,万用表的前世今生
  5. QT解析 JSON 格式的数据
  6. 产品运营实战系列-产品设计从0到1全流程:以优惠券为例
  7. PL/SQL Developer SQL Window中不能插入多条数据
  8. LinkedList线程安全问题
  9. 大数据分析平台有哪些主要功能
  10. Android kernel源码下载与编译
  11. mysql 事务补偿_分布式事务之消息补偿解决方案
  12. 一款Mac平台上自带广告拦截功能插件的浏览器软件
  13. 企业微信api接口,企业微信sdk
  14. 中专生计算机职业素养论文,中职学生的职业素养
  15. 经纬度坐标转换xy坐标 python_Python 高斯坐标转经纬度算法
  16. 做LeetCode题的感悟 (1-10题)
  17. 计算机密码学论文,密码学论文写作范例论文
  18. crm系统如何处理好客户投诉问题?
  19. 路由器的配置,IP,NAT、DHCP
  20. Praat脚本-010 | 提取时长和共振峰

热门文章

  1. 四阶幻方c语言编程,C语言四阶完美幻方.doc
  2. 区块链领域的48个名词,你知道几个?
  3. 电脑内存条是ram的还是rom 的,还是两者都有?
  4. 【IC萌新虚拟项目】ppu整体uvm验证环境搭建
  5. 【imessage苹果家庭推送群发】messageview前置的类型转换因变量
  6. 自己动手开发更好用的markdown编辑器-06(自动更新)
  7. 评论:从裁员事件看百度的人性与命运
  8. 弱校计算机网络试卷(2012-2013)
  9. 做个小本生意怎么赚钱
  10. 详述 MIMIC护理人员信息表(十五)