当前位置: 首页 > news >正文

3.8【Q】cv

这个draw_line函数的逻辑和功能是什么?代码思路是什么?怎么写的?

这个t是什么?t.v[0]和t.v[1],[2]又是什么?

void rst::rasterizer::draw(rst::pos_buf_id pos_buffer, rst::ind_buf_id ind_buffer, rst::Primitive type)
{
    if (type != rst::Primitive::Triangle)
    {
        throw std::runtime_error("Drawing primitives other than triangle is not implemented yet!");
    }
    auto& buf = pos_buf[pos_buffer.pos_id];
    auto& ind = ind_buf[ind_buffer.ind_id];

    float f1 = (100 - 0.1) / 2.0;
    float f2 = (100 + 0.1) / 2.0;

    Eigen::Matrix4f mvp = projection * view * model;
    for (auto& i : ind)
    {
        Triangle t;

        Eigen::Vector4f v[] = {
                mvp * to_vec4(buf[i[0]], 1.0f),
                mvp * to_vec4(buf[i[1]], 1.0f),
                mvp * to_vec4(buf[i[2]], 1.0f)
        };

        for (auto& vec : v) {
            vec /= vec.w();
        }

        for (auto & vert : v)
        {
            vert.x() = 0.5*width*(vert.x()+1.0);
            vert.y() = 0.5*height*(vert.y()+1.0);
            vert.z() = vert.z() * f1 + f2;
        }

        for (int i = 0; i < 3; ++i)
        {
            t.setVertex(i, v[i].head<3>());
            t.setVertex(i, v[i].head<3>());
            t.setVertex(i, v[i].head<3>());
        }

        t.setColor(0, 255.0,  0.0,  0.0);
        t.setColor(1, 0.0  ,255.0,  0.0);
        t.setColor(2, 0.0  ,  0.0,255.0);

        rasterize_wireframe(t);
    }
}

这个draw函数的输入参数都是什么?有什么意义?内部处理逻辑是什么?

void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
    
    // TODO : Find out the bounding box of current triangle.
    // iterate through the pixel and find if the current pixel is inside the triangle

    // 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.
}

这里为什么有一个“  auto v = t.toVector4();”操作?作用是什么?

什么叫“支持透视投影下的正确深度插值透视校正属性插值”?还是没理解,形象地说明?为什么要拓展到四维?

void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto& v0 = t.v;
    auto& v1 = t.v;
    auto& v2 = t.v;

    // 计算三角形的包围盒
    float min_x = std::min({v0.x(), v1.x(), v2.x()});
    float max_x = std::max({v0.x(), v1.x(), v2.x()});
    float min_y = std::min({v0.y(), v1.y(), v2.y()});
    float max_y = std::max({v0.y(), v1.y(), v2.y()});

这些 v0,v1,v2是什么意思?原代码里写的不是 auto v = t.toVector4();吗?

void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
       // 计算包围盒
    float min_x = std::min({t.a().x(), t.b().x(), t.c().x()});
    float max_x = std::max({t.a().x(), t.b().x(), t.c().x()});
    float min_y = std::min({t.a().y(), t.b().y(), t.c().y()});
    float max_y = std::max({t.a().y(), t.b().y(), t.c().y()});
    // 转换为整数像素范围并钳位
    int x_begin = std::max(static_cast<int>(std::floor(min_x)), 0);
    int x_end = std::min(static_cast<int>(std::ceil(max_x)), width);
    int y_begin = std::max(static_cast<int>(std::floor(min_y)), 0);
    int y_end = std::min(static_cast<int>(std::ceil(max_y)), height);
    // 遍历包围盒内的所有像素
    for (int x = x_begin; x < x_end; ++x) {
        for (int y = y_begin; y < y_end; ++y) {
            float center_x = x + 0.5f;
            float center_y = y + 0.5f;

            if (insideTriangle(center_x, center_y, t)) {
                // 计算重心坐标
                Eigen::Vector2f A(v0.x(), v0.y());
                Eigen::Vector2f B(v1.x(), v1.y());
                Eigen::Vector2f C(v2.x(), v2.y());
                Eigen::Vector2f P(center_x, center_y);

                float denominator = (B.y() - C.y()) * (A.x() - C.x()) + (C.x() - B.x()) * (A.y() - C.y());
                if (denominator == 0) continue;

                float u = ((B.y() - C.y()) * (P.x() - C.x()) + (C.x() - B.x()) * (P.y() - C.y())) / denominator;
                float v = ((C.y() - A.y()) * (P.x() - C.x()) + (A.x() - C.x()) * (P.y() - C.y())) / denominator;
                float w = 1 - u - v;

                if (u >= 0 && v >= 0 && w >= 0) {
                    // 插值深度
                    float z_interpolated = u * v0.z() + v * v1.z() + w * v2.z();
                    int index = get_index(x, y);

                    // 深度测试
                    if (z_interpolated < depth_buf[index]) {
                        // 颜色插值
                        Eigen::Vector3f color = u * t.color + v * t.color + w * t.color;
                        set_pixel(Eigen::Vector3f(x, y, 1.0f), color);
                        depth_buf[index] = z_interpolated;
                    }
                }
            }
        }
    }  
    // TODO : Find out the bounding box of current triangle.
    // iterate through the pixel and find if the current pixel is inside the triangle

    // 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.
}

