【Unity功能集】TextureShop纹理工坊(五)选区
项目源码:在终章发布
索引
- 选区
- PS选区
- 选区功能点提炼
- TextureShop选区
- 方形区域
- 中间镂空
- 边框的流动虚线
- SelectedRegion类
- 选择选区
- 更新选区
选区
选区
,也既是在当前选中图层中,已选择的编辑区域,我们后续的所有图像编辑操作,都将针对此选中的区域(了解PS选区)。
此功能是TextureShop
的核心功能,毕竟我们后续的所有操作都将针对选区
展开,那么本章我们将探讨如何实现这个功能点。
PS选区
我们先来看看PS
中的选区:
选区功能点提炼
TextureShop
的选区
功能将完全参照PS选区
来实现,所以我们首先来提炼PS选区
的功能特点:
1.选区为一个方形区域;
2.选区内部为无色透明(也即是中间镂空);
3.选区边框为流动的虚线;
如上即为实现选区
后的功能点,如果你了解unity shader
,这三个功能点对你来说并不难。
TextureShop选区
那么现在,让我们来循序展开吧。
方形区域
首先我们要实现的是代表已选取的方形区域
,实现的方式依然是借助shader
。
众所周知,在图形学领域,可用来代表已选取(未选取)
这样一个开关属性的参数,通常是用图像的alpha
通道来表示,如下图像,白色区域(alpha=1)即可代表已选取
区域,棋盘格区域(alpha=0)即可代表未选取
区域:
在shader
中实现它时,首先需要传入这张代表选区状态
的图像:
Shader "Hidden/TextureShop/Region"
{Properties{[HideInInspector] _RegionTex("区域纹理", 2D) = "black" {}}
}
然后在片元处理方法中实现对已选取(未选取)
区域的甄别:
fixed4 frag(FragData IN) : SV_Target{//读取代表选区状态的图像数据half texA = tex2D(_RegionTex, IN.texcoord).a;//texA=1 为已选取区域,输出半透明白色//texA=0 为未选取区域,输出纯透明白色half4 color = half4(1, 1, 1, texA * 0.5);return color;}
看看效果(如何构建这个代表选区状态
的图像数据,将在后面讲解):
很明显,选区
的方形区域效果是OK了。
中间镂空
接下来我们要实现选区
的内部区域不可见(中间镂空),为此,我们引入参数边框大小
,方形区域四周需要显示的部分称作边框
,由边框大小
来决定其尺寸,而除去边框
以外的部分即为中间
区域,都将不可见:
Shader "Hidden/TextureShop/Region"
{Properties{[HideInInspector] _RegionTex("区域纹理", 2D) = "black" {}[HideInInspector] _BrushSize("边框大小", int) = 1 }
}
在片元处理方法中:
fixed4 frag(FragData IN) : SV_Target{float2 uv = IN.texcoord;half texA = tex2D(_RegionTex, uv).a;//基准alpha值half alpha = 1;//遍历边框四周颜色for (int i = -_BrushSize; i <= _BrushSize; i++){for (int j = -_BrushSize; j <= _BrushSize; j++){//将四周的alpha值,累乘到基准alpha值//实现的效果如下://如果四周的alpha值都为1(已选取),则最终基准alpha值也为1(表示此区域为中间区域)//如果四周的alpha值存在0(未选取),则最终基准alpha值也为0(表示此区域为边框区域)float2 borderUV = float2(uv.x + i * _RegionTex_TexelSize.x, uv.y + j * _RegionTex_TexelSize.y);half borderA = tex2D(_RegionTex, borderUV).a;alpha *= borderA;}}half4 color = half4(1, 1, 1, 1);//1 - alpha,将基准alpha值取反,中间区域将为0(输出纯透明色),边框区域将为1(输出白色)color.a = texA * (1 - alpha);return color;}
看看效果:
边框的流动虚线
接下来我们要实现选区
边框区域的流动虚线,我们的第一想法肯定是使用黑白棋盘格图片来实现,为此,我们引入参数边框纹理
(棋盘格图片),边框流动速度
:
Shader "Hidden/TextureShop/Region"
{Properties{[HideInInspector] _RegionTex("区域纹理", 2D) = "black" {}[HideInInspector] _BrushSize("边框大小", int) = 1 [HideInInspector] _BorderTex("边框纹理", 2D) = "black" {}[HideInInspector] _BrushSpeed("边框流动速度", float) = 0.3 }
}
使用此边框纹理
(棋盘格图片):
在片元处理方法中,将边框纹理
(棋盘格图片)输出到边框区域,并随时间流动uv:
fixed4 frag(FragData IN) : SV_Target{//......//half4 color = half4(1, 1, 1, 1);//将原本的边框颜色(白色),改为读取边框纹理颜色,并随时间流动,流动方向:左上角到右下角float2 realUV = float2(uv.x - _Time.x * _BrushSpeed, uv.y + _Time.x * _BrushSpeed);half4 color = tex2D(_BorderTex, realUV * 20);//......}
看看效果:
效果有点奇怪,由于棋盘格图片是斜着向右下方移动的,所以每移动一个单位,就会有翻滚一下的效果(图片边缘),因为我们的棋盘格是正方格的图片。
所以需要改进棋盘格图片,使用如下的图片作为边框纹理
:
再次运行看效果:
OK,没问题了,边框纹理
与边框流动方向相同后,流动的虚线效果更加顺眼。
SelectedRegion类
选区
的展现效果实现后,接下来新建一个类SelectedRegion
,用它来驱动选区逻辑,构建并传入代表选区状态
的图像到shader
中:
/// <summary>/// 选区/// </summary>public sealed class SelectedRegion{private RectTransform _rectTransform;private Material _material;private RawImage _target;private Texture2D _texture;private bool _isTextureDirty = false;/// <summary>/// 选区/// </summary>/// <param name="width">选区宽度</param>/// <param name="height">选区高度</param>/// <param name="parent">选区所属父级</param>/// <param name="borderTex">选区边框纹理</param>public SelectedRegion(int width, int height, RectTransform parent, Texture2D borderTex){//创建选区实体(用于显示选区流动的虚线效果)_rectTransform = Utility.CreateRectTransform("SelectedRegion", parent, true);//创建选区材质(使用我们上文创建的shader)_material = new Material(Utility.RegionShader);_material.hideFlags = HideFlags.HideAndDontSave;//使用RawImage作为渲染器_target = _rectTransform.gameObject.AddComponent<RawImage>();_target.raycastTarget = false;_target.material = _material;//构建选区状态图像_texture = new Texture2D(width, height, TextureFormat.RGBA32, false);_texture.SetPixels(new Color[width * height]);_texture.wrapMode = TextureWrapMode.Clamp;_texture.name = "SelectedRegion";//传入选区状态图像到shader_material.SetTexture("_RegionTex", _texture);//传入边框纹理到shader(上文的棋盘格图片)_material.SetTexture("_BorderTex", borderTex);//标记选区状态为脏的,将触发选区更新_isTextureDirty = true;}}
选择选区
矩形选区可由左上角
、右下角
两个点位描述其位置信息,所以我们如此编写选择选区
的方法:
/// <summary>/// 选区/// </summary>public sealed class SelectedRegion{private Vector2Int _leftUp = new Vector2Int(-1, -1);private Vector2Int _rightDown = new Vector2Int(-1, -1);/// <summary>/// 选择选区【矩形选取】/// </summary>/// <param name="leftUp">区域左上角</param>/// <param name="rightDown">区域右下角</param>/// <param name="isImmediatelyUpdate">是否立即更新选区</param>internal void SetRegion(Vector2Int leftUp, Vector2Int rightDown, bool isImmediatelyUpdate = false){_leftUp = leftUp;_rightDown = rightDown;_isTextureDirty = true;if (isImmediatelyUpdate){//更新选区状态OnUpdate();}}}
更新选区
/// <summary>/// 选区/// </summary>public sealed class SelectedRegion{/// <summary>/// 是否选取任意区域/// </summary>public bool IsSelected { get; private set; } = false;/// <summary>/// 选区更新(OnUpdate帧更新方法由TextureShop编辑器统一调用)/// </summary>public void OnUpdate(){//如果本帧内选区状态为脏的,将触发更新一次if (_isTextureDirty){_isTextureDirty = false;int count = 0;for (int i = 0; i < _texture.width; i++){for (int j = 0; j < _texture.height; j++){if (i >= _leftUp.x && i <= _rightDown.x && j <= _leftUp.y && j >= _rightDown.y){//将处于选区(左上角-右下角)内的像素设置为白色(代表已选取)_texture.SetPixel(i, j, Color.white);count += 1;}else{//将未处于选区(左上角-右下角)内的像素设置为无色(代表未选取)_texture.SetPixel(i, j, Color.clear);}}}//是否存在任意已选取的区域IsSelected = count > 0;//更新选区状态图像,此图像已在构造方法中传递给shader,其将依据此状态图像更新选区展示效果_texture.Apply();}}}
那么至此,矩形选区的功能就实现了。
相关文章:

【Unity功能集】TextureShop纹理工坊(五)选区
项目源码:在终章发布 索引 选区PS选区选区功能点提炼 TextureShop选区方形区域中间镂空边框的流动虚线SelectedRegion类选择选区更新选区 选区 选区,也既是在当前选中图层中,已选择的编辑区域,我们后续的所有图像编辑操作&#x…...
Spring Cloud OpenFeign快速入门demo
一、应用场景 Spring Cloud OpenFeign 是一个声明式的 HTTP 客户端,旨在简化微服务之间的通信。它使得开发者能够通过简单的接口定义和注解来调用 RESTful API,极大地减少了样板代码。以下是一些典型的应用场景: 微服务间调用:在…...

研发效能DevOps: Vite 使用 Element Plus
目录 一、实验 1.环境 2.初始化前端项目 3.安装 vue-route 4.安装 pinia 5.安装 axios 6.安装 Element Plus 7.gitee创建工程 8. 配置路由映射 9.Vite 使用 Element Plus 二、问题 1.README.md 文档推送到gitee未自动换行 2.访问login页面显示空白 3.表单输入账户…...

sfnt-pingpong -测试网络性能和延迟的工具
sfnt-pingpong 是一个用于测试网络性能和延迟的工具,通常用于测量不同网络环境下的数据包传输性能、吞吐量、延迟等指标。 它通常是基于某种网络协议(如 TCP)执行“ping-pong”式的测试,即客户端和服务器之间相互发送数据包&…...
Kubernetes、Docker 和 Docker Registry 关系是是什么?
Kubernetes(常简称为 k8s)、Docker 和 Docker Registry 是现代云原生应用中三个关键的组件,它们各自承担不同的职责,但在容器化部署和管理过程中紧密协作。以下是它们之间关系的详细解释: 一、核心概念简介 1. Docker…...
docker部署微信小程序自动构建发布和更新
通过 Jenkins 和 Docker 部署微信小程序,并实现自动构建、发布和版本更新,主要涉及以下几个步骤: 设置 Jenkins 环境配置 GitLab 与 Jenkins 的集成构建 Docker 镜像部署和发布微信小程序配置 Jenkins 自动构建 以下是详细的步骤说明&#…...
模仿elementui的Table,实现思路
vue2子组件使用render,给子子组件插槽传值 和elementui的Table一样使用render 在 Vue 2 中,子组件使用render函数向子子组件插槽传值可以通过以下步骤实现: 1、创建子组件 首先创建一个子组件,在子组件中使用render函数来渲染内容…...

Unity中使用环形缓冲区平滑抖动值
环形缓冲数据结构,就是如下图一样的一个收尾相接的列表 在index指针指到4时,再往里添加数据,index就会指向0,并覆盖已有数据。 如何绘制Sin函数,请看下面一篇文章 Unity中如何实现绘制Sin函数图像-CSDN博客 接下来要…...

【Yonghong 企业日常问题 06】上传的文件不在白名单,修改allow.jar.digest属性添加允许上传的文件SH256值?
文章目录 前言问题描述问题分析问题解决1.允许所有用户上传驱动文件2.如果是想只上传白名单的驱动 前言 该方法适合永洪BI系列产品,包括不限于vividime desktop,vividime z-suit,vividime x-suit产品。 问题描述 当我们连接数据源的时候&a…...

SpringBoot使用 AOP 实现自定义日志记录并保存在Mysql
本文主要介绍在 Spring Boot 中使用 AOP 实现自定义日志记录并保存在 Mysql 的方法。先阐述记录日志的重要性及传统方式的弊端,提出新方式,即通过创建自定义注解、切面类等,将重要日志存到数据库,还给出了创建日志表、注解类、切面…...

谷歌开源最强天气预报AI模型 GenCast
谷歌 DeepMind 开源新一代天气预测 AI 模型 GenCast,GenCast 以最先进的精度预测天气和极端条件的风险 天气预报对人们生活和决策至关重要,但传统 NWP 模型存在不确定性,且计算资源需求大、运行慢。机器学习在天气预报中虽有进展,…...

C++打造局域网聊天室第十课: 客户端编程及数据发送
文章目录 前言一、补充内容,设置显示框换行二、客户端编程三、封装消息发送函数四、所处的身份状态总结 前言 C打造局域网聊天室第十课: 客户端编程及数据发送 一、补充内容,设置显示框换行 编辑框的显示内容默认是不会换行的,这…...
Nginx整合Lua脚本
Nginx-Lua Nginx整合Lua脚本 Lua环境搭建 下载地址 linux环境下 yum install lua安装后验证 lua -vLua脚本执行 lua xxx.luaNginx整合Lua nginx需要添加lua模块 嵌入内容 示例如下 修改nginx.conf如下 location /lua {default_type text/plain;content_by_lua ngx.sa…...
【C++】C++11 STL容器emplace方法原理剖析
在 C 11 STL 容器中,push/insert > emplace 新的方法,push 和 emplace 的区别在于: 1. push push 通常用于将一个元素添加到容器的末尾(在 std::vector、std::deque 等序列容器中),或者在关联容器中插入…...
QT-简单视觉框架代码
文章目录 简介1. 整体架构2. 关键类功能概述3. 详细代码实现hikcameraworker.h 和 hikcameraworker.cpp(海康相机工作线程类)imageviewerwidget.h 和 imageviewerwidget.cpp(图像查看部件类)构造函数 ImageViewerWidget析构函数 ~…...

AI新书推荐:深度学习和大模型原理与实践(清华社)
本书简介 在这个信息爆炸、技术革新日新月异的时代,深度学习作为人工智能领域的重要分支,正引领着新一轮的技术革命。《深度学习和大模型原理与实践》一书,旨在为读者提供深度学习及其大模型技术的全面知识和实践应用的指南。 本书特色在于…...

[spring]处理器
我们可以通过spring来管理我们的类,之后我们可以通过spring的容器来获取我们所需要的Bean类对象。Spring的处理器是Spring对外开发的重要扩展点,它允许我们介入到Bean的整个实例化流程中来,可以动态添加、修改BeanDefinition、动态修改Bean 首…...

重温设计模式--中介者模式
中介者模式介绍 定义:中介者模式是一种行为设计模式,它通过引入一个中介者对象来封装一系列对象之间的交互。中介者使得各个对象之间不需要显式地相互引用,从而降低了它们之间的耦合度,并且可以更方便地对它们的交互进行管理和协调…...

重温设计模式--设计模式七大原则
文章目录 1、开闭原则(Open - Closed Principle,OCP)定义:示例:好处: 2、里氏替换原则(Liskov Substitution Principle,LSP)定义:示例:好处&#…...
LeetCode429周赛T4
最小化二进制字符串中最长相同子字符串的长度 在处理二进制字符串问题时,优化字符串结构以满足特定条件是一项常见的挑战。本文将探讨一个具体的问题:给定一个长度为 n 的二进制字符串 s 和一个整数 numOps,通过最多 numOps 次位翻转操作&am…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学
一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件,其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时,价带电子受激发跃迁至导带,形成电子-空穴对,导致材料电导率显著提升。…...

表单设计器拖拽对象时添加属性
背景:因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...
【大厂机试题解法笔记】矩阵匹配
题目 从一个 N * M(N ≤ M)的矩阵中选出 N 个数,任意两个数字不能在同一行或同一列,求选出来的 N 个数中第 K 大的数字的最小值是多少。 输入描述 输入矩阵要求:1 ≤ K ≤ N ≤ M ≤ 150 输入格式 N M K N*M矩阵 输…...

若依项目部署--传统架构--未完待续
若依项目介绍 项目源码获取 #Git工具下载 dnf -y install git #若依项目获取 git clone https://gitee.com/y_project/RuoYi-Vue.git项目背景 随着企业信息化需求的增加,传统开发模式存在效率低,重复劳动多等问题。若依项目通过整合主流技术框架&…...
零基础在实践中学习网络安全-皮卡丘靶场(第十一期-目录遍历模块)
经过前面几期的内容我们学习了很多网络安全的知识,而这期内容就涉及到了前面的第六期-RCE模块,第七期-File inclusion模块,第八期-Unsafe Filedownload模块。 什么是"遍历"呢:对学过一些开发语言的朋友来说应该知道&…...
软件工程教学评价
王海林老师您好。 您的《软件工程》课程成功地将宏观的理论与具体的实践相结合。上半学期的理论教学中,您通过丰富的实例,将“高内聚低耦合”、SOLID原则等抽象概念解释得十分透彻,让这些理论不再是停留在纸面的名词,而是可以指导…...
CSS中justify-content: space-between首尾贴边中间等距(两端元素紧贴左右边缘,中间元素等距均匀分布)
justify-content: space-between; 是 CSS Flexbox 布局中的一个属性值,主要作用是在弹性容器的主轴方向上均匀分布子元素,具有以下核心特性: 作用效果: 首尾贴边 第一个子元素紧贴容器起始端 最后一个子元素紧贴容器结束端 中…...