首页 > 其他分享 >计算机图形:三角形光栅化

计算机图形:三角形光栅化

时间:2024-05-16 11:22:11浏览次数:25  
标签:bc 插值 bm 像素 绘制 三角形 光栅 图形

目录

三角形光栅化

光栅化是将几何数据经一系列变换,最终转换为像素,而在屏幕上显示的过程.

直线光栅化,在2D屏幕上,对两端点间插值,绘制一条直线(段). 常用中点算法和Bresenham算法,Bresensham算法参见Bresenham画直线算法(所有斜率).

类似地,视口变换后,需要在2D屏幕上绘制三角形\(\bm{abc}\),顶点坐标分别为\(a(x_0,y_0),b(x_1,y_1),c(x_2,y_2)\). 三角形的绘制,需要用顶点的颜色或其他属性插值,即重心坐标插值(详见计算机图形:三角形及重心空间).

假设三顶点颜色\(\bm{c_0,c_1,c_2}\),那么三角形中任一点\(p(x,y)\)重心插值坐标为\((α,β,γ)\),颜色为:

\[\bm{c}=α\bm{c_0}+β\bm{c_1}+γ\bm{c_2} \]

tips: Gouraud明暗处理中,用这种方法对光强进行插值.

绘制三角形轮廓

可用中点算法(midpoint algorithm)绘制三角形轮廓.

img

图片from 计算机是怎么画线的?中点算法与Bresenham算法

中点算法思想:以斜率>0为例,画直线要确定下一像素时,将位于右侧和右上侧的2个待选像素中心点的中点代入直线方程,根据中点位于该直线的上方 or 下方决定下个像素. 当中点位于上侧,说明直线靠近右侧像素;反之,说明直线靠近右上侧像素.

填充三角形内部

总流程:重心坐标 \(\xrightarrow{α,β,γ\in (0,1)?}\) 是否像素绘制\(\xrightarrow{顶点插值颜色}\)像素颜色

平面上任一点\(p(x,y)\),都能用以三角形三顶点\(\bm{a,b,c}\)为基础的重心坐标表示.

\[\bm{p}=α\bm{a}+β\bm{b}+γ\bm{c},α=\frac{A_a}{A},β=\frac{A_b}{A},γ=\frac{A_c}{A} \]

其中,\(A_a,A_b,A_c,A\)分别表示三角形\(pbc,pac,pab,abc\)面积. 由于都是三角形面积比值,可以换算成同底不同高的比值.

该公式可用于颜色等属性插值.

当像素的重心坐标\(α,β,γ\in(0,1)\)时,认为像素中心位于三角形内,而避免顺序问题、消除孔洞.

得到了像素插值颜色,如何填充三角形内部像素?

可遍历屏幕所有像素点,当点位于三角形内部时,通过颜色插值进行绘制.

img

实践中,为减少要遍历的像素点,可用三顶点构造一个边界矩形,将检索范围限制在矩形内. 算法如下:

// a(xa,ya),b(xb,yb),c(xc,yc) consits of a 2D triangle, including color property
xmin = floor(x[i]);
xmax = ceiling(x[i]);
ymin = floor(y[i]);
ymax = ceiling(y[i]);
for (y = ymin; y <= ymax; y++) {
    for (x = xmin ; x <= xmax; x++) {
        alpha = f_bc(x, y) / f_bc(xa, ya);
        beta  = f_ac(x, y) / f_ac(xb, yb);
        gamma = f_ab(x, y) / f_ab(xc, yc);
        if (alpha > 0 && beta > 0 && gamma > 0) {
            color = alpha * a + beta * b + gamma * c; // color of pixel(x,y)
            drawpixel(x, y, color);
        }
    }
}

\(f_{ab}、f_{bc}、f_{ac}\)分别表示直线ab、bc、ac,对应方程:

