图形学初识--纹理采样和Wrap方式

news2024/11/17 13:51:19

文章目录

  • 前言
  • 正文
    • 1、为什么需要纹理采样?
    • 2、什么是纹理采样?
    • 3、如何进行纹理采样?
        • (1)假设绘制区域为矩形
        • (2)假设绘制区域为三角形
    • 4、什么是纹理的Wrap方式?
    • 5、有哪些纹理的Wrap方式?
        • (1)Repeat
        • (2)Mirror_Repeat
        • (3)Clamp_To_Edge
        • (4)Clamp_To_Border
    • 6、如何实现纹理的Wrap方式?
        • (1)Repeat
        • (2)Mirror_Repeat
  • 结尾:喜欢的小伙伴可以点点关注+赞哦

前言

上节讲述了双线性插值算法,虽然也有提到主要应用的点就是纹理采样,但是对于这一块有些小小白可能还不了解,所以这一节补充一下纹理采样的内容!

请叫我贴心航火火!梦想为小白而生!

正文

1、为什么需要纹理采样?

想象一个场景: 如果有这么一个需求,需要在屏幕的一块400x400目标区域显示一张图片,正好这张图片的尺寸也是400x400像素,怎么做?

答: 啥都不需要做,是的,根本不需要做什么处理,直接一一对应像素显示即可!

但是,实际情况中,往往几乎不可能这么巧合的一一对应,要么纹理图片过大,要么纹理图片过小,没法一一对应,怎么办呢?

答: 通过引入一种机制,进行等比例对应,这就是uv坐标的由来,它本质上就表示百分比,一般地,uv坐标的标准取值范围是:0.0 - 1.0。

举个纹理图片过小的例子,如下图: 当我们需要绘制 400x400 窗口区域图片纹理大小是 200x200,如果要在窗口 (20, 20) 位置绘制,那么我们就相当于取纹理图片的 ( 20 / 400 , 20 / 400 ) = ( 0.05 , 0.05 ) (20 / 400 , 20 / 400) = (0.05, 0.05) (20/400,20/400)=(0.05,0.05) 比例位置的像素数据,也就是 ( 0.05 ∗ 200 , 0.05 ∗ 200 ) = ( 10 , 10 ) (0.05 * 200,0.05 * 200) = (10, 10) (0.052000.05200)=(10,10) 位置的数据!这里的 ( 0.05 , 0.05 ) (0.05, 0.05) (0.05,0.05)​ 其实就是uv坐标!

在这里插入图片描述

这里引申一下,由于上述举的例子是绘制区域大,纹理图片小。所以自然而然会存在多个绘制区域对应一个纹理像素位置的情况。这时候就应用到上节的内容。是直接采用最邻近的采样方式,还是双线性插值的方式,来缓解像素化的情况,取决于自身的需求!

2、什么是纹理采样?

在屏幕上某一像素绘制时,根据像素所在位置,去图片上寻找对应像素值的过程,这个过程就是纹理采样!如下图所示:

在这里插入图片描述

3、如何进行纹理采样?

其实需要采样的情形无非就是两种情况,上面也说了!纹理太大或太大。这里咱们只说纹理太小的情况,需要用到上一节的双线性插值的知识。

纹理太大的时,解决的思路无非就是让纹理变小,变到一个最适合绘制窗口的大小。如果想要适应各种绘制窗口大小,就需要利用MipMap的知识,后面章节有空的话,会把这部分给补上哦,童鞋们!

(1)假设绘制区域为矩形

