图形学初识--光栅化直线算法

news2024/11/20 6:18:27

文章目录

  • 什么叫做光栅化?
  • 为什么需要光栅化?
  • 直线的光栅化算法有哪些?
  • Bresemham算法
    • 问题定义:
    • 问题模型简化:
    • 算法核心理解:
    • 算法拓展:
  • 结尾:喜欢的小伙伴可以点点关注+赞哦

什么叫做光栅化?

光栅化(Rasterization)是一种计算机图形学技术,用于将几何图形(如矢量图形、3D模型)转换成由像素或点组成的光栅图像(raster image)。这个过程通常在图形硬件(如显卡)上进行,用于生成最终在屏幕上显示的图像。

上面来自chatGPT,对于有图形学基础的人还是很好理解。

我这里单纯用绘制2D图形的两个案例,用大白话简易解释一下:

(1)给屏幕坐标系中的两个点坐标,如何绘制出以这两个点为首尾的直线?这就是直线光栅化的作用;

(2)给屏幕坐标系中三个点,如何绘制以这三个点为顶点的填充三角形?这就是三角形光栅化的作用;

再次声明,以此类推,这些说辞都是方便理解用的,并不专业!

为什么需要光栅化?

计算机图形通常以矢量形式存储和处理,包括点、线、三角形等基本几何形状。

然而,显示设备(如计算机屏幕、手机屏幕)是基于像素的。这意味着最终显示图像需要将矢量图形转换为像素阵列,光栅化正是这个转换过程。

直线的光栅化算法有哪些?

  • 数值微分法(DDA)
  • Bresenham
  • Wu

使用场景比较:

  • DDA算法:适合简单的直线绘制,计算过程容易理解,但由于使用浮点数,效率较低
  • Bresenham算法:效率高,使用整数运算,适用于大多数应用场景,尤其是实时图形渲染
  • Wu算法:用于生成平滑的抗锯齿直线,适合需要高质量图像的应用

咱们重点讲述Bresemham算法!也是最常用的!

Bresemham算法

问题定义:

已知两个点 p 1 ( x 1 , y 1 ) , p 2 ( x 2 , y 2 ) p1(x_1,y_1),p2(x_2,y_2) p1(x1,y1),p2(x2,y2) 请在屏幕像素空间绘制一条直线。

问题模型简化:

最简单的问题模型满足如下条件:

  • x 1 < x 2 x_1 < x_2 x1<x2
  • y 1 < y 2 y_1 < y_2 y1<y2
  • 直线表达式: $ y = kx + b$​
  • 直线斜率 k k k 满足: 0 < k < 1 0 < k < 1 0<k<1

概念图如下:

在这里插入图片描述

算法核心理解:

顶级理解: 假设当前直线已经通过点 ( x i , y i ) (x_i,y_i) (xi,yi) ,那么当 x i − > x i + 1 x_i -> x_i + 1 xi>xi+1 ,此时的 y i y_i yi 如何变动呢?如下图所示:

在这里插入图片描述

其实 y i y_i yi 的变动只有两个选择,要么 y i − > y i y_i -> y_i yi>yi 保持不变,要么 y i y_i yi -> y i + 1 y_{i + 1} yi+1 向上增加一个像素。

这两种情况说人话:一个向正东移动、一个向东北方移动!

问题来了: 那么何时朝正东移动,何时朝东北移动,依据什么呢?如下图所示:

在这里插入图片描述

感官上来看: 依据直线是朝下倾斜一点,还是朝上倾斜一点。

数学表达来看: 根据上图的 d 0 d_0 d0 d 1 d_1 d1 谁更大( d 0 d_0 d0 更大,表明向下倾斜,反之向上)

让我们开始步入数学公式的殿堂:
d 0 = y i + 1 − k ( x i + 1 ) − b d 1 = k ( x i + 1 ) + b − y i \begin{aligned} d_0 &= y_i + 1 - k(x_i + 1) - b\\ d_1 &= k(x_i + 1) + b - y_i \end{aligned} d0d1=yi+1k(xi+1)b=k(xi+1)+byi

