Skip to content

Commit 1c0c544

Browse files
author
root
committed
complete hw3
1 parent 0d2db14 commit 1c0c544

File tree

3 files changed

+146
-41
lines changed

3 files changed

+146
-41
lines changed

Assignment3/codes/Texture.hpp

+17
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,23 @@ class Texture{
2929
auto color = image_data.at<cv::Vec3b>(v_img, u_img);
3030
return Eigen::Vector3f(color[0], color[1], color[2]);
3131
}
32+
33+
Eigen::Vector3f getColorBilinear(float u, float v){
34+
float w1 = int(u * width), h1 = int(v * height);
35+
float w2 = w1 + 1, h2 = h1;
36+
float w3 = w1, h3 = h1 + 1;
37+
float w4 = w1 + 1, h4 = h1 + 1;
38+
39+
Eigen::Vector3f color1, color2, color3, color4, color5, color6, color;
40+
color1 = getColor(w1 / width, h1 / height);
41+
color2 = getColor(w2 / width, h2 / height);
42+
color3 = getColor(w3 / width, h3 / height);
43+
color4 = getColor(w4 / width, h4 / height);
44+
color5 = color1 + (color2 - color1) * (u * width - w1);
45+
color6 = color3 + (color4 - color3) * (u * width - w1);
46+
color = color5 + (color6 - color5) * (v * height - h1);
47+
return color;
48+
}
3249

3350
};
3451
#endif //RASTERIZER_TEXTURE_H

Assignment3/codes/main.cpp

+90-20
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,26 @@ Eigen::Matrix4f get_model_matrix(float angle)
4747
return translate * rotation * scale;
4848
}
4949

50-
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
50+
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
51+
float zNear, float zFar)
5152
{
52-
// TODO: Use the same projection matrix from the previous assignments
5353

54+
Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
55+
56+
float fov_angle = eye_fov * M_PI / 180;
57+
58+
float n = -zNear;
59+
float t = tan(fov_angle / 2) * zNear;
60+
float b = -t;
61+
float r = t * aspect_ratio;
62+
float l = -r;
63+
float f = -zFar;
64+
65+
projection << 2 * n /(r - l), 0, (l + r)/(l - r) , 0,
66+
0, 2 * n /(t-b), (b + r)/(b - t), 0,
67+
0, 0, (f + n)/(n - f), 2 * f * n / (f-n),
68+
0, 0 ,1, 0;
69+
return projection;
5470
}
5571

5672
Eigen::Vector3f vertex_shader(const vertex_shader_payload& payload)
@@ -84,6 +100,7 @@ Eigen::Vector3f texture_fragment_shader(const fragment_shader_payload& payload)
84100
if (payload.texture)
85101
{
86102
// TODO: Get the texture value at the texture coordinates of the current fragment
103+
return_color = payload.texture->getColor(payload.tex_coords.x(), payload.tex_coords.y());
87104

88105
}
89106
Eigen::Vector3f texture_color;
@@ -102,7 +119,6 @@ Eigen::Vector3f texture_fragment_shader(const fragment_shader_payload& payload)
102119

103120
float p = 150;
104121

105-
Eigen::Vector3f color = texture_color;
106122
Eigen::Vector3f point = payload.view_pos;
107123
Eigen::Vector3f normal = payload.normal;
108124

@@ -113,6 +129,13 @@ Eigen::Vector3f texture_fragment_shader(const fragment_shader_payload& payload)
113129
// TODO: For each light source in the code, calculate what the *ambient*, *diffuse*, and *specular*
114130
// components are. Then, accumulate that result on the *result_color* object.
115131

132+
Eigen::Vector3f l = light.position - point;
133+
Eigen::Vector3f v = eye_pos - point;
134+
Eigen::Vector3f h = (l.normalized() + v.normalized()).normalized();
135+
Vector3f diffuse = kd.cwiseProduct(light.intensity / (l.dot(l)) * std::max(0.0f, (normal.normalized().dot(l.normalized()))));
136+
Vector3f specular = ks.cwiseProduct(light.intensity / (l.dot(l)) * pow(std::max(0.0f, normal.normalized().dot(h)), p));
137+
Vector3f ambient = ka.cwiseProduct(amb_light_intensity);
138+
result_color += diffuse + specular + ambient;
116139
}
117140

118141
return result_color * 255.f;
@@ -133,25 +156,31 @@ Eigen::Vector3f phong_fragment_shader(const fragment_shader_payload& payload)
133156

134157
float p = 150;
135158

136-
Eigen::Vector3f color = payload.color;
137159
Eigen::Vector3f point = payload.view_pos;
138160
Eigen::Vector3f normal = payload.normal;
139161

