当前位置: 首页 > news >正文

Unity开发绘画板——03.简单的实现绘制功能

从本篇文章开始,将带着大家一起写代码,我不会直接贴出成品代码,而是会把写代码的历程以及遇到的问题、如何解决这些问题都记录在文章里面,当然,同一个问题的解决方案可能会有很多,甚至有更好更高效的方式是我所没有想到的,大家也可以在评论区一起讨论一下。

1.监听鼠标输入

要实现绘画的功能,监听鼠标的输入是首先要解决的问题,我们希望按下鼠标左键之后开始在屏幕中绘制,要实现这个也比较简单。

我们先在Scripts文件夹下创建一个新脚本,命名为Painter.cs, 并将其挂载到场景中的Painter节点上,我们将在Painter.cs的Update中实现该逻辑。

public class Painter : MonoBehaviour
{void Update(){if (Input.GetMouseButtonDown(0)){//开始绘制var mousePosition = Input.mousePosition; //获取当前鼠标位置}if (Input.GetMouseButton(0)){//绘制}if (Input.GetMouseUp(0)){//停止绘制}}
}

 2.绘制图案

通过Graphics.DrawTexture接口向RenderTexture中绘制图案,这里的图案其实就是我们的笔刷样式了。

例如我们现在有一张圆形的图案:

想要用这个作为笔刷在一张空的RenderTexture上去作画,实现的代码也很简单,在Painter.cs中实现如下方法:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Painter : MonoBehaviour
{public RenderTexture renderTexture;public Texture2D brushTexture; //笔刷纹理public float brushSize = 5f;void Update(){if (Input.GetMouseButtonDown(0)){}if (Input.GetMouseButton(0)){var mousePosition = Input.mousePosition;DrawBrush((int)mousePosition.x, (int)mousePosition.y);}}private void DrawBrush(int x, int y){//纹理绘制的位置和大小Rect brushRect = new Rect(x, y, brushSize, brushSize);//指定渲染目标为renderTextureGraphics.SetRenderTarget(renderTexture);//保存当前矩阵状态GL.PushMatrix();//设置像素矩阵GL.LoadPixelMatrix(0, renderTexture.width, 0, renderTexture.height);//绘制纹理Graphics.DrawTexture(brushRect, brushTexture);//恢复之前的矩阵状态GL.PopMatrix();//重置渲染目标Graphics.SetRenderTarget(null);}}

由于笔刷颜色是白色的,画板背景也是白色,为了让绘制结果能被看到,我们先把背景颜色调成黑色,改变MainCamera的Background即可(改变线条颜色我们之后会讲到),执行效果如下图所示:

可见已经有点感觉了,但是表现是很多间断的点,而不是连续的线,因为我们的绘制是由Update驱动的,所以绘制速度也受Update帧率影响,当鼠标速度快的时候尤其明显。

为了解决这个问题,我们可以考虑在点与点之间进行线性插值,绘制更多的点,这样就会显得连续了。

原理如下图:

从A点到B点之间线性插入若干点。

 为了达到此目的,我们需要从一下几个点入手:

  • 我们期望这些插入点的密度是可以通过参数调节的
  • 我们在绘制当前的位置时需要知道上一次绘制的位置

简单改一下代码:

新增一个previousMousePos字段,用于记录上一次笔刷位置

新增函数 private void DrawLine(Vector2 start, Vector2 end) 用于绘制两点之间的连线

优化后的代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Painter : MonoBehaviour
{public RenderTexture renderTexture;public Texture2D brushTexture; //笔刷纹理public float brushSize = 5f;    //笔刷大小public float resolutionMultiplier = 5;  //线性插值密度调节private Vector2 previousMousePos; //记录上一帧鼠标的位置  void Update(){if (Input.GetMouseButtonDown(0)){previousMousePos = Input.mousePosition;}if (Input.GetMouseButton(0)){var mousePosition = Input.mousePosition;DrawLine(previousMousePos, mousePosition);previousMousePos = mousePosition;}}private void DrawLine(Vector2 start, Vector2 end){float distance = Vector2.Distance(start, end);int steps = Mathf.CeilToInt(distance * resolutionMultiplier);for (int i = 0; i <= steps; i++){float t = i / (float)steps;int x = Mathf.FloorToInt(Mathf.Lerp(start.x, end.x, t));int y = Mathf.FloorToInt(Mathf.Lerp(start.y, end.y, t));DrawBrush(x, y);}}private void DrawBrush(int x, int y){Rect brushRect = new Rect(x, y, brushSize, brushSize);Graphics.SetRenderTarget(renderTexture);GL.PushMatrix();GL.LoadPixelMatrix(0, renderTexture.width, 0, renderTexture.height);Graphics.DrawTexture(brushRect, brushTexture);GL.PopMatrix();Graphics.SetRenderTarget(null);}}

效果如下,感觉还是不错的~

这样我们就简单实现了绘制的功能,下一章我们来实现滑动条调节画笔的大小~

相关文章:

Unity开发绘画板——03.简单的实现绘制功能

从本篇文章开始&#xff0c;将带着大家一起写代码&#xff0c;我不会直接贴出成品代码&#xff0c;而是会把写代码的历程以及遇到的问题、如何解决这些问题都记录在文章里面&#xff0c;当然&#xff0c;同一个问题的解决方案可能会有很多&#xff0c;甚至有更好更高效的方式是…...

R语言的基础知识R语言函数总结

R语言与数据挖掘&#xff1a;公式&#xff1b;数据&#xff1b;方法 R语言特征 对大小写敏感通常&#xff0c;数字&#xff0c;字母&#xff0c;. 和 _都是允许的(在一些国家还包括重音字母)。不过&#xff0c;一个命名必须以 . 或者字母开头&#xff0c;并且如果以 . 开头&…...

龙年国庆专属姓氏头像

关注▲洋洋科创星球▲一起成长&#xff01; 2024年&#xff0c;我们迎来了龙年&#xff0c;龙年国庆姓氏头像&#xff01; 慢慢找&#xff01; 你的和你朋友的都有。 01赵 02 钱 03 孙 04 李 05 周 06 吴 07 郑 08 王 09 冯 010 陈 011 褚 012 卫 013 蒋 014 沈 015 韩 姓氏…...

基于Es和智普AI实现的语义检索

1、什么是语义检索 语义检索是一种利用自然语言处理&#xff08;NLP&#xff09;和人工智能&#xff08;AI&#xff09;技术来理解搜索查询的语义&#xff0c;以提供更准确和相关搜索结果的搜索技术&#xff0c;语义检索是一项突破性的技术&#xff0c;旨在通过深入理解单词和…...

URI和URL的区别

1: 将 URI 转换为 URL import java.net.URI; import java.net.URL;public class UriToUrlExample {public static void main(String[] args) {// 创建一个 URI 对象URI uri = new URI("http://example.com/path/to/resource");// 将 URI 转换为 URLtry {URL url = u…...

Java 入门指南:获取对象的内存地址

文章目录 hashCode()应用重写 hashCode() 方法示例 Symstem . indentityHashCode()应用 注意事项 在 Java 开发中&#xff0c;了解对象的内存管理是十分重要的&#xff0c;尽管 Java 的设计初衷是让开发者更专注于业务逻辑而非底层资源管理。但在某些情况下&#xff0c;了解对象…...

【Linux】项目自动化构建工具-make/Makefile 详解

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;Linux系统编程 这里将会不定期更新有关Linux的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 文章目…...

嵌入式开发中学习C++的用处?

这个问题一直有同学在问&#xff0c;其实从我的角度是一定是需要学的&#xff0c;最直接的就是你面试大厂的嵌入式岗位或者相关岗位&#xff0c;最后一定会问c&#xff0c;而很多人是不会的&#xff0c;这就是最大的用处&#xff0c;至于从技术角度考量倒是其次&#xff0c;因为…...

基于SAM大模型的遥感影像分割工具,用于创建交互式标注、识别地物的能力,可利用Flask进行封装作为Web后台服务

如有帮助&#xff0c;支持一下&#xff08;GitHub - Lvbta/ImageSegmentationTool-SAM: An interactive annotation case developed based on SAM for remote sensing image annotation, which can generate corresponding segmentation results based on point, multi-point, …...

Selenium入门

Selenium 是一个用于自动化 web 应用程序测试的工具&#xff0c;它支持多种浏览器和编程语言。 下载驱动程序&#xff1a;根据你的浏览器类型和版本&#xff0c;下载相应的 WebDriver。例如&#xff0c;Chrome 浏览器需要 ChromeDriver。 安装 Selenium 库 pip install sele…...

USB 3.1 Micro-A 与 Micro-B 插头,Micro-AB 与 Micro-B 插座,及其引脚定义

连接器配对 下表列出 USB 插座可接受的插头&#xff1a; USB 3.1 Micro-B 连接器 USB 3.1 Micro-B 插头和 USB 3.1 Micro-B 插座连接器是为小型手持设备和其他可能使用小尺寸连接器的应用而定义的。其定义使得 USB 3.1 Micro-B 插座既可以接受 USB 3.1 Micro-B 插头&#xff…...

MySQL多版本并发控制MVCC实现原理

MVCC MVCC 是多版本并发控制方法&#xff0c;用来解决读和写之间的冲突&#xff0c;比如脏读、不可重复读问题&#xff0c;MVCC主要针对读操作做限制&#xff0c;保证每次读取到的数据都是本次读取之前的已经提交事务所修改的。 概述 当一个事务要对数据库中的数据进行selec…...

【并查集】[ABC372E] K-th Largest Connected Components 题解

题意 前置阅读&#xff1a;并查集算法介绍 洛谷链接 Atcoder 链接 给定 n ( 1 ≤ n ≤ 2 1 0 5 ) n(1 \leq n \leq 2\times 10^5) n(1≤n≤2105) 个点&#xff0c;初始没有边&#xff0c;您要进行以下操作&#xff1a; 1 a b&#xff0c;表示连接一条 ( a , b ) (a,b) …...

HarmonyOS面试题(持续更新中)

1、用过线程通信吗&#xff0c;线程是怎么进行通信的&#xff1f; emitter 和 eventHub 相同&#xff1a; 都是基于事件总线的 区别是&#xff1a; ① eventHub当前线程内通信 ② emitter是同一进程不同线程或者同一进程和同一线程也可以通信 2、页面和组件的生命周期 …...

QT中QWidget和QObject的区别与联系是什么

在Qt框架中&#xff0c;QWidget和QObject是两个核心类&#xff0c;它们各自扮演着不同的角色&#xff0c;但又紧密相连。以下是关于它们区别与联系的详细解释&#xff1a; 区别 基类和功能定位&#xff1a; QObject是Qt中所有类的基类&#xff0c;包括几乎所有的Qt对象。它提供…...

解决macOS安装redis以后不支持远程链接的问题

参考文档:https://blog.csdn.net/qq_37703224/article/details/142542179?spm1001.2014.3001.5501 安装的时候有个提示, 使用指定配置启动: /opt/homebrew/opt/redis/bin/redis-server /opt/homebrew/etc/redis.conf那么我们可以尝试修改这个配置文件: code /opt/homebrew/…...

2024年研究生数学建模“华为杯”E题——肘部法则、k-means聚类、目标检测(python)、ARIMA、逻辑回归、混淆矩阵(附:目标检测代码)

文章目录 一、情况介绍二、思路情况二、代码展示三、感受 一、情况介绍 前几天也是参加了研究生数学建模竞赛&#xff08;也就是华为杯&#xff09;&#xff0c;也是和本校的两个数学学院的朋友在网上组的队伍。昨天&#xff08;9.25&#xff09;通宵干完论文&#xff08;一条…...

绝了,自从用了它,我每天能多摸鱼2小时!

大家好&#xff0c;我是可乐。 俗话说的好&#xff1a;“摸鱼一时爽&#xff0c;一直摸鱼一直爽”。 作为一个程序员&#xff0c;是否有过调试代码熬到深夜&#xff1f;是否有过找不到解决方案而挠秃头顶&#xff1f; 但现在你即将要解放了&#xff0c;用了这款工具——秘塔…...

C语言指针系列1——初识指针

祛魅&#xff1a;其实指针这块儿并不难&#xff0c;有人说难只是因为基础到进阶没有处理好&#xff0c;大家要好好跟着一步一步学习&#xff0c;今天我们先来认识一下指针 指针定义&#xff1a;指针就是内存地址&#xff0c;指针变量是用来存放内存地址的变量&#xff0c;在同一…...

传神论文中心|第26期人工智能领域论文推荐

在人工智能领域的快速发展中&#xff0c;我们不断看到令人振奋的技术进步和创新。近期&#xff0c;开放传神&#xff08;OpenCSG&#xff09;传神社区发现了一些值得关注的成就。传神社区本周也为对AI和大模型感兴趣的读者们提供了一些值得一读的研究工作的简要概述以及它们各自…...

别再只盯着wx.login了!SpringBoot后端实战:用getPhoneNumber接口搞定小程序用户手机号绑定

微信小程序用户手机号绑定&#xff1a;SpringBoot后端深度实践指南 在当今移动互联网生态中&#xff0c;微信小程序已成为连接用户与服务的重要桥梁。对于需要强实名认证或直接触达用户的业务场景&#xff08;如电商交易、金融服务、政务办理等&#xff09;&#xff0c;仅依赖w…...

别再死记硬背公式了!用Python+NumPy手把手带你仿真RLC串联谐振(附代码)

用PythonNumPy动态仿真RLC串联谐振&#xff1a;告别枯燥公式&#xff0c;直观理解电路本质 当你第一次翻开电路分析教材&#xff0c;看到那些密密麻麻的公式推导和抽象的频率响应曲线时&#xff0c;是否感到一阵眩晕&#xff1f;RLC串联谐振作为电路分析的核心概念&#xff0c;…...

如何3步免费解锁WeMod专业版:2026年终极增强工具使用指南

如何3步免费解锁WeMod专业版&#xff1a;2026年终极增强工具使用指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 还在为WeMod专业版的订阅费用而犹豫…...

终极Windows Defender移除指南:13项核心服务的完整卸载方案

终极Windows Defender移除指南&#xff1a;13项核心服务的完整卸载方案 【免费下载链接】windows-defender-remover A tool which is uses to remove Windows Defender in Windows 8.x, Windows 10 (every version) and Windows 11. 项目地址: https://gitcode.com/gh_mirror…...

基于Kubernetes Lease构建分布式部署锁:解决CI/CD环境下的资源竞争

1. 项目概述&#xff1a;从“clawfight”看一场被遗忘的社区技术博弈看到“2019-02-18/clawfight”这个标题&#xff0c;很多人的第一反应可能是困惑。它不像一个标准的软件项目名&#xff0c;没有清晰的版本号&#xff0c;也没有指明具体的技术栈。但恰恰是这种看似随意的命名…...

如何在Windows 11上让经典游戏重获新生:DDrawCompat兼容性解决方案详解

如何在Windows 11上让经典游戏重获新生&#xff1a;DDrawCompat兼容性解决方案详解 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_m…...

基于Python/Flask的洗车店业务管理系统设计与实现

1. 项目概述&#xff1a;从“洗车”到“洗车服务”的数字化重构最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“washing-cars”。光看名字&#xff0c;你可能会觉得这只是一个关于洗车的小工具或者记录表。但当我深入进去&#xff0c;才发现它远不止于此。这个项目本质上…...

告别命令行启动!在Ubuntu 20.04上为Clion创建桌面快捷方式的保姆级教程

告别命令行启动&#xff01;在Ubuntu 20.04上为Clion创建桌面快捷方式的保姆级教程 每次打开Clion都要在终端输入./clion.sh&#xff1f;作为从Windows转战Linux的开发者&#xff0c;这种操作简直让人抓狂。本文将彻底解决这个痛点&#xff0c;手把手教你用.desktop文件创建专业…...

医院内外部人员管理系统

基于计算机视觉技术的医院人员综合管理解决方案&#xff0c;整合人脸识别考勤与行人流量监控两大核心能力&#xff0c;实现内部员工身份验证、自动打卡签到&#xff0c;以及公共区域人流量实时统计与可视化分析&#xff0c;提升医院管理效率与安全保障水平。 [&#x1f4fa; 系…...

OpenAI GPT Image 2文字准确率95%,企业视觉硬核生产力4大核心升级与商业落地路径

GPT Image 2的4大核心升级能力1. 文字渲染准确率接近95%&#xff0c;多语言直出即用过去用AI生图&#xff0c;最头疼的就是文字。写个中文标题&#xff0c;十次有八次是乱码&#xff0c;英文稍微长一点也会出错。而GPT Image 2的文字渲染准确率做到了接近95%&#xff0c;支持中…...