Unity UI擦除效果

public class ScratchImage : MonoBehaviour
    {
        /// <summary>
        /// 蒙版贴图
        /// </summary>
        public Image maskImage;
        public Material maskMaterial;
        private Camera uiCamera;
        private Vector2 _maskSize;
        private Texture2D _rt;
        private Color[] spritePixels;
        public int brushRadius = 50;
        private float percent = 0;
        public float finishPercent = 0.95f;
        private int clearNum = 0;
        private int[] dirtyPoints;
        private Vector2 SCALE_FACTOR;
        private Vector2Int RTSize;
        bool bClear = false;
        private void Reset()
        {
            maskImage = GetComponent<Image>();
            maskMaterial = maskImage.material;
        }
        public void SetParams(int brushRadius,float fpercent)
        {
            this.brushRadius = brushRadius;
            this.finishPercent = fpercent;
        }
        private void Init()
        {
            if (uiCamera == null)
            {
                uiCamera = UIHelper.Instance.UICamera;
            }
            SCALE_FACTOR = maskImage.sprite.textureRect.size / maskImage.rectTransform.rect.size;
            _maskSize = maskImage.rectTransform.rect.size;
            //Debug.LogFormat("mask image size:{0}*{1}", maskSize.x, maskSize.y);
            RTSize = new Vector2Int((int)maskImage.sprite.textureRect.size.x, (int)maskImage.sprite.textureRect.size.y);
            spritePixels = maskImage.sprite.texture.GetPixels(0, 0, RTSize.x, RTSize.y);
            _rt = new Texture2D(RTSize.x, RTSize.y);
            _rt.SetPixels(spritePixels);
            _rt.Apply();
            maskMaterial.SetTexture("_TempTex", _rt);
            dirtyPoints = new int[RTSize.x * RTSize.y];
            bClear = false;
            percent = 0;
            clearNum = 0;
        }
        public void Update()
        {
            onUpdate();
        }
        void Fill()
        {
            bClear = true;
            for (int i = 0; i < RTSize.x; i++)
            {
                for (int j = 0; j < RTSize.y; j++)
                {
                    if(dirtyPoints[i*RTSize.y+j]==0)
                    {
                        _rt.SetPixel(i, j, new Color(1, 1, 1, 0));
                    }
                }
            }
            _rt.Apply();
        }
        public void ResetMask()
        {
            _rt.SetPixels(spritePixels);
            _rt.Apply();
            for (int i = 0; i < dirtyPoints.Length; i++)
            {
                dirtyPoints[i] = 0;
            }
            clearNum = 0;
            bClear = false;
        }
        private void onUpdate()
        {
            if (bClear) return;
            if (uiCamera == null)
                return;
            if (!Input.GetMouseButton(0)) // 移动鼠标或者处于按下状态
            {
                return;
            }
            Vector2 localPt = Vector2.zero;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(transform as RectTransform, Input.mousePosition, uiCamera, out localPt);

            //Debug.Log($"pt:{localPt}, status:{mouseStatus}");
            if (localPt.x < 0 || localPt.y < 0 || localPt.y >= _maskSize.x || localPt.y >= _maskSize.y)
                return;

            localPt = localPt * SCALE_FACTOR;
            Vector2Int usePixel = new Vector2Int((int)(localPt.x), (int)localPt.y);
            int left = (int)(usePixel.x - brushRadius);
            if (left < 0) left = 0;
            int right = (int)(usePixel.x + brushRadius);
            if (right > RTSize.x) right = (int)RTSize.x;
            int down = (int)(usePixel.y - brushRadius);
            if (down < 0) down = 0;
            int top = (int)(usePixel.y + brushRadius);
            if (top > RTSize.y) top = (int)RTSize.y;
            bool dirty = false;
            for (int i = left; i < right; i++)
            {
                for (int j = down; j < top; j++)
                {
                    int index = (int)(i * RTSize.y + j);
                    if (dirtyPoints[index] == 1)
                    {

                    }
                    else
                    {
                        Vector2 p = new Vector2(i, j);
                        float dis = Vector2.Distance(usePixel, p);
                        if (dis <= brushRadius)
                        {
                            _rt.SetPixel(i, j, new Color(1, 1, 1, 0));
                            dirtyPoints[index] = 1;
                            ++clearNum;
                            dirty = true;
                        }
                    }
                }
            }
            if (dirty)
            {
                percent = (float)clearNum / dirtyPoints.Length;
                if (percent > finishPercent)
                {
                    Fill();
                    GameHelp.FireEvent((ushort)DGlobalEvent.EVENT_SMALL_GAME_RESULT_OK, 0, 0, null);
                }
                else
                {
                    _rt.Apply();
                }
            }
        }
    }

