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采样下的极限了吧

 

### Games101 作业2 MSAA实现方法 在处理多采样抗锯齿(MSAA, Multi-Sample Anti-Aliasing)技术时,主要目标是在不显著增加计算成本的情况下提高图像质量。对于Games101课程中的第二项作业而言,重点在于理解如何配置渲染管线来启用并有效利用MSAA。 #### 启用MSAA设置 为了支持MSAA,在初始化Direct3D设备时需指定所需的样本数量以及质量等级: ```cpp DXGI_SWAP_CHAIN_DESC scd; scd.SampleDesc.Count = 4; // 设置为四倍采样 scd.SampleDesc.Quality = 0; // 使用默认的质量级别 ``` 上述代码片段展示了创建交换链描述结构体`DXGI_SWAP_CHAIN_DESC`实例化对象`sdc`的过程,并设置了样本计数为4表示采用四重采样的方式[^1]。 #### 创建带有MSAA的支持纹理资源 当定义用于颜色输出的目标视图时,应确保其格式能够兼容所选的多重采样模式: ```cpp D3D11_TEXTURE2D_DESC depthStencilDesc; depthStencilDesc.MipLevels = 1u; depthStencilDesc.ArraySize = 1u; depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilDesc.SampleDesc.Count = 4u; // 对于深度模板缓冲区同样应用相同的采样率 depthStencilDesc.SampleDesc.Quality = 0u; // ...其他参数保持不变... ID3D11Texture2D* pDepthStencil = nullptr; device->CreateTexture2D(&depthStencilDesc, NULL, &pDepthStencil); ``` 这段C++代码说明了怎样构建适合做深度测试与模板操作的同时也适用于MSAA场景下的纹理对象[^2]。 #### 渲染过程中考虑MSAA的影响 一旦启用了MSAA选项,则在整个绘制流程里都需要特别注意那些可能影响最终效果的操作。例如,在执行任何几何变换之前要确认顶点着色器阶段不会破坏原始边缘特征;而在像素着色期间则应当避免不必要的条件分支语句以免造成性能损失。 最后值得注意的是,尽管MSAA可以在很大程度上改善视觉体验,但它并非万能药——某些类型的伪影仍然无法通过这种方式完全消除。因此开发者们还需结合实际情况灵活调整策略以达到最佳平衡点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值