需要在一个分辨率为 screen_width X screen_height 的矩形窗口区域绘制一张图片,这张图片分辨率为picture_width X picture_height,假设绘制区域左下角的uv坐标为 ( u x 0 , u y 0 ) (u_{x0}, u_{y0}) (ux0,uy0),右上角的uv坐标为 ( u x 1 , u y 1 ) (u_{x1}, u_{y1}) (ux1,uy1) ,且满足 0 = < u x 0 、 u x 1 、 u y 0 、 u y 1 < = 1.0 0 =< u_{x0}、u_{x1}、u_{y0}、u_{y1} <= 1.0 0=<ux0ux1uy0uy1<=1.0 ,则对于任何绘制区域坐标为 ( x , y ) (x,y) (x,y)​ 的uv坐标为
u x = x s c r e e n _ w i d t h ∗ u x 1 + ( 1 − x s c r e e n _ w i d t h ) ∗ u x 0 u y = y s c r e e n _ h e i g h t ∗ u y 1 + ( 1 − y s c r e e n _ h e i g h t ) ∗ u y 1 u_x = \frac{x}{screen\_width} *u_{x1} + (1 - \frac{x}{screen\_width}) * u_{x0}\\ u_y = \frac{y}{screen\_height} *u_{y1} + (1 - \frac{y}{screen\_height}) * u_{y1}\\ ux=screen_widthxux1+(1screen_widthx)ux0uy=screen_heightyuy1+(1screen_heighty)uy1
既然已经有了绘制区域每一个位置的uv坐标,咱么只需要根据uv坐标,去纹理图片进行采样像素值即可,至于采取何种采样方法,可以参考上一片文章,既可以采用最邻近取整的方式,也可以采取双线性插值的方式!这里根据用户需求,自行决定,不多赘述!

(2)假设绘制区域为三角形

给定三个顶点 p 1 = ( x 1 , y 1 ) 、 p 2 = ( x 2 , y 2 ) 、 p 3 = ( x 3 , y 3 ) p1 = (x_1,y_1)、p2 = (x_2,y_2)、p3 = (x_3,y_3) p1=(x1,y1)p2=(x2,y2)p3=(x3,y3) 并且给定三个顶点的uv坐标分别为 u 1 = ( u x 1 , u y 1 ) , u 2 = ( u x 2 , u y 2 ) , u 3 = ( u x 3 , u y 3 ) u_1 = (u_{x1},u_{y1}),u_2 = (u_{x2},u_{y2}),u_3 = (u_{x3},u_{y3}) u1=(ux1,uy1),u2=(ux2,uy2),u3=(ux3,uy3),如何得知三角形内每一个顶点 p ( x , y ) p(x,y) p(x,y) 的uv坐标呢?

这时候重心坐标插值公式,又派上用上了,之前的章节已经介绍过,就不过多阐释了!

这时候 每一个三角形内的顶点 p ( x , y ) p(x,y) p(x,y) 的uv坐标 u p = α u 1 + β u 2 + γ u 3 u_p = \alpha u_1 + \beta u_2 +\gamma u_3 up=αu1+βu2+γu3 ,三个系数根据重心坐标公式即可算得!这时候同样,根据uv坐标去纹理图片进行采样像素值即可!

简单给个参考图:

在这里插入图片描述

4、什么是纹理的Wrap方式?

虽然标准规定的uv坐标范围为: ( 0.0 , 1.0 ) (0.0, 1.0) (0.0,1.0) ,但是如果越界了,对应的uv坐标的采样值如何取呢?这个问题的答案就是纹理的Wrap属性!

5、有哪些纹理的Wrap方式?

常见的Wrap方式有四种:

  • Repeat
  • Mirror_Repeat
  • Clamp_To_Edge
  • Clamp_To_Border

这里分别简单介绍并给出示例图:

(1)Repeat

超出部分,不断循环重复

在这里插入图片描述

(2)Mirror_Repeat

超出部分,不断循环镜像重复

在这里插入图片描述

(3)Clamp_To_Edge

纹理坐标会被约束在0到1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果

在这里插入图片描述

(4)Clamp_To_Border

超出的坐标为用户指定的边缘颜色

在这里插入图片描述

6、如何实现纹理的Wrap方式?

上述的第(3)和第(4)很好理解,咱们就讨论下第(1)种和第(2)种的计算方式吧!

(1)Repeat

