unity 鼠标实时画箭头
程序员文章站
2022-05-22 12:41:08
...
pc端的QQ与微信截图里都有个拖拽鼠标画箭头的功能以至于好做标注,其实unity也可以实现这个功能,亲测在webgl端与pc端可用,移动端由于感觉没意义没测试,博主觉得应该没啥问题,主要思路就是:箭头由线段和图片组成,鼠标可以实时改变箭头长短和方向(箭头的方向我暂时只是在2维下画的,绕着z轴实时旋转就行,一点向量基础就行),鼠标按下出现一个三角箭头,鼠标滑动就绘制出线段,线段可跟着你的鼠标变长变短,变粗这块博主很苦恼(因为男人嘛都要粗),由于最近一直在研究OpenGL,所以线段是用GL画的,性能这块没得说,dc不会随着线段的条数增加,unity没有提供变粗的方法,那就忍忍吧,bb了这么多看起来很厉害吧!来张图压压惊:
效果看了那就直接看脚本了?
using UnityEngine;
using System.Collections;
public class LinesGL : MonoBehaviour
{
private Shader shader;
private static Material m;
private GameObject g;//便于查看当前点的坐标信息
public Vector3[] lp;//存储的点
private Vector3 s;//开始点
public GameObject JT;
private GameObject go;
private Vector3 Vxyz;
void Start()
{
shader = Shader.Find("Yogi3/ImageEffect/Occlusion");
m = new Material(shader);
m.SetColor("_MainColor", new Color(1f, 0.01f, 0.1f, 1f));//修改shader颜色
g = new GameObject("g");
lp = new Vector3[0];
Vxyz = new Vector3(2,0,0);//平行于X轴向量
}
void Update()
{
Vector3 e;//结束点
if (Input.GetMouseButtonDown(0))
{
s = GetNewPoint();
//显示的z轴看自己需求赋值,只要在相机前面就行
go=Instantiate(JT, Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.z * -1.0f) ), Quaternion.identity)as GameObject;
}
//拖拽便于确定箭头方向
if (Input.GetMouseButton(0))
{
e = GetNewPoint();
lp = AddLine(lp, s, e, true);
go.transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.z * -1.0f));
Vector3 Vangle = lp[lp.Length-1] - lp[lp.Length - 2];//最后一条线段
float angle = Vector3.Angle(Vangle,Vxyz)-90;//三角箭头绕着Z轴旋转 那么就限制与X轴夹角为旋转角度吧
if (Vangle.y > 0)
{
go.transform.eulerAngles = new Vector3(0, 0, angle);
}
else
{
go.transform.eulerAngles = new Vector3(0, 0, 180-angle);
}
}
if (Input.GetMouseButtonUp(0))
{
e = GetNewPoint();
lp = AddLine(lp, s, e, false);
}
}
//判断最后一个点是否鼠标抬起确定了,确定了就存储起来,没有就删除,但是都会绘制出来(绘制了就删除刷新)
Vector3[] AddLine(Vector3[] l, Vector3 s, Vector3 e, bool tmp)
{
int vl = l.Length;
if (!tmp || vl == 0) l = resizeVertices(l, 2);
else vl -= 2;
l[vl] = s;
l[vl + 1] = e;
return l;
}
//处理拖拽的线条,实时更新
Vector3[] resizeVertices(Vector3[] ovs, int ns)
{
Vector3[] nvs = new Vector3[ovs.Length + ns];
for (int i = 0; i < ovs.Length; i++) nvs[i] = ovs[i];
return nvs;
}
//反转坐标
Vector3 GetNewPoint()
{
return g.transform.InverseTransformPoint(
Camera.main.ScreenToWorldPoint(
new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.z * -1.0f)
)
);
}
void OnPostRender()
{
m.SetPass(0);
GL.PushMatrix();
GL.MultMatrix(g.transform.transform.localToWorldMatrix);
GL.Begin(GL.LINES);
for (int i = 0; i < lp.Length; i++)
{
GL.Vertex3(lp[i].x, lp[i].y, lp[i].z);
}
GL.End();
GL.PopMatrix();
}
}
其实我想说说shader的在看看效果:
线段shader的是自己写的,图片的shader是默认的,是的没错,线段是透视的,不会被物体挡住的,但是会被UI挡住,最近迷上了图形学,捣鼓了大变天实现了屎样的效果,简直了,顺便贴出shader,
Shader "Yogi3/ImageEffect/Occlusion"
{
Properties
{
_MainTex("Base (RGB)", 2D) = "white" {}
_DepthMap("DepthMap (RGB)", 2D) = "white" {}
_OcclusionMap("OcclusionMap (RGB)", 2D) = "white" {}
_Intensity("Intensity", Float) = 0.0
_Tiling("Tiling", Vector) = (1.0, 1.0, 0.0, 0.0)
_MainColor("MainsColor",Color)=(1,1,1,1)
}
SubShader
{
Pass
{
ZTest Always
ZWrite Off
Cull Off
Fog{ Mode Off }
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
sampler2D _MainTex;
sampler2D _DepthMap;
sampler2D _OcclusionMap;
sampler2D _CameraDepthNormalsTexture;
fixed4 _MainTex_TexelSize;
fixed _Intensity;
fixed _Power;
fixed4 _Tiling;
fixed4 _MainColor;
struct a2v
{
fixed4 vertex : POSITION;
fixed2 texcoord : TEXCOORD0;
};
struct v2f
{
fixed4 vertex : SV_POSITION;
fixed2 uv : TEXCOORD0;
};
v2f vert(a2v v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 c = tex2D(_MainTex, i.uv);
fixed4 depthMap = tex2D(_DepthMap, i.uv);
fixed depth = DecodeFloatRG(depthMap.zw);
fixed3 normal = DecodeViewNormalStereo(depthMap);
fixed4 cameraDepthMap = tex2D(_CameraDepthNormalsTexture, i.uv);
fixed cameraDepth = DecodeFloatRG(cameraDepthMap.zw);
fixed4 o = c;
if (depth > 0
&& cameraDepth < depth)
{
fixed2 uv = i.uv * _Tiling.xy + _Tiling.zw;
fixed3 color = tex2D(_OcclusionMap, uv);
fixed nf = saturate(dot(normal, fixed3(0, 0, 1)));
nf = pow(nf, _Intensity);
o.rgb = lerp(color, c.rgb, nf)+_MainColor;
}
return _MainColor;
//return o;
}
ENDCG
}
}
Fallback off
}
上一篇: 使用Python画作业调度甘特图
下一篇: Matlab画机器作业甘特图(区间数)
推荐阅读