Rasterization

Z-Buffer(用来存储深度):储存每个样本(像素)的当前最小值,需要一个额外的缓冲区来存放深度值。为了简单起见,我们假设Z总是正的,较小的z—>近,较大的z—>远

Z-Buffer算法()

{

帧缓存全置为背景色

深度缓存全置为最小z值

for(每一个多边形)

{

扫描转换该多边形

for(该多边形所覆盖的每个象素(x,y) )

{

计算该多边形在该象素的深度值Z(x,y);

if(z(x,y)大于z缓存在(x,y)的值)

{

把z(x,y)存入z缓存中(x,y)处

把多边形在(x,y)处的颜色值存入帧缓存的(x,y)处

}

}

}

}

完整代码参考:

void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos) 
{
    auto v = t.toVector4();

    int min_x = std::min({ v[0].x(), v[1].x(), v[2].x() });
    int max_x = std::max({ v[0].x(), v[1].x(), v[2].x() });
    int min_y = std::min({ v[0].y(), v[1].y(), v[2].y() });
    int max_y = std::max({ v[0].y(), v[1].y(), v[2].y() });

    for (int x = min_x; x <= max_x; x++)//遍历包围盒中的每一个点
    {
        for (int y = min_y; y <= max_y; y++)
        {
            if (insideTriangle((float)x + 0.5, (float)y + 0.5, t.v))//如果这个点在三角形内
            {
                
                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;

                if (zp < depth_buf[get_index(x, y)])
                {
                    // TODO: Interpolate the attributes:
                    // auto interpolated_color
                    // auto interpolated_normal
                    // auto interpolated_texcoords
                    // auto interpolated_shadingcoords

                    auto interpolated_color = interpolate(alpha, beta, gamma, t.color[0], t.color[1], t.color[2], 1);
                    auto interpolated_normal = interpolate(alpha, beta, gamma, t.normal[0], t.normal[1], t.normal[2], 1).normalized();
                    auto interpolated_texcoords = interpolate(alpha, beta, gamma, t.tex_coords[0], t.tex_coords[1], t.tex_coords[2], 1);
                    
                    auto interpolated_shadingcoords = interpolate(alpha, beta, gamma, view_pos[0], view_pos[1], view_pos[2], 1);

                    fragment_shader_payload payload( interpolated_color, interpolated_normal.normalized(), interpolated_texcoords, texture ? &*texture : nullptr);
                    payload.view_pos = interpolated_shadingcoords;
                    // 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;
                    auto pixel_color = fragment_shader(payload);

                    depth_buf[get_index(x, y)] = zp;
                    set_pixel(Eigen::Vector2i(x, y), pixel_color);
                }
            }
        }
    }
}

view_pos[ ]是三角形顶点在view space中的坐标,插值是为了还原在camera space中的坐标 

细节

1、如何找到包围盒

    auto v = t.toVector4();
    int min_x = std::min({ v[0].x(), v[1].x(), v[2].x() });
    int max_x = std::max({ v[0].x(), v[1].x(), v[2].x() });
    int min_y = std::min({ v[0].y(), v[1].y(), v[2].y() });
    int max_y = std::max({ v[0].y(), v[1].y(), v[2].y() });

注释: 这里的v为Z-Buffer指针

2、判断该点是否在三角形内

static bool insideTriangle(int x, int y, const Vector4f* _v){
    Vector3f v[3];
    for(int i=0;i<3;i++)
        v[i] = {_v[i].x(),_v[i].y(), 1.0};
    Vector3f f0,f1,f2;
    f0 = v[1].cross(v[0]);
    f1 = v[2].cross(v[1]);
    f2 = v[0].cross(v[2]);
    Vector3f p(x,y,1.);
    if((p.dot(f0)*f0.dot(v[2])>0) && (p.dot(f1)*f1.dot(v[0])>0) && (p.dot(f2)*f2.dot(v[1])>0))
        return true;
    return false;
}

 质心(重心)坐标(Barycentric):

static std::tuple<float, float, float> computeBarycentric2D(float x, float y, const Vector4f* v){
    float c1 = (x*(v[1].y() - v[2].y()) + (v[2].x() - v[1].x())*y + v[1].x()*v[2].y() - v[2].x()*v[1].y()) / (v[0].x()*(v[1].y() - v[2].y()) + (v[2].x() - v[1].x())*v[0].y() + v[1].x()*v[2].y() - v[2].x()*v[1].y());
    float c2 = (x*(v[2].y() - v[0].y()) + (v[0].x() - v[2].x())*y + v[2].x()*v[0].y() - v[0].x()*v[2].y()) / (v[1].x()*(v[2].y() - v[0].y()) + (v[0].x() - v[2].x())*v[1].y() + v[2].x()*v[0].y() - v[0].x()*v[2].y());
    float c3 = (x*(v[0].y() - v[1].y()) + (v[1].x() - v[0].x())*y + v[0].x()*v[1].y() - v[1].x()*v[0].y()) / (v[2].x()*(v[0].y() - v[1].y()) + (v[1].x() - v[0].x())*v[2].y() + v[0].x()*v[1].y() - v[1].x()*v[0].y());
    return {c1,c2,c3};
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值