计算公式:
记 f ( x ) 函数表示取浮点数 x 的小数部分 , 则坐标 ( u x , u y ) 的最终坐标为 u x = f (   f ( u x ) + 1   ) u y = f (   f ( u y ) + 1   ) 记f(x)函数表示取浮点数x的小数部分,则坐标(u_x, u_y)的最终坐标为\\ u_x = f(\ f(u_x) + 1\ )\\ u_y = f(\ f(u_y) + 1\ ) f(x)函数表示取浮点数x的小数部分,则坐标(ux,uy)的最终坐标为ux=f( f(ux)+1 )uy=f( f(uy)+1 )

举例佐证:

  • ( 1.2 , 2.2 ) = > (   f ( 0.2 + 1 ) , f ( 0.2 + 1 )   ) = > ( 0.2 , 0.2 ) (1.2, 2.2) => (\ f(0.2 + 1),f(0.2 + 1)\ ) => (0.2, 0.2) (1.2,2.2)=>( f(0.2+1),f(0.2+1) )=>(0.2,0.2) ok

  • ( 0.3 , 0.8 ) = > (   f ( 0.3 + 1 ) , f ( 0.8 + 1 )   ) = > ( 0.3 , 0.8 ) (0.3, 0.8) => (\ f(0.3 + 1),f(0.8 + 1)\ ) => (0.3, 0.8) (0.3,0.8)=>( f(0.3+1),f(0.8+1) )=>(0.3,0.8) ok

  • ( − 0.5 , − 2.2 ) = > (   f ( − 0.5 + 1 ) , f ( − 0.2 + 1 )   ) = > ( 0.5 , 0.8 ) (-0.5, -2.2) => (\ f(-0.5 + 1),f(-0.2 + 1)\ ) => (0.5, 0.8) (0.5,2.2)=>( f(0.5+1),f(0.2+1) )=>(0.5,0.8) ok

(2)Mirror_Repeat

计算公式:
记 f ( x ) 函数表示取浮点数 x 的小数部分 , 则坐标 ( u x , u y ) 的最终坐标为 u x = 1 − f (   f ( u x ) + 1   ) u y = 1 − f (   f ( u y ) + 1   ) 记f(x)函数表示取浮点数x的小数部分,则坐标(u_x, u_y)的最终坐标为\\ u_x = 1 - f(\ f(u_x) + 1\ )\\ u_y = 1 - f(\ f(u_y) + 1\ ) f(x)函数表示取浮点数x的小数部分,则坐标(ux,uy)的最终坐标为ux=1f( f(ux)+1 )uy=1f( f(uy)+1 )

举例佐证:

  • ( 1.2 , 2.2 ) = > (   1 − f ( 0.2 + 1 ) , 1 − f ( 0.2 + 1 )   ) = > ( 1 − 0.2 , 1 − 0.2 ) = > ( 0.8 , 0.8 ) (1.2, 2.2) => (\ 1 - f(0.2 + 1),1 - f(0.2 + 1)\ ) => (1 - 0.2, 1 - 0.2) => (0.8,0.8) (1.2,2.2)=>( 1f(0.2+1),1f(0.2+1) )=>(10.2,10.2)=>(0.8,0.8) ok
  • ( 0.3 , 0.8 ) = > (   1 − f ( 0.3 + 1 ) , 1 − f ( 0.8 + 1 )   ) = > ( 1 − 0.3 , 1 − 0.8 ) = > ( 0.7 , 0.2 ) (0.3, 0.8) => (\ 1 - f(0.3 + 1),1 - f(0.8 + 1)\ ) => (1 - 0.3, 1 - 0.8) => (0.7, 0.2) (0.3,0.8)=>( 1f(0.3+1),1f(0.8+1) )=>(10.3,10.8)=>(0.7,0.2) ok
  • ( − 0.5 , − 2.2 ) = > (   1 − f ( − 0.5 + 1 ) , 1 − f ( − 0.2 + 1 )   ) = > ( 1 − 0.5 , 1 − 0.8 ) = > ( 0.5 , 0.2 ) (-0.5, -2.2) => (\ 1 - f(-0.5 + 1),1 - f(-0.2 + 1)\ ) => (1 - 0.5, 1 - 0.8) => (0.5, 0.2) (0.5,2.2)=>( 1f(0.5+1),1f(0.2+1) )=>(10.5,10.8)=>(0.5,0.2) ok

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

