光栅化
void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos)
{
auto v = t.toVector4();
rst::BoundingBox2D bbox;
bbox = createBoundingBox2D(v);
for (int x = 0; x < bbox.maxX; ++x)
{
for (int y = 0; y < bbox.maxY; ++y)
{
bool isInside = insideTriangle(x,y, t.v);
if (isInside)
{
auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
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;
auto interpolated_color = alpha * t.color[0]+ beta * t.color[1] + gamma * t.color[2];
auto interpolated_normal = interpolate(alpha, beta, gamma, t.normal[0], t.normal[1], t.normal[2], Z);
auto interpolated_texcoords = interpolate(alpha, beta, gamma, t.tex_coords[0], t.tex_coords[1], t.tex_coords[2], Z);
auto interpolated_shadingcoords = interpolate(alpha, beta, gamma, view_pos[0], view_pos[1], view_pos[2], Z);
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);
int index = get_index(x, y);
if (static_cast<std::vector<float>::size_type>(index) < depth_buf.size() && zp < depth_buf[index])
{
depth_buf[index] = zp;
set_pixel( Eigen::Vector2i(x,y), pixel_color);
}
}
}
}
}
Blinn-Phong
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.0f;
Eigen::Vector3f color = payload.color;
Eigen::Vector3f point = payload.view_pos;
Eigen::Vector3f normal = payload.normal;
Eigen::Vector3f result_color = {0, 0, 0};
result_color += amb_light_intensity.cwiseProduct(ka);
for (const auto& light : lights)
{
Eigen::Vector3f lightDir = (light.position - point).normalized();
float lightDistance = (light.position - point).norm();
// 漫反射
float diffuse = std::max(0.0f, normal.dot(lightDir));
result_color += diffuse * light.intensity.cwiseProduct(kd);
// 镜面反射
Eigen::Vector3f viewDir = (eye_pos - point).normalized();
Eigen::Vector3f reflectDir = (lightDir - 2.0f * normal.dot(lightDir) * normal).normalized();
float specular = std::pow(std::max(0.0f, viewDir.dot(reflectDir)), p);
result_color += specular * light.intensity.cwiseProduct(ks);
}
return result_color ;
}
纹理
Eigen::Vector3f texture_fragment_shader(const fragment_shader_payload& payload)
{
Eigen::Vector3f return_color = {0, 0, 0};
if (payload.texture)
{
Eigen::Vector2f tex_coord = payload.tex_coords;
return_color = payload.texture->getColor(tex_coord.x(), tex_coord.y());
// TODO: Get the texture value at the texture coordinates of the current fragment
}
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}, {200, 200, 200}};
auto l2 = light{{-20, 20, 0}, {200, 200, 200}};
std::vector<light> lights = {l1, l2};
Eigen::Vector3f amb_light_intensity{10, 10, 10};
Eigen::Vector3f eye_pos{0, 0, 10};
float p = 15;
Eigen::Vector3f color = texture_color;
Eigen::Vector3f point = payload.view_pos;
Eigen::Vector3f normal = payload.normal;
Eigen::Vector3f result_color = {0, 0, 0};
result_color += amb_light_intensity.cwiseProduct(ka);
for (const auto& light : lights)
{
Eigen::Vector3f lightDir = (light.position - point).normalized();
float lightDistance = (light.position - point).norm();
// 漫反射
float diffuse = std::max(0.0f, normal.dot(lightDir));
result_color += diffuse * light.intensity.cwiseProduct(kd);
// 镜面反射
Eigen::Vector3f viewDir = (eye_pos - point).normalized();
Eigen::Vector3f reflectDir = (lightDir - 2.0f * normal.dot(lightDir) * normal).normalized();
float specular = std::pow(std::max(0.0f, viewDir.dot(reflectDir)), p);
result_color += specular * light.intensity.cwiseProduct(ks);
}
return result_color ;
}
小牛
就是运行了二十几分钟