既然要比较 d 0 d_0 d0 d 1 d_1 d1 的大小,咱们就用 d 1 d_1 d1 - d 0 d_0 d0​ :
d 1 − d 0 = k ( x i + 1 ) + b − y i − [ y i + 1 − k ( x i + 1 ) − b ] = 2 k ( x i + 1 ) − 2 y i − 1 + 2 b \begin{aligned} d_1 - d_0 &= k(x_i + 1) + b - y_i - [ y_i + 1 - k(x_i + 1) - b ]\\ &= 2k(x_i + 1) - 2y_i - 1 + 2b \end{aligned} d1d0=k(xi+1)+byi[yi+1k(xi+1)b]=2k(xi+1)2yi1+2b

由于模型简化,根据已知条件:
k = y 2 − y 1 x 2 − x 1 Δ x = x 2 − x 1 > 0 \begin{aligned} k &= \frac{y_2 - y_1}{x_2 - x_1}\\ \Delta x &= x_2 - x_1 > 0 \end{aligned} kΔx=x2x1y2y1=x2x1>0

所以,等式两边同乘 Δ x \Delta x Δx ,表达式正负号不会发生变化,记 p i = Δ x ( d 1 − d 0 ) p_i = \Delta x(d_1 - d_0) pi=Δx(d1d0)

p i = Δ x ( d 1 − d 0 ) = Δ x ∗ [ 2 k ( x i + 1 ) − 2 y i − 1 + 2 b ] = Δ x ∗ [ 2 ∗ y 2 − y 1 x 2 − x 1 ∗ ( x i + 1 ) − 2 y i − 1 + 2 b ] = Δ x ∗ [ 2 ∗ Δ y Δ x ∗ ( x i + 1 ) − 2 y i − 1 + 2 b ] = 2 Δ y ∗ ( x i + 1 ) + Δ x ( − 2 y i − 1 + 2 b ) = 2 Δ y ∗ ( x i + 1 ) − Δ x ( 2 y i + 1 − 2 b ) = 2 Δ y ∗ x i − 2 Δ x y i + [ 2 Δ y + ( 2 b − 1 ) Δ x ] \begin{aligned} p_i &= \Delta x(d_1 - d_0)\\ &= \Delta x * [2k(x_i + 1) - 2y_i - 1 + 2b]\\ &= \Delta x * [2* \frac{y_2 - y_1}{x_2 - x_1} * (x_i + 1) - 2y_i - 1 + 2b]\\ &= \Delta x * [2* \frac{\Delta y}{\Delta x} * (x_i + 1) - 2y_i - 1 + 2b]\\ &= 2\Delta y*(x_i + 1) + \Delta x(-2y_i - 1 + 2b)\\ &= 2\Delta y*(x_i + 1) - \Delta x(2y_i + 1 - 2b)\\ &= 2\Delta y*x_i - 2\Delta xy_i + [2\Delta y + (2b-1)\Delta x] \end{aligned} pi=Δx(d1d0)=Δx[2k(xi+1)2yi1+2b]=Δx[2x2x1y2y1(xi+1)2yi1+2b]=Δx[2ΔxΔy(xi+1)2yi1+2b]=y(xi+1)+Δx(2yi1+2b)=y(xi+1)Δx(2yi+12b)=yxixyi+[y+(2b1)Δx]

推导到这,咱们观察一下: Δ y \Delta y Δy已知、 Δ x \Delta x Δx已知,所以 p i p_i pi 的值就取决于 x i x_i xi y i y_i yi、b的值

因为咱们发现出现了b,b很有可能是浮点数,是不满足咱们这个算法的要求的,于是伟大的思路,要求我们尝试构造递推关系式,来进行对b消去!

迭代模型:
p i = 2 Δ y x i − 2 Δ x y i + [ 2 Δ y + ( 2 b − 1 ) Δ x ] p i + 1 = 2 Δ y ( x i + 1 ) − 2 Δ x y i + 1 + [ 2 Δ y + ( 2 b − 1 ) Δ x ] p i + 1 − p i = 2 Δ y − 2 Δ x ( y i + 1 − y i ) \begin{aligned} p_i &= 2\Delta yx_i - 2\Delta xy_i + [2\Delta y + (2b-1)\Delta x]\\ p_{i+1} &= 2\Delta y(x_i+1) - 2\Delta xy_{i+1} + [2\Delta y + (2b-1)\Delta x]\\ p_{i+1} - p_i &= 2\Delta y - 2\Delta x(y_{i+1} - y_i) \end{aligned} pipi+1pi+1pi=yxixyi+[y+(2b1)Δx]=y(xi+1)xyi+1+[y+(2b1)Δx]=yx(yi+1yi)