shader

Shader "Unlit/PaintMask"
{
    Properties
    {
        _MainTex ("MainTexture", 2D) = "white" {}
        _TempTex ("TempTexture",2D) = "white" {}
    }
    SubShader
    {
        Tags 
        { 
           "Queue"="Transparent"
           "RenderType"="Transparent"
        }
        LOD 100
        ZWrite Off
        ZTest Off
        Blend SrcAlpha OneMinusSrcAlpha 
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            sampler2D _TempTex;
            float4 _TempTex_ST;
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                half alpha = tex2D(_TempTex,i.uv).a;
                col.a = alpha;
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

最粗暴的方法,原理就是跟着鼠标的位置,以鼠标为圆心把圆内的像素点清除,遮罩变成透明了,里面的图片就显示出来了,如果觉得鼠标滑动快的时候采样点不够,考虑DDA直线插值

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(三十一)第 5 章 数组和广义表(稀疏矩阵的三元组行逻辑链接的顺序存储表示实现)

1. 背景说明 2. 示例代码 1)errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strrch…

算法03贪心与动态规划

算法03贪心与动态规划 1. 贪心与动态规划概述1.贪心1.1贪心概述1.2贪心常用场景1.3贪心解题思路 2.动态规划2.1动态规划概述2.2动态规划常用场景2.3动态规划解题模板 3.浅谈贪心与动态规划的关系 2.贪心经典题目区间问题 3.动态规划经典题目3.1体会“从整体到局部”的思考过程3…

2024Mac系统热门游戏排行榜 Mac支持的网络游戏有哪些?mac能玩哪些大型网游 苹果电脑Mac游戏资源推荐 Mac玩Windows游戏

“游戏是这个世界上唯一能和女性争夺男朋友的东西&#xff08;/滑稽&#xff0c;有不少女生也喜欢玩游戏&#xff09;。” 虽然只是一句玩笑话&#xff0c;不过也可以看出游戏对大多数男生来说是必不可少的一项娱乐活动了。而网络游戏是游戏中的一大分支&#xff0c;能让玩家们…

zabbix自动发现和自动注册

一、zabbix自动发现 1.1 确保客户端上的zabbix-agent2服务器状态正常 1.2 在web页面删除原有的客户端主机 1.3 在服务端和客户端上配置hosts 1.4 web端配置自动发现 二、zabbix自动注册 2.1 环境配置 2.2 修改zabbix-agent2配置文件 过滤非#或非&#xffe5;开头的内容 2.3 we…

基于遗传优化算法的TSP问题求解matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于遗传优化算法的TSP问题求解&#xff0c;分别对四个不同的城市坐标进行路径搜索。 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 3.核心程序 ....…

前端开发攻略---用原生JS在网页中也能实现语音识别

1、语音识别的过程 语音识别涉及三个过程&#xff1a;首先&#xff0c;需要设备的麦克风接收这段语音&#xff1b;其次&#xff0c;语音识别服务器会根据一系列语法 (基本上&#xff0c;语法是你希望在具体的应用中能够识别出来的词汇) 来检查这段语音&#xff1b;最后&#xf…

基于EBAZ4205矿板的图像处理:02生成测试彩条图像

基于EBAZ4205矿板的图像处理&#xff1a;02生成测试彩条图像 生成测试彩条图像可以有两种方式 VDMA缓存PS端生成彩条图像数据&#xff0c;PL端输出 这里可以直接看超级大电工开源的代码&#xff0c;写的很好详细&#xff0c;我就不再班门弄斧了&#xff08;下面是链接&#…

22 - Hadoop HA 高可用集群搭建、手动模式、自动模式以及HA模式集群

目录 1、HA 概述 2、HDFS-HA 集群搭建 2.1、HDFS-HA 核心问题 3、HDFS-HA 手动模式 3.1、环境准备 3.2、规划集群 3.3、配置 HDFS-HA 集群 3.4、启动 HDFS-HA 集群 4、HDFS-HA 自动模式 4.1、HDFS-HA 自动故障转移工作机制 4.2、HDFS-HA 自动故障转移的集群规划 4.…

AI助力后厨可视化智慧监管,让“舌尖安全”看得见

一、背景与需求分析 夏天是食物易腐败的季节&#xff0c;高温容易引发食品安全问题。在后厨环境中&#xff0c;食品安全问题可能涉及食品加工、后厨环境、食品是否被污染等方面&#xff0c;而不合格的食品安全管理可能导致食品中毒事件等风险&#xff0c;损害消费者的健康和餐…

Asp .Net Core 系列:国际化多语言配置

文章目录 概述术语 本地化器IStringLocalizer在服务类中使用本地化 IStringLocalizerFactoryIHtmlLocalizerIViewLocalizer 资源文件区域性回退 配置 CultureProvider内置的 RequestCultureProvider实现自定义 RequestCultureProvider使用 Json 资源文件 设计原理IStringLocali…

你的动漫AI女友 Anime gf :自定义创建各种独特个性、语言风格的虚拟角色

一个本地且开源的 CharacterAI 替代工具 Anime gf&#xff0c;提供了一个用户友好的界面&#xff0c;允许用户在桌面上与虚拟角色互动。你可以自定义创建各种角色&#xff0c;让每个虚拟角色都有自己的独特个性和语言风格&#xff0c;可以接入OpenAI、Anthropic、Mistral和 Tog…

建立外贸网站常用的WordPress插件

我们最近使用hostease的虚拟主机在创建wordpress外贸网站时&#xff0c;需要选择安装一些插件。对于wordpress建站选择合适的WordPress插件至关重要。面对琳琅满目的插件选择&#xff0c;根据多年的实践经验&#xff0c;我为您推荐以下必备插件清单&#xff0c;让您的网站建设更…

电商红利再现,“视频号小店”即将顶替“抖音小店”

哈喽~我是电商月月 电商行业发展迅速&#xff0c;除了“刚兴起”就入驻的商家&#xff0c;竞争少&#xff0c;市场大&#xff0c;能简简单单吃到第一批红利&#xff0c;后来入驻的商家就需要运用技巧与同行竞争了【要么认真选品&#xff0c;有独特的卖点。要么就是打价格战&am…

系统性文献综述的撰写(Systematic Review)

文献综述 什么是文献综述 对某一个“领域、专业、课题、问题、研究专题”&#xff0c;通过搜集大量的相关资料&#xff08;别人发表的论文&#xff09;&#xff0c;然后通过“阅读、分析、归纳、整理”给出最新进展、学术见解或建议。对其做出综合性介绍和阐述的一种学术论文…

基于SpringBoot和PostGIS的各省与地级市空间距离分析

目录 前言 一、PostGIS时空库 1、时空表设计 2、空间数据管理与查询 二、后台接口设计 1、ORM层设计与实现 2、业务层设计与实现 3、控制层设计 三、web可视化设计与实现 1、省份范围展示 2、城市距离可视化 3、成果展示 总结 前言 在上一篇博客中基于Java和GDAL实…

力扣HOT100 - 78. 子集

解题思路&#xff1a; class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> lists new ArrayList<>(); // 解集lists.add(new ArrayList<Integer>()); // 首先将空集加入解集中for(int i 0; i < n…

【nginx】http2 配置造成 多进程请求变成单进程

一、环境简要说明 #访问请求过程 用户&#xff08;浏览器&#xff09; ——> 防火墙映射 ——> nginx ——> app服务&#xff08;java&#xff09; http2是什么&#xff0c;简单来说是继HTTP1.1版本之后的新版HTTP协议&#xff0c;支持二进制分帧、多路复用、首部压缩…

认识Linux及一些基本

目录 linux简介&#xff1a; 1. 发展史 UNIX发展的历史 Linux发展历史 2. 开源 3. 企业应用现状 Linux在服务器领域的发展 Linux在桌面领域的发展 Linux在移动嵌入式领域的发展 Linux在云计算/大数据领域的发展 4. 发行版本 Debian Ubuntu 红帽企业级Linux Cent…

数据结构复习指导之数组和特殊矩阵

文章目录 数组和特殊矩阵 考纲内容 复习提示 前言 1.数组的定义 2.数组的存储结构 3.特殊矩阵的压缩存储 3.1对称矩阵 3.2三角矩阵 3.3三对角矩阵 4.稀疏矩阵 5.知识回顾 数组和特殊矩阵 考纲内容 &#xff08;一&#xff09;栈和队列的基本概念 &#xff08;二&a…

ubuntu neo4j 下载与配置(一)

neo4j 官方下载页面 https://neo4j.com/deployment-center/#community 进入页面之后&#xff0c;往下滑 咱们在下载neo4j时&#xff0c;官方可能要咱们填写一下个人信息&#xff0c;比如&#xff1a;姓名组织结构邮箱等&#xff1a; 咱们可以观察一下&#xff0c;ne4j的下载链…