Phong shader + Texture

Blinn-Phong:Shading

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Eigen::Vector3f texture_fragment_shader(const fragment_shader_payload& payload)
{
Eigen::Vector3f return_color = { 0, 0, 0 };
if (payload.texture)
{
return_color = payload.texture->getColor(payload.tex_coords.x(), payload.tex_coords.y());

}
Eigen::Vector3f texture_color;
texture_color << return_color.x(), return_color.y(), return_color.z();

//三种光的颜色 [0-1]之间
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);

// light: position intensity
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 };

//games101-3 Shading
for (auto& light : lights)
{
//点O到光源L的方向OL
Vector3f lightDir = (light.position - point).normalized();
//点O到视点V的方向OV
Vector3f viewDir = (eye_pos - point).normalized();
//可以用反射函数计算反射光线
//Vector3f reflectDir = reflect(-lightDir, normal);
//OL和OV的中间方向OH 用OH和该点法线ON计算镜面光
Vector3f halfDir = (lightDir + viewDir).normalized();

//计算OL长度
float r = (light.position - point).norm();
//光强度衰减系数
float attenuation = 1.0 / (r * r);
Vector3f ambient = ka.cwiseProduct(amb_light_intensity);
Vector3f diffuse = kd.cwiseProduct(light.intensity) * std::max(0.0f, normal.dot(lightDir));
//Vector3f specular = ks.cwiseProduct(light.intensity) * std::pow(std::max(0.0f, reflectDir.dot(viewDir)), p);
Vector3f specular = ks.cwiseProduct(light.intensity) * std::pow(std::max(0.0f, normal.dot(halfDir)), p);
result_color += attenuation * (ambient + diffuse + specular);
}

return result_color * 255.f;
}

Bump shader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Eigen::Vector3f bump_fragment_shader(const fragment_shader_payload& payload)
{
// 初始化 与phongshader一样

float kh = 0.2, kn = 0.1;
Vector3f n = normal;
Vector3f t = Vector3f(n.x() * n.y() / sqrt(n.x() * n.x() + n.z() * n.z()), sqrt(n.x() * n.x() + n.z() * n.z()), n.z() * n.y() / sqrt(n.x() * n.x() + n.z() * n.z()));
Vector3f b = n.cross(t);
Matrix3f TBN;
TBN << t, b, n;
//求u、v上的导数
float dU = kh * kn * (payload.texture->getColor(payload.tex_coords.x() + 1.0f / payload.texture->width, payload.tex_coords.y()).norm() - payload.texture->getColor(payload.tex_coords.x(), payload.tex_coords.y()).norm());
float dV = kh * kn * (payload.texture->getColor(payload.tex_coords.x(), payload.tex_coords.y() + 1.0f / payload.texture->height).norm() - payload.texture->getColor(payload.tex_coords.x(), payload.tex_coords.y()).norm());
//转成法线
Vector3f ln = Vector3f(-dU, -dV, 1);
normal = (TBN * ln).normalized();

Eigen::Vector3f result_color = { 0, 0, 0 };
result_color = normal;

return result_color * 255.f;
}

Displacement shader

1
2
3
4
5
6
7
8
9
10
11
Eigen::Vector3f displacement_fragment_shader(const fragment_shader_payload& payload)
{
// 与bumpshader一样
// 不同之处 新增point运算
point = point + kn * normal * payload.texture->getColor(payload.tex_coords.x(), payload.tex_coords.y()).norm();
normal = (TBN * ln).normalized();

for (auto& light : lights)
// 与phongshader一样
return result_color * 255.f;
}

rasteriza_triangle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos) 
{
auto v = t.toVector4();
//BVH
int x_min = std::min({ v[0].x(), v[1].x(), v[2].x() });
int x_max = std::max({ v[0].x(), v[1].x(), v[2].x() });
int y_min = std::min({ v[0].y(), v[1].y(), v[2].y() });
int y_max = std::max({ v[0].y(), v[1].y(), v[2].y() });

for (int x = x_min; x <= x_max; x++) {
for (int y = y_min; y <= y_max; y++) {
//判断点是否在三角形内
if (insideTriangle(x, y, t.v)) {
//计算重心坐标 games101-3 Interpolation Across Triangles
auto [alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
//在三角形内 与上方insideTriangle函数重复
if (alpha >= 0 && beta >= 0 && gamma >= 0) {
//计算深度插值 目前不理解
float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
z_interpolated *= w_reciprocal;

int index = get_index(x, y);
//games101-2 Z-Buffering
if (z_interpolated < depth_buf[index]) {
depth_buf[index] = z_interpolated;
Eigen::Vector2i point(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);
//根据mv变换得到的view space坐标 根据这个计算在视角中看到的这个点的坐标
auto interpolated_shadingcoords = interpolate(alpha, beta, gamma, view_pos[0], view_pos[1], view_pos[2], 1.0);

// r的属性
// fragment_shader
// 最后一个参数是texture指针 不可用传递nullptr
fragment_shader_payload payload(interpolated_color, interpolated_normal.normalized(), interpolated_texcoords, texture ? &*texture : nullptr);
// fragment_shader_payload 定义在shader.hpp中
// payload的属性
// Eigen::Vector3f view_pos; 坐标
// Eigen::Vector3f color; 颜色
// Eigen::Vector3f normal; 法线
// Eigen::Vector2f tex_coords; 贴图坐标
// Texture* texture; 贴图指针
payload.view_pos = interpolated_shadingcoords;
// std::function<Eigen::Vector3f(fragment_shader_payload)> fragment_shader;
//fragment_shader在main函数里赋值 是本次编写的几个shader函数之一 payload是参数
auto pixel_color = fragment_shader(payload);
set_pixel(point, pixel_color);
}
}
}
}
}
}

getColorBilinear

双线性插值:Shading

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Eigen::Vector3f Texture::getColorBilinear(float u, float v)
{
// 防止数组越界
u = adjust_by_range(u, 0, 1.0f);
v = adjust_by_range(v, 0, 1.0f);

// height和width都-1是指数组从0开始
float u_img = u * (width - 1);
float v_img = (1 - v) * (height - 1);

//上下取整
float u_min = std::floor(u_img);
float u_max = std::ceil(u_img);
float v_min = std::floor(v_img);
float v_max = std::ceil(v_img);

// auto color = image_data.at<cv::Vec3b>(v_img, u_img);
auto u00 = image_data.at<cv::Vec3b>(v_min, u_min);
auto u10 = image_data.at<cv::Vec3b>(v_min, u_max);
auto u01 = image_data.at<cv::Vec3b>(v_max, u_min);
auto u11 = image_data.at<cv::Vec3b>(v_max, u_max);

float s = (u_img - u_min) / (u_max - u_min);
float t = (v_img - v_min) / (v_max - v_min);

auto u0 = lerp(s, u00, u10);
auto u1 = lerp(s, u01, u11);

auto result = lerp(t, u0, u1);

return Eigen::Vector3f(result[0], result[1], result[2]);
};
1
2
3
4
cv::Vec3b lerp(float x, cv::Vec3b v0, cv::Vec3b v1)
{
return v0 + x * (v1 - v0);
};

结果

normal shader phong shader
texture shader bump shader
displacement shader
getColorBilinear getColor