惊奇的发现,b被消去了,大功告成,这是我们发现:计算 p i + 1 p_{i+1} pi+1 的值,只和 p i p_i pi 以及 y i + 1 y_{i+1} yi+1 y i y_i yi 有关系!

所以咱们需要单独计算 p 1 p_1 p1,咱们就用这个公式: p i = 2 Δ y x i − 2 Δ x y i + [ 2 Δ y + ( 2 b − 1 ) Δ x ] p_i = 2\Delta yx_i - 2\Delta xy_i + [2\Delta y + (2b-1)\Delta x] pi=yxixyi+[y+(2b1)Δx]

i i i = 1,带入 ( x 1 , k x 1 + b ) (x_1, kx_1 + b) (x1,kx1+b)

咱们得到:
p 1 = 2 Δ y x i − 2 Δ x y i + [ 2 Δ y + ( 2 b − 1 ) Δ x ] = 2 Δ y x 1 − 2 Δ x ( k x 1 + b ) + [ 2 Δ y + ( 2 b − 1 ) Δ x ] = 2 Δ y x 1 − 2 Δ x ( Δ y Δ x x 1 + b ) + [ 2 Δ y + ( 2 b − 1 ) Δ x ] = 2 Δ y x 1 − 2 Δ y x 1 − 2 b Δ x + 2 Δ y + 2 b Δ x − Δ x ) = 2 Δ y − Δ x \begin{aligned} p_1 &= 2\Delta yx_i - 2\Delta xy_i + [2\Delta y + (2b-1)\Delta x]\\ &=2\Delta yx_1 - 2\Delta x(kx_1+b) + [2\Delta y + (2b-1)\Delta x]\\ &=2\Delta yx_1 - 2\Delta x(\frac{\Delta y}{\Delta x}x_1+b) + [2\Delta y + (2b-1)\Delta x]\\ &=2\Delta yx_1 - 2\Delta yx_1-2b\Delta x + 2\Delta y + 2b\Delta x-\Delta x)\\ &=2\Delta y - \Delta x \end{aligned} p1=yxixyi+[y+(2b1)Δx]=yx1x(kx1+b)+[y+(2b1)Δx]=yx1x(ΔxΔyx1+b)+[y+(2b1)Δx]=yx1yx12bΔx+y+2bΔxΔx)=yΔx

重申目标:

我们需要通过 p i p_i pi 的正负值,从而决定 d 1 d_1 d1 d 0 d_0 d0 谁大谁小,从而决定他是往东北方向移动,还是往正东方向移动。