140162
Eigen::Vector3f result_color = {0, 0, 0};
163+
141164
for (auto& light : lights)
142165
{
143166
// TODO: For each light source in the code, calculate what the *ambient*, *diffuse*, and *specular*
144167
// components are. Then, accumulate that result on the *result_color* object.
145168

169+
Eigen::Vector3f l = light.position - point;
170+
Eigen::Vector3f v = eye_pos - point;
171+
Eigen::Vector3f h = (l.normalized() + v.normalized()).normalized();
172+
Vector3f ambient = ka.cwiseProduct(amb_light_intensity);
173+
Vector3f diffuse = kd.cwiseProduct(light.intensity / (l.dot(l)) * std::max(0.0f, (normal.dot(l.normalized()))));
174+
Vector3f specular = ks.cwiseProduct(light.intensity / (l.dot(l)) * pow(std::max(0.0f, normal.dot(h)), p));
175+
result_color += ambient + diffuse + specular;
146176
}
147177

148178
return result_color * 255.f;
149179
}
150180

151181

152-
153-
Eigen::Vector3f displacement_fragment_shader(const fragment_shader_payload& payload)
154-
{
182+
Eigen::Vector3f displacement_fragment_shader(const fragment_shader_payload& payload)
183+
{
155184

156185
Eigen::Vector3f ka = Eigen::Vector3f(0.005, 0.005, 0.005);
157186
Eigen::Vector3f kd = payload.color;
@@ -171,17 +200,29 @@ Eigen::Vector3f displacement_fragment_shader(const fragment_shader_payload& payl
171200
Eigen::Vector3f normal = payload.normal;
172201

173202
float kh = 0.2, kn = 0.1;
174-
175-
// TODO: Implement displacement mapping here
176-
// Let n = normal = (x, y, z)
177-
// Vector t = (x*y/sqrt(x*x+z*z),sqrt(x*x+z*z),z*y/sqrt(x*x+z*z))
178-
// Vector b = n cross product t
179-
// Matrix TBN = [t b n]
180-
// dU = kh * kn * (h(u+1/w,v)-h(u,v))
181-
// dV = kh * kn * (h(u,v+1/h)-h(u,v))
182-
// Vector ln = (-dU, -dV, 1)
183-
// Position p = p + kn * n * h(u,v)
184-
// Normal n = normalize(TBN * ln)
203+
float x = normal.x();
204+
float y = normal.y();
205+
float z = normal.z();
206+
Eigen::Vector3f t;
207+
t << x*y/sqrt(x*x+z*z), sqrt(x*x+z*z), z*y/sqrt(x*x+z*z);
208+
Eigen::Vector3f b = normal.cross(t);
209+
Eigen::Matrix3f TBN;
210+
TBN << t, b, normal;
211+
212+
float u, v, w, h;
213+
u = payload.tex_coords.x();
214+
v = payload.tex_coords.y();
215+
w = payload.texture->width;
216+
h = payload.texture->height;
217+
218+
float dU = kh * kn * (payload.texture->getColor(u + 1.0 / w,v).norm() - payload.texture->getColor(u,v).norm());
219+
float dV = kh * kn * (payload.texture->getColor(u,v + 1.0 / h).norm() - payload.texture->getColor(u,v).norm());
220+
221+
Vector3f ln;
222+
ln << -dU, dV, 1;
223+
224+
point += kn * normal * payload.texture->getColor(u,v).norm();//这一步就是区分displacement与bump的关键,位移
225+
normal = (TBN * ln).normalized();
185226

186227

187228
Eigen::Vector3f result_color = {0, 0, 0};
@@ -190,10 +231,17 @@ Eigen::Vector3f displacement_fragment_shader(const fragment_shader_payload& payl
190231
{
191232
// TODO: For each light source in the code, calculate what the *ambient*, *diffuse*, and *specular*
192233
// components are. Then, accumulate that result on the *result_color* object.
193-
194-
234+
235+
Eigen::Vector3f l = light.position - point;
236+
Eigen::Vector3f v = eye_pos - point;
237+
Eigen::Vector3f h = (l.normalized() + v.normalized()).normalized();
238+
Vector3f ambient = ka.cwiseProduct(amb_light_intensity);
239+
Vector3f diffuse = kd.cwiseProduct(light.intensity / (l.dot(l)) * std::max(0.0f, (normal.dot(l.normalized()))));
240+
Vector3f specular = ks.cwiseProduct(light.intensity / (l.dot(l)) * pow(std::max(0.0f, normal.dot(h)), p));
241+
result_color += ambient + diffuse + specular;
195242
}
196243

244+
197245
return result_color * 255.f;
198246
}
199247

@@ -231,6 +279,28 @@ Eigen::Vector3f bump_fragment_shader(const fragment_shader_payload& payload)
231279
// Vector ln = (-dU, -dV, 1)
232280
// Normal n = normalize(TBN * ln)
233281

282+
float x = normal.x();
283+
float y = normal.y();
284+
float z = normal.z();
285+
Eigen::Vector3f t;
286+
t << x*y/sqrt(x*x+z*z), sqrt(x*x+z*z), z*y/sqrt(x*x+z*z);
287+
Eigen::Vector3f b = normal.cross(t);
288+
Eigen::Matrix3f TBN;
289+
TBN << t, b, normal;
290+
291+
float u, v, w, h;
292+
u = payload.tex_coords.x();
293+
v = payload.tex_coords.y();
294+
w = payload.texture->width;
295+
h = payload.texture->height;
296+
297+
float dU = kh * kn * (payload.texture->getColorBilinear(u + 1.0 / w,v).norm() - payload.texture->getColorBilinear(u,v).norm());
298+
float dV = kh * kn * (payload.texture->getColorBilinear(u,v + 1.0 / h).norm() - payload.texture->getColorBilinear(u,v).norm());
299+
300+
Vector3f ln;
301+
ln << -dU, dV, 1;
302+
303+
normal = (TBN * ln).normalized();
234304

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

Assignment3/codes/rasterizer.cpp

+39-21
Original file line numberDiff line numberDiff line change
@@ -259,27 +259,45 @@ static Eigen::Vector2f interpolate(float alpha, float beta, float gamma, const E
259259
//Screen space rasterization
260260
void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos)
261261
{
262-
// TODO: From your HW3, get the triangle rasterization code.
263-
// TODO: Inside your rasterization loop:
264-
// * v[i].w() is the vertex view space depth value z.
265-
// * Z is interpolated view space depth for the current pixel
266-
// * zp is depth between zNear and zFar, used for z-buffer
267-
268-
// float Z = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
269-
// float zp = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
270-
// zp *= Z;
271-
272-
// TODO: Interpolate the attributes:
273-
// auto interpolated_color
274-
// auto interpolated_normal
275-
// auto interpolated_texcoords
276-
// auto interpolated_shadingcoords
277-
278-
// Use: fragment_shader_payload payload( interpolated_color, interpolated_normal.normalized(), interpolated_texcoords, texture ? &*texture : nullptr);
279-
// Use: payload.view_pos = interpolated_shadingcoords;
280-
// 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;
281-
// Use: auto pixel_color = fragment_shader(payload);
282-
262+
float minX=INT_MAX, maxX=INT_MIN, maxY=INT_MIN, minY=INT_MAX;
263+
for(auto &k:t.v){//找到bounding box的边界坐标
264+
minX = int(std::min(minX,k.x()));
265+
maxX = std::max(maxX,k.x());
266+
maxX = maxX == int(maxX) ? int(maxX)-1 : maxX;
267+
maxY = std::max(maxY,k.y());
268+
maxY = maxY == int(maxY) ? int(maxY)-1 : maxY;
269+
minY = int(std::min(minY,k.y()));
270+
}
271+
for (int x = minX; x < maxX; x++) {
272+
273+
for (int y = minY; y < maxY; y++) {
274+
if (insideTriangle(x + 0.5, y + 0.5, t.v)) {
275+
auto[alpha, beta, gamma] = computeBarycentric2D(x + 0.5, y + 0.5, t.v);
276+
float w_reciprocal = 1.0/(alpha / t.a().w() + beta / t.b().w() + gamma / t.c().w());
277+
float z_interpolated = alpha * t.a().z() / t.a().w() + beta * t.b().z() / t.b().w() + gamma * t.c().z() / t.c().w();
278+
z_interpolated *= w_reciprocal;
279+
280+
int cur_index = get_index(x, y);
281+
if (-z_interpolated < depth_buf[cur_index]) {
282+
depth_buf[cur_index] = -z_interpolated;
283+
// TODO: Interpolate the attributes:
284+
auto interpolated_color = interpolate(alpha, beta, gamma, t.color[0], t.color[1], t.color[2], 1);
285+
auto interpolated_normal = interpolate(alpha, beta, gamma, t.normal[0], t.normal[1], t.normal[2], 1);
286+
auto interpolated_texcoords = interpolate(alpha, beta, gamma, t.tex_coords[0], t.tex_coords[1], t.tex_coords[2], 1);
287+
auto interpolated_shadingcoords = interpolate(alpha, beta, gamma, view_pos[0], view_pos[1], view_pos[2], 1);
288+
289+
290+
fragment_shader_payload payload( interpolated_color, interpolated_normal.normalized(), interpolated_texcoords, texture ? &*texture : nullptr);
291+
payload.view_pos = interpolated_shadingcoords;
292+
//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;
293+
auto pixel_color = fragment_shader(payload);
294+
Vector2i vertex;
295+
vertex << x, y;
296+
set_pixel(vertex, pixel_color);
297+
}
298+
}
299+
}
300+
}
283301

284302
}
285303

0 commit comments

Comments
 (0)