希望对各位小伙伴能够有所帮助哦,永远在学习的道路上伴你而行, 我是航火火,火一般的男人!

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

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

相关文章

强大友好的Nginx扩展:VeryNginx

VeryNginx&#xff1a; 简化Web管理&#xff0c;增强网站防御- 精选真开源&#xff0c;释放新价值。 概览 VeryNginx是一个基于lua-nginx-module&#xff08;openresty&#xff09;的高效、友好的Nginx版本&#xff0c;专为满足现代Web应用的需求而设计。它不仅提供了强大的We…

Java | Leetcode Java题解之第115题不同的子序列

题目&#xff1a; 题解&#xff1a; class Solution {public int numDistinct(String s, String t) {int m s.length(), n t.length();if (m < n) {return 0;}int[][] dp new int[m 1][n 1];for (int i 0; i < m; i) {dp[i][n] 1;}for (int i m - 1; i > 0; …

K-means聚类模型入门介绍

K-means聚类是一种无监督学习方法&#xff0c;广泛应用于数据挖掘、机器学习和模式识别等领域&#xff0c;用于将数据集划分为K个簇&#xff08;cluster&#xff09;&#xff0c;其中每个簇的数据具有相似的特征。其基本思想是通过迭代寻找使簇内点间距离平方和最小的簇划分方式…

【Java SE】超详细讲解String类(上)

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 初步认识String2. String类的常用方法2.1 字符串构造2.2 String对象比较2.2.1 比较是否引用同一个对象2.2…

创新实训2024.05.28日志:记忆化机制、基于MTPE与CoT技术的混合LLM对话机制

1. 带有记忆的会话 1.1. 查询会话历史记录 在利用大模型自身能力进行对话与解答时&#xff0c;最好对用户当前会话的历史记录进行还原&#xff0c;大模型能够更好地联系上下文进行解答。 在langchain chat chat的chat函数中&#xff0c;通过实现langchain框架提供的ChatMemo…

XGIS引擎上线曲折历史

演示地址&#xff1a;threelab首页 其实在一年前甚至更早&#xff0c;已经完整了初版的XGIS三维引擎开发&#xff0c;完成了基本的操作。 但是很多原因导致我一直没有上线&#xff0c;也不是没有上线&#xff0c;上线了&#xff0c;又下掉了。总感觉自己写的欠缺&#xff0c;或…

Easy-laser激光对中仪维修D505激光测平仪维修

Easylaser激光对中仪多应用于风力发电业的塔架、机架、轮毂、偏航轴承和变桨轴承的几何指标测量中。此系列常见维修型号包括D450&#xff1b;D480&#xff1b;D505&#xff1b;D525&#xff1b;D550等。 Easy-Laser对中仪维修注意事项&#xff1a; 测量功能包括&#xff1a; …

虚拟化技术 分布式资源调度

一、实验内容 实现分布式资源调度 二、实验主要仪器设备及材料 安装有64位Windows操作系统的台式电脑或笔记本电脑&#xff0c;建议4C8G或以上配置已安装VMware Workstation Pro已安装Windows Server 2008 R2 x64已安装vCenter Server 三、实验步骤 将主机esxi1和esxi2加入…

JVM-之GC日志

一、 开启gc 日志 在项目中开启GC 日志打印后会查看gc 日志如下 nohup java -Xms768m -Xmx768m -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath./dumplog/dumplog.log -Xloggc:./dumplog/gc.log -XX:PrintGCDetails -XX:PrintGCDateStamps -XX:PrintHeapAtGC -jar xxxx…

小易大数据:大数据报告查询领域的黑马,这些优势让你无法忽视!

