前言
上篇作业2
本篇将更新作业3相关内容
作业3相关链接
games的作业3链接
我的源码
作业3简述
作业3相关知识笔记
作业3思路
注意:后面有代码展示,一定要自己先做一遍再看,而且我的设计不一定正确规范高效。
根据作业2补充上透视矩阵,这里就不再赘述了
实现rasterize_triangle()插值
void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array& view_pos)
{
// TODO: From your HW2, get the triangle rasterization code.
auto v = t.toVector4();
int x_max,x_min,y_max,y_min,index;
x_min=floor(MIN(v[0].x(),MIN(v[1].x(),v[2].x())));
x_max=ceil(MAX(v[0].x(),MAX(v[1].x(),v[2].x())));
y_min=floor(MIN(v[0].y(),MIN(v[1].y(),v[2].y())));
y_max=ceil(MAX(v[0].y(),MAX(v[1].y(),v[2].y())));
// TODO : Find out the bounding box of current triangle.
// iterate through the pixel and find if the current pixel is inside the triangle
for(int x=x_min;x<=x_max;x++){
for(int y=y_min;y<=y_max;y++){
if(insideTriangle(x+0.5f,y+0.5f,t.v)){
auto[alpha, beta, gamma] = computeBarycentric2D(x+0.5f, y+0.5f, t.v);
// 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 : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
index=get_index(x,y);
if(zp
补充 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 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};
Eigen::Vector3f v = (eye_pos - point).normalized();
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 l = (light.position - point).normalized();
Eigen::Vector3f h = (v + l).normalized();
auto r2 = (light.position - point).squaredNorm();
auto ambient = ka.cwiseProduct(amb_light_intensity);
auto diffuse = kd.cwiseProduct(light.intensity/r2 * MAX(0.0f,normal.dot(l)));
auto specular = ks.cwiseProduct(light.intensity/r2 * std::pow(MAX(0.0f,normal.dot(h)),p));
result_color += ambient + diffuse + specular;
}
return result_color * 255.f;
}
补充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
return_color = payload.texture -> getColor(payload.tex_coords.x(),payload.tex_coords.y());
//return_color = payload.texture -> getColorBilinear(payload.tex_coords.x(),payload.tex_coords.y());
}
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 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};
Eigen::Vector3f v = (eye_pos - point).normalized();
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 l = (light.position - point).normalized();
Eigen::Vector3f h = (v + l).normalized();
auto r2 = (light.position - point).squaredNorm();
auto ambient = ka.cwiseProduct(amb_light_intensity);
auto diffuse = kd.cwiseProduct(light.intensity/r2 * MAX(0.0f,normal.dot(l)));
auto specular = ks.cwiseProduct(light.intensity/r2 * std::pow(MAX(0.0f,normal.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 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)
Eigen::Vector3f n = normal;
float x = n.x();
float y = n.y();
float z = n.z();
//Vector t = (x*y/sqrt(x*x+z*z),sqrt(x*x+z*z),z*y/sqrt(x*x+z*z))
Eigen::Vector3f 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
Eigen::Vector3f b = n.cross(t);
t.normalize();
b.normalize();
//Matrix TBN = [t b n]
Eigen::Matrix3f TBN = Eigen::Matrix3f::Identity();
TBN << t.x(),b.x(),n.x(),\
t.y(),b.y(),n.y(),\
t.z(),b.z(),n.z();
//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)
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 = Eigen::Vector3f(-dU,-dV,1).normalized();
//Normal n = normalize(TBN * ln)
normal = (TBN * ln).normalized();
Eigen::Vector3f result_color = {0, 0, 0};
result_color = normal;
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 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)
Eigen::Vector3f n = normal;
float x = n.x();
float y = n.y();
float z = n.z();
// Vector t = (x*y/sqrt(x*x+z*z),sqrt(x*x+z*z),z*y/sqrt(x*x+z*z))
Eigen::Vector3f 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
Eigen::Vector3f b = n.cross(t);
t.normalize();
b.normalize();
// Matrix TBN = [t b n]
Eigen::Matrix3f TBN = Eigen::Matrix3f::Identity();
TBN << t.x(),b.x(),n.x(),\
t.y(),b.y(),n.y(),\
t.z(),b.z(),n.z();
// 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)
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 = Eigen::Vector3f(-dU,-dV,1).normalized();
// Position p = p + kn * n * h(u,v)
point += kn * n * (payload.texture -> getColor (u,v).norm());
// Normal n = normalize(TBN * ln)
normal = (TBN * ln).normalized();
Eigen::Vector3f result_color = {0, 0, 0};
Eigen::Vector3f view = (eye_pos - point).normalized();
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 l = (light.position - point).normalized();
Eigen::Vector3f h = (view + l).normalized();
auto r2 = (light.position - point).squaredNorm();
auto ambient = ka.cwiseProduct(amb_light_intensity);
auto diffuse = kd.cwiseProduct(light.intensity/r2 * MAX(0.0f,normal.dot(l)));
auto specular = ks.cwiseProduct(light.intensity/r2 * std::pow(MAX(0.0f,normal.dot(h)),p));
result_color += ambient + diffuse + specular;
}
return result_color * 255.f;
}
提高部分
换用其他模型,更改main.cpp中obj_path和对应obj文件、texture文件即可
双线性插值
Eigen::Vector3f getColorBilinear(float u,float v)
{
if(u<0)u=0;
if(u>1)u=1;
if(v<0)v=0;
if(v>1)v=1;
auto u_img = u * (width - 1);
auto v_img = (1 - v) * (height - 1);
/*
Eigen::Vector2f u00(std::floor(u_img), std::floor(v_img));
Eigen::Vector2f u10(std::ceil(u_img), std::floor(v_img));
Eigen::Vector2f u00(std::floor(u_img), std::ceil(v_img));
Eigen::Vector2f u00(std::ceil(u_img), std::ceil(v_img));
*/
auto color00 = getColor((std::floor(u_img))/width,1-(std::floor(v_img))/height);
auto color10 = getColor((std::ceil(u_img))/width, 1-(std::floor(v_img))/height);
auto color01 = getColor((std::floor(u_img))/width,1-(std::ceil(v_img))/height);
auto color11 = getColor((std::ceil(u_img))/width, 1-(std::ceil(v_img))/height);
float s = u_img - std::floor(u_img);
float t = v_img - std::floor(v_img);
auto color0 = lerp(s,color00,color10);
auto color1 = lerp(s,color10,color11);
auto color = lerp(s,color0,color1);
return Eigen::Vector3f(color[0], color[1], color[2]);
}
Eigen::Vector3f lerp(float coefficient,Eigen::Vector3f color_a,Eigen::Vector3f color_b)
{
return (1-coefficient) * color_a + coefficient * color_b;
}