0
点赞
收藏
分享

微信扫一扫

game101 作业2(含提高)

卿卿如梦 2022-02-12 阅读 32
c++图形学

虚拟机代码:
计算重心坐标的函数
static std::tuple<float, float, float> computeBarycentric2D(float x, float y, const Vector3f* v)

static std::tuple<float, float, float> computeBarycentric2D(float x, float y, const Vector3f* 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};
}

某个像素点是否在三角形内 注意将框架中的int 变成float,否则看不到效果
static bool insideTriangle(float x, float y, const Vector3f* _v)

static bool insideTriangle(float x, float y, const Vector3f* _v)
{   
    // 1, get a vector
    Eigen::Vector2f P;
    P<< x, y;

    Eigen::Vector2f AB,BC,CA,AP,BP,CP;
    AB = _v[1].head(2) - _v[0].head(2);
    BC = _v[2].head(2) - _v[1].head(2);
    CA = _v[0].head(2) - _v[2].head(2);
    AP = P - _v[0].head(2);
    BP = P - _v[1].head(2);
    CP = P - _v[2].head(2);
    return ((AB[0]*AP[1] - AB[1]*AP[0]) >0 
        && (BC[0]*BP[1] - BC[1]*BP[0]) >0
        && (CA[0]*CP[1] - CA[1]*CP[0]) >0)
        ||
        (  (AB[0]*AP[1] - AB[1]*AP[0]) <0 
        && (BC[0]*BP[1] - BC[1]*BP[0]) <0
        && (CA[0]*CP[1] - CA[1]*CP[0]) <0);

    // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
}

光栅化三角形MASS4为提高部分
void rst::rasterizer::rasterize_triangle(const Triangle& t)
里面w_reciprocal 为推导公式的一部分,详见下面的理论参考链接,框架直接给出了公式,但自己推导发现费劲!!!

//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
    // get bounding box range
    // get min and max coordinate 
    float minx = std::min({v[0][0], v[1][0], v[2][0]});
    float maxx = std::max({v[0][0], v[1][0], v[2][0]});
    float miny = std::min({v[0][1], v[1][1], v[2][1]});
    float maxy = std::max({v[0][1], v[1][1], v[2][1]});

    // get Integer
    minx = (int)std::floor(minx);
    miny = (int)std::floor(miny);
    maxx = (int)std::ceil(maxx);
    maxy = (int)std::ceil(maxy);

    // using MASS ?
    bool MSAA = true;
    // traverse entail bounding box 
    if(MSAA){
        std::vector<Eigen::Vector2f> mass4 = 
        {
            {0.25,0.25},
            {0.75,0.25},
            {0.75,0.25},
            {0.75,0.75}
        };
        
        for(int i = minx;i<=maxx;i++){
            for(int j = miny;j<=maxy;j++){
                float minDeeph = FLT_MAX;
                float count = 0;
                for(int k = 0;k<4;k++){
                    if(insideTriangle((float)i + mass4[k][0], (float)j + mass4[k][1], t.v)){
                        // get alpha beta gamma
                        count++;
                        float alpha,beta,gamma;
                        auto tup = computeBarycentric2D(i, j, t.v);
                        std::tie(alpha,beta,gamma) = tup;
                        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;
                        minDeeph = std::min(minDeeph, z_interpolated);
                    }
                }
                // compare z_interpolated and z_buffer
                if(minDeeph < depth_buf[get_index(i,j)]){
                    // replace
                    depth_buf[get_index(i,j)] = minDeeph;
                    Eigen::Vector3f newColor = t.getColor() * count / 4.0;
                    Eigen::Vector3f newPos;
                    newPos<< (float)i, (float)j, minDeeph;
                    set_pixel(newPos, newColor);
                }
            }
        }
    }else{
        for(int i = minx;i<=maxx;i++){
            for(int j = miny;j<=maxy;j++){
                if(insideTriangle((float)i + 0.5, (float)j + 0.5, t.v)){
                    // get alpha beta gamma
                    float alpha,beta,gamma;
                    auto tup = computeBarycentric2D(i, j, t.v);
                    std::tie(alpha,beta,gamma) = tup;
                    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;
                    // compare z_interpolated and z_buffer
                    if(z_interpolated < depth_buf[get_index(i,j)]){
                        // replace
                        depth_buf[get_index(i,j)] = z_interpolated;
                        Eigen::Vector3f newColor = t.getColor();
                        Eigen::Vector3f newPos;
                        newPos<< (float)i, (float)j, z_interpolated;
                        set_pixel(newPos, newColor);
                    }
                }
            }
        }

    }
    
    // If so, use the following code to get the interpolated z value.
    //auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
    //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;

    // TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
}

结果:
没有用MSAA4
在这里插入图片描述
使用MSAA4
在这里插入图片描述

理论参考链接

代码参考链接

C++/C++11中std::transform的使用

std::floor和std:ceil简述

std::tie详解

举报

相关推荐

0 条评论