随着大数据技术被运用到各行各业&#xff0c;风控领域也不例外&#xff0c;形成了基于大数据技术的大数据信用&#xff0c;也就是我们常说的大数据报告或者网贷大数据&#xff0c;在众多的查询平台中&#xff0c;小易大数据平台在市面上是比较受欢迎的&#xff0c;那在小易平台…

使用华为快传同步文件至电脑

使用华为快传同步文件至电脑&#xff0c;电脑端未发现设备解决办法 1、手机和电脑连同一网络 2、打开手机华为分享&#xff0c;打开电脑网络 3、网络中找到设备&#xff0c;输入账户密码进行连接&#xff08;未找到设备往下继续看&#xff09; 未找到设备解决办法&#xff1…

电脑如何在网页上下载视频 浏览器如何下载网页视频

对于现代职场人士而言&#xff0c;在日常生活中难免需要下载各种短视频&#xff0c;IDM下载加速器可以轻松获取抖音、快手等平台的无水印短视频文件。 Internet Download Manager&#xff0c;简称IDM。功能强大的网络下载器。您不需要多余的操作&#xff0c;IDM 能捕获您的下载…

阿里云获取nginx头部

k8s 配置 可以修改kube-system/nginx-configuration configmap的方式&#xff0c; compute-full-forwarded-for: “true” forwarded-for-header: “X-Forwarded-For” use-forwarded-headers: “true” https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-g…

Day01-01-git

Day01-01-git Content List0. 运维发展过程1. ci-cd-co基础1.1 软件的生命周期1&#xff09;软件的声明周期&#xff1a;软件从0-->1-->0过程2&#xff09;ci/cd3&#xff09;Devops4) 小结 1.2 什么是环境1.3 什么是代码部署1.4 代码发布方式 3. DevSecOpt之Git极速入门…

INTERCONNECT 中使用库中器件制作一个损耗为 3 dB /m 的直波导

INTERCONNECT 中使用库中器件制作一个损耗为 3 dB /m 的直波导 正文 正文 首先&#xff0c;插入以下器件并连接。 其次&#xff0c;设置直波导 WGD_1 的器件参数&#xff0c;如下图所示&#xff1a; 运行仿真&#xff0c;在 ONA 中查看 gain 值。 可以看到&#xff0c;对应…

C++入门——日期类的实现

前言 生活中&#xff0c;我们时不时会遇到算天数的问题&#xff1a;高考倒计时、考研倒计时、过年倒计时...... 想解决这些问题无非就是实现一个年月日的计算器&#xff0c;那要怎么来实现呢&#xff1f; 下面就让我们来探究一下。 1.了解日期计算器的需求 1.1 表面需求 …

Java实现链表

链表 前言一、链表的概念及结构二、链表的分类三、链表的实现无头单向非循环链表实现无头双向链表实现具体代码 四、链表习题五、顺序表和链表的区别 前言 推荐一个网站给想要了解或者学习人工智能知识的读者&#xff0c;这个网站里内容讲解通俗易懂且风趣幽默&#xff0c;对我…

Linux shell编程学习笔记50:who命令

0 前言 2024年的网络安全检查又开始了&#xff0c;对于使用基于Linux的国产电脑&#xff0c;我们可以编写一个脚本来收集系统的有关信息。比如&#xff0c;我们可以使用who命令来收集当前已登陆系统的用户信息&#xff0c;当前运行级别等信息。 1. who命令 的功能、格式和选项…

再论任何图≌自己这一几何最最起码常识推翻平面公理

黄小宁 有了解析几何使人类对直线和射线的认识有革命性的飞跃。几何学有史2300年来一直认定起点和射出的方向都相同的射线必重合&#xff0c;任两异射线必有全等关系&#xff1b;解析几何使我发现这是2300年肉眼直观错觉。 h定理&#xff08;参考文献中的定理&#xff09;&am…

中国自动分拣行业TOP5玩家:大盘点(年收入开局12亿……)

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 随着物流行业的迅猛发展&#xff0c;自动分拣技术正成为提升物流效率的关键。中国自动分拣行业的几家领军企业在2023年展现了各自的战略…