【Godot4.3】基于绘图函数的矢量蒙版效果与UV换算

news/2025/2/25 14:38:42

概述

在设计圆角容器时突发奇想:

  • 将圆角矩形的每个顶点坐标除以对应圆角矩形所在Rect2size,就得到了顶点对应的UV坐标。
  • 然后使用draw_colored_polygon,便可以做到用图片填充圆角矩形的效果。
  • 而且这种计算的效果就是图片随着其填充的图像缩放。
  • 这就类似于是在CanvasItem绘图函数基础上实现了矢量蒙版效果

基础原理

  • 以上面的五角星为例,它的某个顶点P的UV坐标,应该如下计算:
    顶点P的UV坐标 = 点P的坐标 五角星所在轴对齐包围盒Rect2的size 顶点\text{P}的\text{UV}坐标 = \frac{点\text{P}的坐标}{五角星所在轴对齐包围盒\text{Rect2}的\text{size} } 顶点PUV坐标=五角星所在轴对齐包围盒Rect2sizeP的坐标

  • 前提是:五角星Rect2position(0,0)

  • 这是一种类似自适应的填充形式,图片会随图形的缩放进行缩放,大小和位置始终与图形的包围盒Rect2一致

  • 但是在其他情况下,我们或许需要实现一些复杂的填充效果,比如控制图片进行偏移、旋转、缩放等。这时,上面的UV计算方法就不顶用了。

此时,我们需要考虑图片本身和图形两者是独立的,然后考虑通过它们之间偏移关系去映射坐标位置。

测试

编写了一个基础的UI场景进行测试:

# ==========================================================
# UVtest
# 类型:测试
# 概述:实现基于绘图函数的矢量蒙版效果
# 巽星石
# 创建时间:20251322:50:10
# 最后修改时间:20251323:04:28
# ==========================================================


@tool
extends Control

@export var texture:Texture2D:
	set(val):
		texture = val
		queue_redraw()

@export var texture_position:=Vector2(): ## 纹理的偏移
	set(val):
		texture_position = val
		queue_redraw()

@export var texture_scale:=Vector2.ONE: ## 纹理缩放值
	set(val):
		texture_scale = val
		queue_redraw()

@export_range(-360,360,1) var texture_rotation_degree:=0: ## 纹理旋转
	set(val):
		texture_rotation_degree = val
		queue_redraw()


@export var fill_color:=Color.WHITE:
	set(val):
		fill_color = val
		queue_redraw()


func _draw() -> void:
	var rect = get_rect() * get_transform()
	var pots = star(0,5,rect.size.y/2.0,rect.size.y/3.0,rect.get_center())
	
	# 绘制背景
	if texture:
		var rot = deg_to_rad(texture_rotation_degree)
		
		var image_rect = Rect2(texture_position,texture.get_size() * texture_scale)
		var r:Vector2 = rect.size/image_rect.size  # 比例
		
		var UV.html" title=uv>uvs:PackedVector2Array
		for pot in pots: # 计算UV坐标
			# 进行旋转变换后的坐标
			var p = (pot - rect.get_center()).rotated(-rot) + rect.get_center()
			
			UV.html" title=uv>uvs.append(((p - texture_position)/rect.size) * r)
		# 绘制圆角矩形
		draw_colored_polygon(pots,fill_color,UV.html" title=uv>uvs,texture)
	else:
		draw_polygon(pots,[fill_color])
	pass


# 星形
func star(start_angle:int,edges:int,r:float,r2:float = 0,offset:Vector2 = Vector2.ZERO):
	if r2 == 0:
		r2 = r/2.0
	var points:PackedVector2Array
	# 外部半径
	var vec  = Vector2.RIGHT.rotated(deg_to_rad(start_angle)) * r
	# 内部半径
	var vec2  = Vector2.RIGHT.rotated(deg_to_rad(start_angle + 180/edges)) * r2
	for i in range(edges):
		points.append(vec.rotated(2 * PI/edges * i) + offset)
		points.append(vec2.rotated(2 * PI/edges * i) + offset)
	return points

效果:

进行偏移、旋转和缩放后的效果:

提示

本例中暂时没有使用几何图形自身的Rect2,而是采用了测试场景控件元素的Rect2,所以带来的实际效果可能不太相同。

也就是说这还是一个未完成的实验版本。后续敬请期待。


http://www.niftyadmin.cn/n/5865615.html

相关文章

akka现有的分布式定时任务框架总结

根据你的需求,以下是一些基于 Akka 实现的分布式定时任务框架,以及相关的 GitHub 项目推荐: 1. Openjob Openjob 是一个基于 Akka 架构的新一代分布式任务调度框架,支持多种定时任务、延时任务、工作流设计,采用无中…

CES Asia 2025,技术创新成招商强引力

近日,2025年中国经济白皮书正式发布,为第七届亚洲消费电子技术贸易展(CES Asia 2025)的招商工作注入强大动力,其在技术创新方面展现出的显著优势,成为吸引全球科技企业的关键因素。 白皮书全面展示了中国在…

C#文件操作

文件类File 常用方法介绍Open()打开文件Create()创建文件Copy()复制文件Delete()删除文件Exists()判断文件是否存在Move()移动文件Replace()替换文件AppendAllText()新建并添加文本ReadAllText()打开并读取文本内容 1.读取文件 1.创建一个Filestream 对象 (引入System.IO命名…

Linux版本控制器Git【Ubuntu系统】

文章目录 **前言**一、版本控制器二、Git 简史三、安装 Git四、 在 Gitee/Github 创建项目五、三板斧1、git add 命令2、git commit 命令3、git push 命令 六、其他1、git pull 命令2、git log 命令3、git reflog 命令4、git stash 命令 七、.ignore 文件1、为什么使用 .gitign…

Deepseek引爆AI热潮 防静电地板如何守护数据中心安全

近期,Deepseek的爆火将人工智能推向了新的高度,也引发了人们对AI背后基础设施的关注。作为AI运行的“大脑”,数据中心承载着海量数据的存储、处理和传输,其安全稳定运行至关重要。而在这背后,防静电地板扮演着不可或缺…

告别阻塞,迎接高效:掌握 AsyncIOScheduler 实现异步任务调度

前言 时间在编程中是宝贵的,直接关联到效率与灵活性,尤其在异步编程里,如何优雅地管理定时任务简直是一门“艺术”。如果你还在用 time.sleep() 来控制延时任务,恐怕你早已体会过它的“痛苦”:程序卡住、线程阻塞、性能急剧下滑。想象一下,你的程序如同一个永远无法按时…

HTML应用指南:利用GET请求获取全国泸溪河门店位置信息

随着新零售业态的快速发展,门店位置信息的获取变得越来越重要。作为新兴烘焙品牌之一,泸溪河自2013年在南京创立以来,一直坚持“健康美味,香飘世界”的企业使命,以匠人精神打造新中式糕点。为了更好地理解和利用这些数据,本篇文章将深入探讨GET请求的实际应用,并展示如何…

力扣3464. 正方形上的点之间的最大距离

力扣3464. 正方形上的点之间的最大距离 题目 题目解析及思路 题目要求在points集合中找出k个点,k个点之间的最小的曼哈顿距离的最大值 最大最小值的题一般直接想到二分 将正方形往右展开成一条线,此时曼哈顿距离为两点直线距离**(仅起点右边的点)** …