games101 作业2 原创代码框架进阶版 MSAA4x抗锯齿技术学习

用的库有opencv4.5.5 (vc15)和eign3.4.0

这篇的代码是在我上篇作业1的基础上魔改出来的,目的是为了实现MSAA四倍的抗锯齿技术和实心三角形的光栅化。

#include<Eigen/Eigen>
#include<stdio.h>
#include<cmath>
#include <iostream>
#include <vector>
#include <cctype>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
cv::Mat bg_image = cv::Mat(400, 400, CV_8UC3, Scalar(0, 0, 0));

//质点绕任意过原点的旋转轴进行旋转的操作
Eigen::Vector4d rotating(Eigen::Vector4d point_vector, Eigen::Vector3d Rotary_shaft, double angle)
{
    double u = Rotary_shaft.x(), v = Rotary_shaft.y(), w = Rotary_shaft.z(), o = angle;
    double s = sqrt(u * u + v * v + w * w);
    u = u / s;
    v = v / s;
    w = w / s;
    Eigen::Matrix4d rotating;
    rotating <<
        u * u + (1 - u * u) * cos(o), u* v* (1 - cos(o)) - w * sin(o), u* w* (1 - cos(o)) + v * sin(o), 0,
        u* v* (1 - cos(o)) + w * sin(o), v* v + (1 - v * v) * cos(o), v* w* (1 - cos(o)) - u * sin(o), 0,
        u* w* (1 - cos(o)) - v * sin(o), v* w* (1 - cos(o)) + u * sin(o), w* w + (1 - w * w) * cos(o), 0,
        0, 0, 0, 1;
    Eigen::Vector4d ret = rotating * point_vector;
    return ret;
}



//计算质点相对于摄像机的位置,以摄像机的焦点为坐标原点新建的坐标系,也可以拿来把任意点作为原点建系,求相对位置
Eigen::Vector3d Relative_position(Eigen::Vector4d point_vector, Eigen::Vector4d camera_positon, Eigen::Vector4d camera_z, Eigen::Vector4d camera_x)
{
    Eigen::Vector3d Apart_position;//摄像机位置点到质点的向量
    Apart_position <<
        point_vector.x() - camera_positon.x(),
        point_vector.y() - camera_positon.y(),
        point_vector.z() - camera_positon.z();
    Eigen::Vector3d camera_x_3d, camera_z_3d;
    camera_x_3d <<
        camera_x.x(), camera_x.y(), camera_x.z();
    camera_z_3d <<
        camera_z.x(), camera_z.y(), camera_z.z();
    Eigen::Vector3d camera_y_3d = camera_x_3d.cross(camera_z_3d);//向量叉乘得到垂直于它的向量

    Eigen::Vector3d Relative_position;
    double x = Apart_position.dot(camera_x_3d) / Apart_position.norm();//计算质点在摄像机为原点的坐标系中的x值
    double y = Apart_position.dot(camera_y_3d) / Apart_position.norm();
    double z = Apart_position.dot(camera_z_3d) / Apart_position.norm();
    Relative_position <<
        x, y, z;
    return Relative_position;
}


//摄像机透视成像
Eigen::Vector2d perspective(double fov_w, int width, int height, Eigen::Vector3d Relative_position)
{
    double focal_length = (width / tan(fov_w / 2)) / 20000;
    double x = Relative_position.x() * focal_length / Relative_position.z();
    double y = Relative_position.y() * focal_length / Relative_position.z();
    double z = focal_length;
    Eigen::Vector2d ret;
    ret <<
        (x * 10000) + 200,
        (y * 10000) + 200;
    return ret;
}

//三个顶点连线绘制三角形
void triangle(Point A, Point B, Point C)
{
    Scalar line_color = cv::Scalar(5, 5, 4);
    line(bg_image, A, B, line_color, 2, LINE_8);
    line(bg_image, B, C, line_color, 2, LINE_8);
    line(bg_image, C, A, line_color, 2, LINE_8);
    printf("%d %d\n", A.x, A.y);
}

