多重采样MSAA的实现

1.实验内容

 在计算机图形学中,在屏幕上显示对象时,可能会出现许多的“锯齿”,这些锯齿是由顶点数据像素化之后成为片段的方式所引起的,由于将数学意义上的坐标转换到物理的显示器硬件上进行显示,显示器是有一个个像素点构成的,并不能实现数学意义上的“无限小”的描述。为了消除“锯齿”,图形工作者提出了许多抗锯齿的算法(也称为反走样[Anti-aliasing]算法),本文主要介绍OpenGL中提到的一种反走样方法——多重采样(Multisample antialiasing简称 MSAA)。
 只计算每个像素的颜色,而对于那些子采样点只计算一个覆盖信息和遮挡信息来把像素的颜色信息写到每个子采样点里面,最终根据子采样点里面的颜色值来通过某个重建过滤器来降采样生成目标图像。这就是MSAA的原理。

2.MSAA基本原理和方法

 MSAA的原理就是通过采样一个像素内的多个位置并平均它们的值来近似1像素框过滤器的效果。该方法只是提高了采样率,并没有真正的提高分辨率,屏幕上负责显示的像素还是原始的数量。MSAA能实现不错的反走样效果,但是其代价就是计算量的翻倍。不过,实际工业上应用时,增加的采样点并不是规则分布在每个像素内的,而是会按照特定的图案;同时某些采样点还可能被多个像素复用。这样,计算效率便会有所提升。
在这里插入图片描述

3.实验结果与分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include <opencv2/opencv.hpp>
#include<vector>
#include<ctime>
#include<cmath>


using namespace std;
using namespace cv;

//代表二维坐标系下的一点
struct Points {
	double x;
	double y;
};

//err用来代表浮点型的误差,当差值小于err时,代表相同
const float err = 0.01;


//求取两个向量的叉积
float CrossProduct(Points A, Points B, Points P)
{
	Points a, b;//设AB两点间的向量为a,AP两点间的向量为b
	a.x = B.x - A.x;
	a.y = B.y - A.y;//向量a的坐标
	b.x = P.x - A.x;
	b.y = P.y - A.y;//向量b的坐标
	return (a.x * b.y - a.y * b.x);
}


//判断点P是否在向量左侧
bool IsOnLeft(Points A, Points B, Points P)
{
	//double计算可能会有误差
	if (CrossProduct(A, B, P) > 1e-7)
		return true;
	else
		return false;
}

//利用向量法判断一点是否在三角形内
bool pointInTri(Points A, Points B, Points C, Points D)
{
	bool Left = IsOnLeft(A, B, D);//以点D相对于AB的方位来作为参考
	//判断点是否在三角形内部
	if ((Left == IsOnLeft(B, C, D)) && (Left == IsOnLeft(C, A, D)))
		return true;
	else
		return false;
}

int main() {
	//背景图片
	cv::Mat image(200, 200, CV_8UC3, cv::Scalar(100, 100, 100));
	//三角形的三个顶点像素的中心坐标
	Points triP1 = {30, 30 }, triP2 = { 180, 180 }, triP3 = { 150, 190 };

	//对每个像素进行遍历
	for (int row = 0; row < image.rows; row++)
	{
		for (int col = 0; col < image.cols; col++)
		{
			int inTriNums = 0;
			//以该像素为中心点,分别在左上,右上,左下,右下采样
			Points sam1 = { row - 0.5, col - 0.5 }, sam2 = { row - 0.5, col + 0.5 };
			Points sam3 = { row + 0.5, col - 0.5 }, sam4 = { row + 0.5, col + 0.5 };
			if (pointInTri(triP1, triP2, triP3, sam1)) inTriNums++;
			if (pointInTri(triP1, triP2, triP3, sam2)) inTriNums++;
			if (pointInTri(triP1, triP2, triP3, sam3)) inTriNums++;
			if (pointInTri(triP1, triP2, triP3, sam4)) inTriNums++;
			//根据MSAA的原理计算深度
			unsigned char pixels = 255 * (inTriNums / 4);
			if(inTriNums)image.at<Vec3b>(row, col) = {0, 0, pixels};
		}

	}
	cv::imshow("image", image);
	cv::waitKey(0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只可爱的小猴子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值