文章目录
一、前言
嗨,大家好,我是新发。昨天写了篇文章:《使用Unity ShaderGraph实现在模型上涂鸦的效果,那么,纹个手吧》。
这个原理,可以触类旁通,比如刮刮乐的刮卡效果,也可以利用这个原理来实现,今天就教大家如何使用Unity Shadergraph
实现刮刮乐的刮卡剔除效果。
声明:本文介绍的办法不是做刮刮乐效果的最好办法,只是单纯地进行演示。
本文最终效果如下:
本文
Demo
工程已上传到CodeChina
(最近GitHub
貌似有问题,经常连不上),感兴趣的同学可自行下载学习。CodeChina
地址:https://codechina.csdn.net/linxinfa/UnityShaderGraphScratchTicket
注意,我使用的Unity
版本是2020.2.7f1c1
,Shadergraph
版本是Version 10.3.2 - march 01,2021
,如果你使用的版本比我的版本低,则可能运行我的Demo
工程会有问题。
二、原理
原理就是利用Alpha
通道,Alpha
为0
时透明,我们可以使用一张RenderTexture
作为Alpha
通道图,与UI
的主贴图的Alpha
通道图相乘即可。
根据鼠标刮的位置,在RenderTexture
上对应的位置画笔刷印记即可。
三、实操
1、RenderTexture
首先,创建一个Render Texture
。
设置一下
Render Texture
的尺寸和格式。2、笔刷图案
用photoshop
做两张图,一张纯黑色的方图(用于初始化填充Render Texture
),一张笔刷图,简单起见,笔刷图案我就用一个白点。
如下:
3、写脚本:ScratchUI.cs
开始写代码,就一个脚本:ScratchUI.cs
。代码的注释我写得比较清晰了,大家应该能看懂。
代码如下:
// ScratchUI.cs
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// 刮刮乐UI
/// </summary>
public class ScratchUI : MonoBehavIoUr, IPointerDownHandler, IPointerUpHandler
{
/// <summary>
/// 绘制的目标图片
/// </summary>
public RenderTexture renderTexture;
/// <summary>
/// 笔刷
/// </summary>
public Texture brushTexture;
/// <summary>
/// 空白图
/// </summary>
public Texture blankTexture;
/// <summary>
/// mask的RectTransform
/// </summary>
public RectTransform rectTransform;
/// <summary>
/// 画布
/// </summary>
public Canvas canvas;
private bool m_isMove = false;
private void Start()
{
DrawBlank();
}
/// <summary>
/// 初始化RenderTexture
/// </summary>
private void DrawBlank()
{
// 激活rt
RenderTexture.active = renderTexture;
// 保存当前状态
GL.Pushmatrix();
// 设置矩阵
GL.LoadPixelMatrix(0, renderTexture.width, renderTexture.height, 0);
// 绘制贴图
Rect rect = new Rect(0, 0, renderTexture.height);
Graphics.DrawTexture(rect, blankTexture);
// 弹出改变
GL.PopMatrix();
RenderTexture.active = null;
}
/// <summary>
/// 在RenderTexture的(x,y)坐标处画笔刷图案
/// </summary>
/// <param name="x">Graphics坐标系下的x</param>
/// <param name="y">Graphics坐标系下的y</param>
private void Draw(int x, int y)
{
// 激活rt
RenderTexture.active = renderTexture;
// 保存当前状态
GL.Pushmatrix();
// 设置矩阵
GL.LoadPixelMatrix(0, 0);
// 绘制笔刷图案
x -= (int)(brushTexture.width * 0.5f);
y -= (int)(brushTexture.height * 0.5f);
Rect rect = new Rect(x, y, brushTexture.width, brushTexture.height);
Graphics.DrawTexture(rect, brushTexture);
// 弹出改变
GL.PopMatrix();
RenderTexture.active = null;
}
/// <summary>
/// 按下
/// </summary>
public void OnPointerDown(PointerEventData data)
{
m_isMove = true;
}
/// <summary>
/// 抬起
/// </summary>
public void OnPointerUp(PointerEventData data)
{
m_isMove = false;
}
private void Update()
{
if (m_isMove)
{
OnMouseMove(Input.mousePosition);
}
}
/// <summary>
/// 刮卡
/// </summary>
/// <param name="position">刮卡的屏幕坐标</param>
private void OnMouseMove(Vector2 position)
{
// 获取刮的位置的ui局部坐标
var uiLocalPos = ScreenPosToUiLocalPos(position, rectTransform, canvas.worldCamera);
// 将局部坐标转化为uv坐标
var uvX = (rectTransform.sizeDelta.x / 2f + uiLocalPos.x) / rectTransform.sizeDelta.x;
var uvY = (rectTransform.sizeDelta.y / 2f + uiLocalPos.y) / rectTransform.sizeDelta.y;
// 将uv坐标转化为Graphics坐标
var x = (int)(uvX * renderTexture.width);
// 注意,uv坐标系和Graphics坐标系的y轴方向相反
var y = (int)(renderTexture.height - uvY * renderTexture.height);
Draw(x, y);
}
/// <summary>
/// 将屏幕坐标抓话为目标RectTransform的局部坐标
/// </summary>
/// <param name="screenPos">屏幕坐标</param>
/// <param name="transform">目标RectTransform</param>
/// <param name="cam">摄像机</param>
/// <returns>ui局部坐标</returns>
private Vector2 ScreenPosToUiLocalPos(Vector3 screenPos, RectTransform transform, Camera cam)
{
Vector2 uiLocalPos;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(transform, screenPos, cam, out uiLocalPos))
{
return uiLocalPos;
}
return Vector2.zero;
}
}
4、Shadergraph
创建一个Unlit Shadergraph
,实现UI
主贴图的Alpha
通道与和RenderTexture
的相乘。
注意
Graph Settings
设置Surface
为Transparent
,Blend
设置为Alpha
。暴露出两个变量,方便在材质球中设置参数。
5、UI制作
准备刮刮乐的UI
图片,导入Unity
中。
拼成界面,如下。
mask
层就是要被刮掉的层。6、材质球
创建一个材质球ScratchMaterial
,使用上面做的Shadergraph
,给材质球赋值贴图。
最后将材质赋给
mask
的Material
。7、挂脚本
将ScratchUI.cs
脚本挂到mask
上,并设置好参数。RenderTexture
:用于Alpha
通道图;Brush Texture
:笔刷图案,一个白点;Blank Texture
:一张纯黑色的空白图;RectTransform
:mask
的RectTransform
,用于坐标转换;Canvas
:用于坐标转换。
四、运行测试
运行Unity
,测试效果如下:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。