在遍历包围盒内所有像素时,为什么要定义出center_x和center_y?在计算重心坐标时,各行代码操作的意义和作用又是什么?

void rst::rasterizer::rasterize_triangle(const Triangle& t) {

    auto v = t.toVector4();中,为什么一开始要定义出一个v?v在后续的计算中有什么用?

这个v的w维度,是在传入t后进行扩展的,并没有经过mvp矩阵的变化,那么三个点的w维度上的值不都是1吗?后面 float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());又有什么意义?

不是,mvp矩阵是在draw函数中进行计算的,在draw函数最后调用了rasterize_triangle(t);,在rasterize_triangle(t);中配置auto v = t.toVector4();,那么t的第四维度w不该是1吗?mvp矩阵并没有在此时发挥作用?

static bool insideTriangle(int x, int y,const Vector3f* _v)
{   
    Vector3f P(x+0.5f,y+0.5f,1.0f);
    const Vector3f& A = _v[0];
    const Vector3f& B = _v[1];
    const Vector3f& C = _v[2];


    // 计算三个边的向量和点P到顶点的向量
    Vector3f AB =  B - A;
    Vector3f BC =  C - B;
    Vector3f CA =  A - C;

    Vector3f AP = P - A;
    Vector3f BP = P - B;
    Vector3f CP = P - C;

    // 计算叉积符号
    float cross1 = AB.cross(AP).z();
    float cross2 = BC.cross(BP).z();
    float cross3 = CA.cross(CP).z();

    // 检查符号是否一致
    return (cross1 > 0 && cross2 > 0 && cross3 > 0) || (cross1 < 0 && cross2 < 0 && cross3 < 0);
    // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
}

这段代码能实现判断点是否在内外部的原理是什么?cross1等取z是什么意思?有什么意义?

为什么Vector3f P(x+0.5f,y+0.5f,1.0f);可以确保测试点为像素中心?什么叫像素中心?为什么要保证在像素中心?

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};
}

这个函数是在干什么?有什么用?传入参数的意义和输出是什么意思?

std::tie(alpha, beta, gamma) = tup;

 这句什么意思?tie什么意思?

 //MSAA 4X
 if (MSAA) {
  // 格子里的细分四个小点坐标
  std::vector<Eigen::Vector2f> pos
  {
   {0.25,0.25},
   {0.75,0.25},
   {0.25,0.75},
   {0.75,0.75},
  };
  for (int x = min_x; x <= max_x; x++) {
   for (int y = min_y; y <= max_y; y++) {
    // 记录最小深度
    float minDepth = FLT_MAX;
    // 四个小点中落入三角形中的点的个数
    int count = 0;
    // 对四个小点坐标进行判断 
    for (int i = 0; i < 4; i++) {
     // 小点是否在三角形内
     if (insideTriangle((float)x + pos[i][0], (float)y + pos[i][1], t.v)) {
      // 如果在,对深度z进行插值
      auto tup = computeBarycentric2D((float)x + pos[i][0], (float)y + pos[i][1], t.v);
      float alpha;
      float beta;
      float gamma;
                        // std::tie表示打散tup到 alpha beta gamma三个分量
      std::tie(alpha, beta, gamma) = tup;

                        // reciprocal 倒数
      float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());

                        // 按照三角形三个点的权重,对当前点插值,求出z值,注意,这里的reciprocal用的有点莫名其妙,先不用管
                        // 而且alpha beta gamma用起来是需要矫正的
                        // 此处留个疑问:为什么不能在投影变换时,求出每个点的z坐标映射值呢?
      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;
                        // 求出当前点中四个小点对应的深度,以代表当前点的z值,用来和其他点的z做对比
      minDepth = std::min(minDepth, z_interpolated);
                        // 包含一个点count +1
      count++;
     }
    }
    if (count != 0) {
     if (depth_buf[get_index(x, y)] > minDepth) {

                        // 简单的对color/4也可以,处理的比较粗糙。
                        // 注意getColor其实就只用了一个值,三角形三个点的颜色相同
                        // 这里还考虑了当前缓冲里面存贮的颜色值
      Vector3f color = t.getColor()*count/4 + (4-count)*frame_buf[get_index(x,y)]/4;
      Vector3f point(3);
      point << (float)x, (float)y, minDepth;
      // 替换深度
      depth_buf[get_index(x, y)] = minDepth;
      // 修改颜色
      set_pixel(point, color);
     }
    }
   }
  }
 }