//判断点D是否在三角形ABC内
bool if_in(Eigen::Vector2d& A, Eigen::Vector2d& B, Eigen::Vector2d& C, double x, double y)
{
    Eigen::Vector3d a, b, c, d;
    a << A.x(), A.y(), 0;
    b << B.x(), B.y(), 0;
    c << C.x(), C.y(), 0;
    d << x, y, 0;
    Eigen::Vector3d AB, AC, AD;
    AB = b - a;
    AC = c - a;
    AD = d - a;
    if (AB.cross(AD).z() > 0 && AD.cross(AC).z() > 0)return 1;
    else return 0;
}

void wirte_point(int x, int y, int r, int g, int b)
{
    bg_image.at<Vec3b>(x, y)[0] = b;
    bg_image.at<Vec3b>(x, y)[1] = g;
    bg_image.at<Vec3b>(x, y)[2] = r;
}

void MSAA_4x(Eigen::Vector2d& A, Eigen::Vector2d& B, Eigen::Vector2d& C, int width, int height)
{
    int x = 0, y = 0;
    for (x = 0; x < width-1; x++)
    {
        for (y = 0; y < height-1; y++)
        {
            int num = 0;
            double m = x * 1.0, n = y * 1.0;
            if (if_in(A, B, C, m + 0.25, n + 0.25))num++;
            if (if_in(A, B, C, m + 0.75, n + 0.25))num++;
            if (if_in(A, B, C, m + 0.25, n + 0.75))num++;
            if (if_in(A, B, C, m + 0.75, n + 0.75))num++;
            switch (num)
            {
            case 0:wirte_point(x, y, 255, 255, 255); break;
            case 1:wirte_point(x, y, 192, 192, 192); break;
            case 2:wirte_point(x, y, 128, 128, 128); break;
            case 3:wirte_point(x, y, 64, 64, 64); break;
            case 4:wirte_point(x, y, 0, 0, 0); break;
            default:printf("MSAA_4X error");
                break;
            }
        }
    }
}
//打点

void tick(Eigen::Vector4d A, Eigen::Vector4d B, Eigen::Vector4d C)//暂时废弃掉的tick刷新函数,以后会有用
{



}
int main(void)
{
    namedWindow("GAMES101-homework2-super-plus - SWPU - Li_JinWen", 1);

    int weith = 400, height = 400;
    double FOV = 3.1415926 / 4;
    Eigen::Vector4d S[3];
    S[0] << 3, 0, 4, 0;
    S[1] << -3, 0, 4, 0;
    S[2] << 0, 0, 2, 0;
    double rotating_speed = 0.05;
    Eigen::Vector3d Rotary_shaft;
    Eigen::Vector4d camera_positon, camera_z, camera_x;
    Rotary_shaft << 0, 0, 1;
    camera_positon << 30, 0, 0, 0;//这里可以修改摄像机焦点摆放的位置
    camera_z << -1, 0, 0, 0;//这里可以修改摄像机的朝向
    camera_x << 0, 1, 0, 0;//这里可以修改摄像机的水平方向
    Eigen::Vector2d A, B, C;
    while (true)
    {
        for (int i = 0; i < 3; i++)
        {
            S[i] = rotating(S[i], Rotary_shaft, rotating_speed);
        }
        A << perspective(FOV, weith, height, Relative_position(S[0], camera_positon, camera_z, camera_x)).x(),
            perspective(FOV, weith, height, Relative_position(S[0], camera_positon, camera_z, camera_x)).y();

        B << perspective(FOV, weith, height, Relative_position(S[1], camera_positon, camera_z, camera_x)).x(),
            perspective(FOV, weith, height, Relative_position(S[1], camera_positon, camera_z, camera_x)).y();

        C << perspective(FOV, weith, height, Relative_position(S[2], camera_positon, camera_z, camera_x)).x(),
            perspective(FOV, weith, height, Relative_position(S[2], camera_positon, camera_z, camera_x)).y();

        MSAA_4x(A, B, C, weith, height);

        imshow("GAMES101-homework2-Original - SWPU - Li_JinWen", bg_image);
        waitKey(100);
        bg_image = cv::Mat(weith, height, CV_8UC3, Scalar(0, 0, 0));
        imshow("GAMES101-homework2-Original - SWPU - Li_JinWen", bg_image);
    }
}

因为,没有用官方的代码框架,然后本人技术菜,也懒得做太复杂,所以是整个是单线程历遍的,所以分辨率降到了400*400也很卡,但是能体现MSAA抗锯齿算法就行了。

效果图如下,这应该是400*400分辨率和4x采样下的极限了吧

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值