Home Forums GAMES在线课程(现代计算机图形学入门)讨论区 作业2出现上下左右颠倒的问题成因是什么以及应当如何解决

Viewing 7 reply threads
  • Author
    Posts
    • #8493 Score: 0
      sick_suck
      Participant
      Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
      {
          // TODO: Copy-paste your implementation from the previous assignment.
          zNear *=-1;
          zFar *=-1;
          std::cout<<"zNear is "<<zNear<<std::endl;
          std::cout<<"zFar is "<<zFar<<std::endl;
          Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
          Eigen::Matrix4f m;
          m<<zNear,0,0,0,
          0,zNear,0,0,
          0,0,zNear+zFar,-zNear*zFar,
          0,0,1,0;
          float halve = eye_fov/2*MY_PI/180;
          float top = tan(halve)*zNear;
          float bottom = -top;
          float right = top*aspect_ratio;
          float left = -right;
          Eigen::Matrix4f n,p;
          n<<2/(right-left),0,0,0,
          0,2/(top-bottom),0,0,
          0,0,2/(zNear-zFar),0,
          0,0,0,1;
          p<<1,0,0,-(right+left)/2,
          0,1,0,-(top+bottom)/2,
          0,0,1,-(zFar+zNear)/2,
          0,0,0,1;
          projection = n*p*m;
          return projection;
      }
      
      
      static bool insideTriangle(float x, float y, const Vector3f* _v)
      {   
          // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
          
          Vector3f point_A = _v[0], point_B = _v[1], point_C = _v[2], point_D = Vector3f(x,y,1);
          Vector3f vector_AB = point_B-point_A, vector_BC = point_C-point_B, vector_CA = point_A-point_C, vector_AD = point_D-point_A, vector_BD = point_D-point_B, vector_CD = point_D-point_C;
          Vector3f AB_X_AD = vector_AB.cross(vector_AD), BC_X_BD = vector_BC.cross(vector_BD), CA_X_CD = vector_CA.cross(vector_CD);
          int a = (AB_X_AD.z())*(BC_X_BD.z()), b = (AB_X_AD.z())*(CA_X_CD.z());
          return (AB_X_AD.z()>0&&BC_X_BD.z()>0&&CA_X_CD.z()>0)||(AB_X_AD.z()<0&&BC_X_BD.z()<0&&CA_X_CD.z()<0);
      }
      
      
      void rst::rasterizer::rasterize_triangle(const Triangle& t) {
          auto v = t.toVector4();
          
          // TODO : Find out the bounding box of current triangle.
          int left = MIN(MIN(v[0].x(),v[1].x()),v[2].x()), right = MAX(MAX(v[0].x(),v[1].x()),v[2].x()), down = MIN(MIN(v[0].y(),v[1].y()),v[2].y()), up = MAX(MAX(v[0].y(),v[1].y()),v[2].y());
          // iterate through the pixel and find if the current pixel is inside the triangle
          const Vector3f points[3] = {Vector3f(t.v[0].x(),t.v[0].y(),1), Vector3f(t.v[1].x(),t.v[1].y(),1), Vector3f(t.v[2].x(),t.v[2].y(),1)};
          Vector3f color = t.getColor();
          for(int i = left;i<right;i++){
              for(int j = down;j<up;j++){
                  //background color is black;
                  float r = 0,g = 0,b = 0;
                  for(float _x_ = i+0.25;_x_<i+1;_x_+=0.5){
                      for(float _y_ = j+0.25;_y_<j+1;_y_+=0.5){
                          if(insideTriangle(_x_,_y_,t.v)){
                              r+=0.25f*color.x();
                              g+=0.25f*color.y();
                              b+=0.25f*color.z();
                          }
                      }
                  }
                  auto[alpha, beta, gamma] = computeBarycentric2D(i, j, 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;
                  if(insideTriangle(i,j,t.v)&&z_interpolated<depth_buf[get_index(i,j)]){
                      this->set_pixel(Vector3f(i,j,z_interpolated),Vector3f(r,g,b));
                      depth_buf[get_index(i,j)] = z_interpolated;
                  }
              }
          }
      }
      

      我觉得应该是这个透视矩阵的问题吧?我看作业1初始时生成的三角形也是倒着的

    • #8546 Score: 0
      zhw
      Participant

      楼主解决了吗,我透视矩阵和你一样的,应该没问题,看起来是投影到正交矩阵有问题。

    • #8547 Score: 0
      zhw
      Participant

      结合了其他帖子,我总结的原因是:
      1.opencv左上为原点,课程中左下为原点,所以导致y,z两轴是反着的。
      2.代码中zNear和zFar是按照Z轴正方向给的。
      综上,楼主投影变换修改方式:注释zNear/zFar *=-1;float top = – tan(halve)*zNear;

    • #8595 Score: 1
      曹某
      Participant
      1 pt

      遇到跟楼主一样的问题,确实就是zNear, zFar给的值有问题,问题查了两天:-(
      保证zNear, zFar是负数显示就不颠倒了。

      和课程不一样,非常不便于理解。

      作业2里也有这个问题,如果按照作业1里这么处理Z-buff计算会有新的错误,因为rasterizer里hard code了0.1和50。所以要么手动修改hard code代码,要么对应调整投影矩阵抵消符号。

      This post has received 1 vote up.
    • #8894 Score: 0
      weiwen
      Participant

      我和楼主写法与遇到的问题一致,说一下我的解决方法,希望有所帮助~
      传入的n,f=0.1,50先不用动,用它们计算t,b,r,l时保证t>0,b=-t,r>0,l=-r就好。之后再将n,f各自取反,即n,f=-0.1,-50,这样就能得到正确的P矩阵。

    • #8901 Score: 0
      Aberstone
      Participant
      1 pt

      是因为 zNear *= -1;top = tan(theta)*zNear; 这两行改变zNear的正负,导致top符号错误

    • #8904 Score: 0
      singlelong
      Participant

      应该是像素坐标系左上角是原点,向右是X正方向,向下是Y正方向,刚好和推到公式时使用的是反的,get_projection_matrix中,最后再左乘一个将X和Y变成—X和-Y的矩阵,得到了和作业说明中一样的结果

    • #9085 Score: 0
      Bruce
      Participant

      您好,可以请教一个问题吗?Assignment2中提高项描述MSAA时说到要对像素中的每一个样本都维护其深度值,这个是如何办到的?代码中给我们的深度值不是以像素为单位的吗?我们应该如何得到2*2个样本各自的深度值?维护了这个深度值之后,着色时不也是以像素为单位吗?要如何分别为每个样本着色呢?

      我记得课上说记录样本点在三角形中的比例,我只做了一个像素分为4个样本统计他们有多少在三角形中,然后反馈到该像素的color上,比如 * 0.75这样,也有抗锯齿的效果,实在是有点懵这里。

Viewing 7 reply threads
  • You must be logged in to reply to this topic.