数学表达如下:
y i + 1 = { y i , p i < = 0 即 d 1 < d 0 y i + 1 , p i > 0 即 d 1 > d 0 y_{i+1}=\begin{cases} y_i, & p_i<=0 即d_1 < d_0 \\ y_i + 1, & p_i>0 即d_1 > d_0 \end{cases} yi+1={yi,yi+1,pi<=0d1<d0pi>0d1>d0

所以我们发现: y i + 1 y_{i+1} yi+1 其实是由 p i p_i pi 决定的。咱们已知 p 1 p_1 p1 自然可以求出 y 2 y_2 y2,又根据递推关系式:
p i + 1 − p i = 2 Δ y − 2 Δ x ( y i + 1 − y i ) p_{i+1} - p_i = 2\Delta y - 2\Delta x(y_{i+1} - y_i) pi+1pi=yx(yi+1yi)

自然而然可以迭代计算,求出: p 2 p_2 p2 y 3 y_3 y3 p 3 p_3 p3 y 4 y_4 y4、… p k p_k pk y k + 1 y_{k+1} yk+1,直到所有!

算法拓展:

前面咱们由于为了推导公式,所以简化了模型,假设了以下条件:

  • x 1 < x 2 x_1 < x_2 x1<x2
  • y 1 < y 2 y_1 < y_2 y1<y2
  • 直线表达式: $ y = kx + b$​
  • 直线斜率 k k k 满足: 0 < k < 1 0 < k < 1 0<k<1

但是实际在一个二维平面上,一条直线有八种情况:

  • x 1 < x 2 x_1 < x_2 x1<x2 y 1 < y 2 y_1 < y_2 y1<y2 0 < k > 1 0< k > 1 0<k>1

  • x 1 < x 2 x_1 < x_2 x1<x2 y 1 < y 2 y_1 < y_2 y1<y2 k > 1 k > 1 k>1

  • x 1 > x 2 x_1 > x_2 x1>x2 y 1 < y 2 y_1 < y_2 y1<y2 0 < k > 1 0< k > 1 0<k>1

  • x 1 > x 2 x_1 > x_2 x1>x2 y 1 < y 2 y_1 < y_2 y1<y2 k > 1 k > 1 k>1

  • x 1 < x 2 x_1 < x_2 x1<x2 y 1 > y 2 y_1 > y_2 y1>y2 0 < k > 1 0< k > 1 0<k>1

  • x 1 < x 2 x_1 < x_2 x1<x2 y 1 > y 2 y_1 > y_2 y1>y2 k > 1 k > 1 k>1

  • x 1 > x 2 x_1 > x_2 x1>x2 y 1 > y 2 y_1 > y_2 y1>y2 0 < k > 1 0< k > 1 0<k>1

  • x 1 > x 2 x_1 > x_2 x1>x2 y 1 > y 2 y_1 > y_2 y1>y2 k > 1 k > 1 k>1

如下图,这八种情况,其实就对应八个方位:

在这里插入图片描述

计算的情形其实也类似,只需要将目标点转换到咱们简化模型状态,然后最后结果再转换回去就可以!

比如:x符号取反、y符号取反、xy互换等等,就不多赘述了!

结尾:喜欢的小伙伴可以点点关注+赞哦

希望对各位小伙伴能够有所帮助哦, 我是航火火,火一般的男人!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1686995.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】手把手学会数组的使用

数组的基本用法 创建数组 基本语法&#xff1a; // 动态初始化 数据类型 [] 数组名称 new 数据类型 [] { 初始化数据 }; // 静态初始化 数据类型 [] 数组名称 { 初始化数据 }; 代码示例&#xff1a; int[] array1 {1,2,3,4,5};int[] array2 new int[]…

如何在OpenHarmony上使用SeetaFace2人脸识别库?

简介 相信大部分同学们都已了解或接触过OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;了&#xff0c;但你一定没在OpenHarmony上实现过人脸识别功能&#xff0c;跟着本文带你快速在OpenHarmony标准设备上基于SeetaFace2和OpenCV实现人脸识别。 项目效…

c++ 实现 梯度下降线性回归模型

理论与python实现部分 3.1. 线性回归 — 动手学深度学习 2.0.0 documentation c代码 没能力实现反向传播求梯度&#xff0c;只能自己手动算导数了 #include <bits/stdc.h> #include <time.h> using namespace std;//y_hat X * W b // linreg 函数&#xff1a…

9 个适用于小型企业的顶级API管理解决方案

应用程序接口管理解决方案可帮助各种规模的企业开发、部署和管理其应用程序接口&#xff0c;并实现收入最大化。 建立 API 的组织和开发人员可能会被整个 API 生命周期中需要完成的大量任务压得喘不过气来。从规划和构建到部署、维护和货币化&#xff1b;这是一项具有挑战性的工…

【计算机网络原理】对传输层TCP协议的重点知识的总结

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

7.从0做一个vue键盘组件

文章目录 1. 从0做一个键盘组件1.1. 最终效果1.2. 分析1.3. 实现1.4. 如何引用 1. 从0做一个键盘组件 首先是why的问题&#xff1a;为什么需要做键盘组件&#xff1f; 我们目前可知的场景&#xff1a; 在新增账单的时候&#xff0c;需要用到键盘在比如从账单列表页&#xff…

2024年 电工杯 (B题)大学生数学建模挑战赛 | 大学生平衡膳食食谱的优化设计 | 数学建模完整代码解析

DeepVisionary 每日深度学习前沿科技推送&顶会论文&数学建模与科技信息前沿资讯分享&#xff0c;与你一起了解前沿科技知识&#xff01; 本次DeepVisionary带来的是电工杯的详细解读&#xff1a; 完整内容可以在文章末尾全文免费领取&阅读&#xff01; 问题1&…

【Python自动化测试】:Unittest单元测试与HTMLTestRunner自动生成测试用例的好帮手

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 文章目录 &#x1f525;前言&#x1f680;unittest编写测试用例&#x1f680;unittest测…

49 序列化和反序列化

本章重点 理解应用层的作用&#xff0c;初识http协议 理解传输层的作用&#xff0c;深入理解tcp的各项特性和机制 对整个tcp/ip协议有系统的理解 对tcp/ip协议体系下的其他重要协议和技术有一定的了解 学会使用一些网络问题的工具和方法 目录 1.应用层 2.协议概念 3. 网络计…

awesome-ai4s 现已开源!超全 AI for Science 学术论文与数据资源汇总,持续更新ing

2018 年中国科学院院士鄂维南提出「AI for Science」概念&#xff0c;强调利用 AI 学习科学原理、创造科学模型来解决实际问题。同年&#xff0c;AlphaFold 崭露头角&#xff0c;从 43 种蛋白质中准确预测出了 25 种蛋白质结构。2021 年&#xff0c;AlphaFold 2 开源并预测了 9…

缓存降级

当Redis缓存出现问题或者无法正常工作时,需要有一种应对措施,避免直接访问数据库而导致整个系统瘫痪。缓存降级就是这样一种机制。 主要的缓存降级策略包括: 本地缓存降级 当Redis缓存不可用时,可以先尝试使用本地进程内缓存,如Guava Cache或Caffeine等。这样可以减少对Redis…

OpenLayers中实现对ImageStatic图层的扩展以支持平铺WrapX功能

地图平铺技术概述 地图平铺&#xff08;Tiling&#xff09;是一种将大尺寸地图数据分割成小块&#xff08;瓦片&#xff09;的技术&#xff0c;这在地图服务中非常常见。它使得地图数据能高效加载和展示&#xff0c;尤其适合网络环境。通过仅加载当前视图窗口所需的地图瓦片&a…

Qt官方示例---opengl

文件相对路径&#xff1a;Examples\Qt-5.9.1\opengl 2dpainting cube computegles31 contextinfo hellogl2 hellowindow paintedwindow qopenglwidget qopenglwindow textures threadedqopenglwidget

Rabbitmq 搭建使用案例 [附源码]

Rabbitmq 搭建使用案例 文章目录 RabbitMQ搭建docker 代码golang生产者消费者 可视化消费进度 RabbitMQ搭建 docker docker run -d --hostname rabbitmq --name rabbitmq -e RABBITMQ_DEFAULT_USERadmin -e RABBITMQ_DEFAULT_PASSadmin -e RABBITMQ_DEFAULT_VHOSTmy_vhost -e…

重组蛋白表达系统优缺点对比|卡梅德生物

重组蛋白是现代生物技术中不可或缺的一部分&#xff0c;它们广泛应用于药物开发、研究工具和工业酶的生产。根据目标蛋白的特性和所需的修饰&#xff0c;可以选择不同的表达系统。下文罗列一下四个主要蛋白表达系统的优缺点&#xff1a; 1. 原核表达系统&#xff08;如大肠杆菌…

【QT实战】汇总导航

✨Welcome 大家好&#xff0c;欢迎来到瑾芳玉洁的博客&#xff01; &#x1f611;励志开源分享诗和代码&#xff0c;三餐却无汤&#xff0c;顿顿都被噎。 &#x1f62d;有幸结识那个值得被认真、被珍惜、被捧在手掌心的女孩&#xff0c;不出意外被敷衍、被唾弃、被埋在了垃圾堆…

深度学习之基于Tensorflow卷积神经网络(CNN)实现猫狗识别

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 在人工智能和深度学习的热潮中&#xff0c;图像识别是一个备受关注的领域。猫狗识别作为图像识…

Milvus的内存索引

简介&#xff1a; 这篇文章主要介绍milvus支持的各种内存索引&#xff0c;以及它们最适用的场景&#xff0c;还有用户为了获得更好的搜索性能可以配置的参数。 索引是有效组织数据的过程&#xff0c;它的主要角色是在大的数据集中显著的加速耗时的查询从而有效的进行相似搜索…

【制作100个unity游戏之28】花半天时间用unity复刻童年4399经典小游戏《黄金矿工》(附带项目源码)

最终效果 文章目录 最终效果前言素材模拟绳子钩子来回摆动发射回收钩子方法发射钩子回收钩子勾取物品随机生成物品其他源码完结 前言 在游戏发展史上&#xff0c;有些游戏以其简单而耐玩的特性&#xff0c;深深地烙印在了玩家的记忆中。《黄金矿工》就是其中之一&#xff0c;它…