\[\begin{aligned} f_{ab}(x,y)&=(y_a-y_b)x+(x_b-x_a)y+x_ay_b-x_by_a\\ f_{bc}(x,y)&=(y_b-y_c)x+(x_c-x_b)y+x_by_c-x_cy_b\\ f_{ac}(x,y)&=(y_c-y_a)x+(x_a-x_c)y+x_cy_a-x_ay_c \end{aligned} \]

推导可参见计算机图形:三角形及重心空间

问题:为什么循环体内只测试\(α,β,γ>0\),而不是验证\(\in (0,1)\)?

因为\(α+β+γ=1\),如果3者都>0,那么都位于区间\((0,1)\).

  • 增量法节省计算量

绘制直线时,考虑到相邻像素,有以下关系:

\[\begin{aligned} f(x,y)&=Ax+By+C\\ \implies f(x+1,y)&=f(x,y)+A\\ f(x,y+1)&=f(x,y)+B \end{aligned} \]

如此,只需1次加法,就能求出\(f(x,y+1),f(x+1,y)\),从而减少求\(α.β,γ\)时间.

处理公共边界

如果一个像素中心位于2个三角形的公共边,该如何处理?

有3种策略:

  • 下策:不绘制该像素,但是会在2个三角形之间形成孔洞.

  • 中策:2个三角形都绘制该像素,但如果三角形是透明的,会造成双重着色.

  • 上侧:属于哪个三角形不重要,选择明确即可.

一种简单的选择方法,是找一个屏幕外的点,比如\(p_0(-1,-1)\),通常认为屏幕外的点不在直线上.

\(f_{bc}(\bm{p_0})\cdot f_{bc}(\bm{{a_1}})<0\),表明\(\bm{p_0},\bm{a_1}\)在直线bc不同侧;

\(f_{bc}(\bm{p_0})\cdot f_{bc}(\bm{{a_2}})<0\),表明\(\bm{p_0},\bm{a_2}\)在直线bc同侧;

那么,选择\(△a_2bc\)绘制公共边bc.

img

当\(α=0\)时, \(f_{bc}(x,y)=0\),代表p在bc上;
当\(β=0\)时, \(f_{ac}(x,y)=0\),代表p在ac上;
当\(γ=0\)时, \(f_{ab}(x,y)=0\),代表p在ab上.

算法如下:

// a(xa,ya),b(xb,yb),c(xc,yc) consits of a 2D triangle, including color property
xmin = floor(x[i]);
xmax = ceiling(x[i]);
ymin = floor(y[i]);
ymax = ceiling(y[i]);
p0 = (-1, -1);
f_alpha = f_bc(xa, ya);
f_beta  = f_ac(xb, yb);
f_gamma = f_ab(xc, yc);

for (y = ymin; y <= ymax; y++) {
    for (x = xmin ; x <= xmax; x++) {
        alpha = f_bc(x, y) / f_bc(xa, ya);
        beta  = f_ac(x, y) / f_ac(xb, yb);
        gamma = f_ab(x, y) / f_ab(xc, yc);

        if (alpha >= 0 && belta >= 0 && gamma >= 0 ) {
            if ((alpha > 0 || f_alpha * f_bc(p0.x, p0.y)) 
                && (beta > 0 || f_beta * f_ac(p0.x, p0.y))
                && (gamma > 0 || f_gamma * f_ab(p0.x, p0.y))
            ) {
                color = alpha * a + beta * b + gamma * c; // color of pixel(x,y)
                drawpixel(x, y, color);
            }
        }
    }
}

参考

[1] Marschner S , Shirley P , Ashikhmin M ,et al.Fundamentals of computer graphics, fourth edition[J].A. K. Peters, Ltd. 2015.

标签:bc,插值,bm,像素,绘制,三角形,光栅,图形
From: https://www.cnblogs.com/fortunely/p/18188180