详细解释这段代码每一句的作用和意义?如何实现MSAA抗锯齿的?

 Vector3f color = t.getColor()*count/4 + (4-count)*frame_buf[get_index(x,y)]/4;这个color的计算是什么意思?怎么做的?

为什么不能在投影变换时,求出每个点的z坐标映射值呢?什么意思?思路是什么?

当前代码开启了超采样,但是if (count != 4)std::cout << "current count test: " << count << '\n';并没有输出,说明count要么是0要么是4,为什么会发生这种情况?为什么?如何处理?使其去锯齿?

就是这个函数static bool insideTriangle(float x, float y,const Vector3f* _v)的传入参数一开始设置为int的原因;此外,想要进一步提升抗锯齿的效果,该怎么做?给出修改代码


/ 修改后的抗锯齿核心逻辑
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
    
    // 8x旋转采样点布局
    std::vector<Eigen::Vector2f> pos { /* 上述8个点 */ };
    
    // 包围盒扩展(增加1像素冗余)
    min_x = static_cast<int>(std::floor(min_x - 1.0f));
    max_x = static_cast<int>(std::ceil(max_x + 1.0f));
    
    for (int x = min_x; x <= max_x; x++) {
        for (int y = min_y; y <= max_y; y++) {
            int count = 0;
            float minDepth = FLT_MAX;
            
            // 第一层8x采样
            for (int i=0; i<8; ++i) {
                float sx = x + pos[i][0], sy = y + pos[i][1];
                if (insideTriangle(sx, sy, t.v)) {
                    // 计算深度...
                    count++;
                }
            }
            
            // 边缘区域二次采样
            if (count>0 && count<8) {
                std::vector<Eigen::Vector2f> edge_pos {/* 4个点 */};
                for (auto& ep : edge_pos) {
                    if (insideTriangle(x+ep[0], y+ep[1], t.v)) count++;
                }
            }
            
            // 深度加权颜色混合
            if (count > 0) {
                float weight = count / 12.0; // 最大12采样
                Vector3f color = /* 加权混合公式 */;
                set_pixel(point, color);
            }
        }
    }
    
    // 后处理阶段
    post_process(); 
}

完成这个代码里省略的部分

增加采样数量后,在原来4*的基础上,8*的图形边缘出现了黑边,且抗锯齿效果并没有显著提升,甚至有所倒退,这是为什么?

相关文章:

  • AWS 如何导入内部SSL 证书
  • VsCode导入时选择相对路径
  • 伊藤积分(Ito Integral):随机世界中的积分魔法
  • Windows下配置Conda环境路径
  • C语言中内存布局(内存模型)是怎样的?
  • 一周热点-OpenAI 推出了 GPT-4.5,这可能是其最后一个非推理模型
  • 仿真新能源充电桩管理系统
  • Linux16-数据库、HTML
  • 人工智能(AI)与 生命体智能的本质差异
  • Office/WPS接入DeepSeek等多个AI工具,开启办公新模式!
  • 【Raspberry Pi 5 测评】无显示器上手指南
  • .NET Core全屏截图,C#全屏截图
  • Windows 如何开启和使用FTP服务
  • 从零开始训练小型语言模型之minimind
  • cannon g3810打印机设置
  • Python自学指南:从入门到进阶(第一天)
  • Mysql的卸载安装配置以及简单使用
  • 【GPT入门】第3课 客服会话质检(思维链)
  • SGLang Router:基于缓存感知负载均衡的数据并行路由实践
  • 约束问题的最优性条件
  • 上海设计网站建设/seo外链
  • 福建省建设工程继续教育网站/域名注册阿里云
  • wordpress成品网站yunbuluo/武汉网络推广公司排名
  • 有哪些做投行网站/做网页设计一个月能挣多少
  • 庆阳市人大常委会网站建设/seo能干一辈子吗
  • 建设手机银行官方网站/现在有哪些网址