0%

09 - 着色03(纹理映射)hwk

1. 源代码

1.1 phong_fragment_shader()

Blinn-Phong 模型计算 Fragment Color

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
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 light_vec = light.position - point;
auto view_vec = eye_pos - point;
auto radius2 = light_vec.dot(light_vec);
auto light_vec_norm = light_vec.normalized();
auto view_vec_norm = view_vec.normalized();

// ambient term
result_color += ka.cwiseProduct(amb_light_intensity);
// diffuse term
result_color += kd.cwiseProduct(light.intensity) / radius2
* std::max(0.0f, light_vec_norm.dot(normal));
// specular term
auto h_vec = (light_vec_norm + view_vec_norm).normalized();
result_color += ks.cwiseProduct(light.intensity) / radius2
* std::pow(std::max(0.0f, h_vec.dot(normal)), p);
}

// for debugging
// std::clog << result_color << std::endl;

return result_color * 255.f;
}

1.2 texture_fragment_shader()

将纹理颜色参数视作公式中的 kdk_d

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
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(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)
{
// 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.

// copied from function *phong_fragment_shader*
auto light_vec = light.position - point;
auto view_vec = eye_pos - point;
auto radius2 = light_vec.dot(light_vec);
auto light_vec_norm = light_vec.normalized();
auto view_vec_norm = view_vec.normalized();

// ambient term
result_color += ka.cwiseProduct(amb_light_intensity);
// diffuse term
result_color += kd.cwiseProduct(light.intensity) / radius2
* std::max(0.0f, light_vec_norm.dot(normal));
// specular term
auto h_vec = (light_vec_norm + view_vec_norm).normalized();
result_color += ks.cwiseProduct(light.intensity) / radius2
* std::pow(std::max(0.0f, h_vec.dot(normal)), p);

}

return result_color * 255.f;
}

1.3 displacement_fragment_shader()

实现 displacement mapping(位移贴图)

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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)

// copied from function *bump_fragment_shader*
// map to local coord. system
Eigen::Vector3f n = normal;
Eigen::Vector3f t;
t << n.x()*n.y()/std::sqrt(n.x()*n.x()+n.z()*n.z()),
std::sqrt(n.x()*n.x()+n.z()*n.z()),
n.z()*n.y()/std::sqrt(n.x()*n.x()+n.z()*n.z());
Eigen::Vector3f b = n.cross(t);
Eigen::Matrix3f TBN;
TBN << t, b, n;

// finite difference
float u = payload.tex_coords(0), v = payload.tex_coords(1);
float w = payload.texture->width;
float h = payload.texture->height;
// w: width of texture
float dU = kh * kn * ( payload.texture->getColor(u+1.0f/w, v).norm() - payload.texture->getColor(u, v).norm() );
// h: height of texture
float dV = kh * kn * ( payload.texture->getColor(u+1, v+1.0f/h).norm() - payload.texture->getColor(u, v).norm() );
Eigen::Vector3f ln = {-dU, -dV, 1.0f};
// displacement
point += kn * n * payload.texture->getColor(u, v).norm();
normal = (TBN * ln).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.

// copied from function *phong_fragment_shader*
auto light_vec = light.position - point;
auto view_vec = eye_pos - point;
auto radius2 = light_vec.dot(light_vec);
auto light_vec_norm = light_vec.normalized();
auto view_vec_norm = view_vec.normalized();

// ambient term
result_color += ka.cwiseProduct(amb_light_intensity);
// diffuse term
result_color += kd.cwiseProduct(light.intensity) / radius2
* std::max(0.0f, light_vec_norm.dot(normal));
// specular term
auto h_vec = (light_vec_norm + view_vec_norm).normalized();
result_color += ks.cwiseProduct(light.intensity) / radius2
* std::pow(std::max(0.0f, h_vec.dot(normal)), p);
}

return result_color * 255.f;
}

2. 结果展示

screenShot.png