相关文章

  • Python-Tkinter图形化界面设计(详细教程 )
    Python-Tkinter图形化界面设计(详细教程)声明:本篇文章为转载自https://www.jianshu.com/p/91844c5bca78,在原作者的基础上添加目录导航,旨在帮助大家以更高效率进行学习和开发。Python-Tkinter图形化界面设计(详细教程)#一.图形化界面设计的基本理解#当前流行的计算机桌面应用程序......
  • docker快速部署 influxdb+telegraf+grafana 推送主机及docker容器监控数据 并展示图
    简述1、InfluxDBInfluxDB是用Go语言编写的一个开源分布式时序、事件和指标数据库,无需外部依赖。 2、TelegrafTelegraf是一个插件驱动的服务器代理,用于收集和报告指标,并且是TICKStack的第一部分。Telegraf插件可以直接从它运行的系统中获取各种指标,从第三方API中提取指标,甚......
  • debian 12 设置启动界面(文本或图形)
    默认启动界面为图形界面。1.查看启动界面现状:systemctlget-default2.设置启动界面为文本模式:systemctlset-defaultmulti-user.target3.设置启动界面为图形模式:systemctlset-defaultgraphical.target4.重启系统:reboot ......
  • gcov - 标准c/c++代码覆盖率测试工具+lcov - GCC测试覆盖率的前端图形展示工具+gprof
    1、advent-calendar-of-circuits-2020-一个月每天用KiCad设计一个PCB项目GregoryDavill是来自澳大利亚的一个技术牛人,在开源硬件领域非常有名且活跃。他在2020年12月坚持每一天设计一个电路板,用KiCad完成电路设计到PCB的布局布线完成,这便是advent-calendar-of-circuits-......
  • nicegui:Python 图形界面库,简单好用
    前言在现代计算机应用程序开发中,图形用户界面(GUI)是用户与程序交互的重要组成部分。然而,GUI开发往往需要大量的代码和复杂的布局,给开发者带来了一定的挑战。在本篇博文中,将介绍nicegui,它是一个简单易用的图形用户界面库,提供了一种简化GUI开发的方式,使开发者能够更快速地构建吸......
  • nicegui:Python 图形界面库,简单好用
    前言在现代计算机应用程序开发中,图形用户界面(GUI)是用户与程序交互的重要组成部分。然而,GUI开发往往需要大量的代码和复杂的布局,给开发者带来了一定的挑战。在本篇博文中,将介绍nicegui,它是一个简单易用的图形用户界面库,提供了一种简化GUI开发的方式,使开发者能够更快速地构建吸......
  • jmeter无图形界面执行测试并生成报告
    一.命令行:jemeter-n-txxx.jmx-lMMM.jtl-e-oNNN二.命令行参数解释:2.1运行参数-n无图形界面执行-t指定要执行的脚本路径xxx.jmx,必须指定,格式为jmx文件(-txxx.jmx)-l指定运行过程中生成数据文件路径,必须指定,格式为jtl文件,文件名随......
  • VectSharp一个C#轻量级矢量图形库
    VectSharp是一个功能强大的C#库,专门用于创建矢量图形,包括文本,不依赖任何第三方,支持跨平台运行,包括Mac、Windows和Linux。使得开发者可以更容易地在他们的项目中集成矢量图形的生成和处理。https://github.com/arklumpus/VectSharp特点:内置字体:包含了14种标准字体,这些字体......
  • 服务器分层拓扑架构图形化显示工具
    目录服务器分层拓扑架构图形化显示工具---HWLOC下载依赖包安装源码编译安装执行命令示例显示PCI层次结构参考文档服务器分层拓扑架构图形化显示工具---HWLOC 可移植硬件局部(hwloc)软件包提供了现代架构分层拓扑的可移植抽象(跨操作系统、版本、体系结构等),包括NUMA内......
  • esxi服务器进图形化界面配置
    1、先进入网络配置2、选择ip43、选择第三个设置静态网络同时记住ipv4地址:192.168.8.112然后确定4、 选仅主机模式5、6、在物理机直接访问刚才的ipv4地址登录 ......