Unity Shader 使用鼠标绘制自由多边形
2017-01-04 22:47
260 查看
原文链接 : http://www.manew.com/thread-98660-1-1.html
效果:
注意,基于 unity 5.4.1 或以上版本
shader 代码:
C#绘制代码:
效果:
注意,基于 unity 5.4.1 或以上版本
shader 代码:
Shader "Unlit/polygon" { Properties { //定义基本属性,可以从编辑器里面进行设置的变量 // _MainTex ("Texture", 2D) = "white" {} } CGINCLUDE //从应用程序传入顶点函数的数据结构定义 struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; //从顶点函数传入片段函数的数据结构定义 struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; //定义贴图变量 sampler2D _MainTex; // float4 _MainTex_ST; //定义与脚本进行通信的变量 vector Value[8]; int PointNum =0; //计算两点间的距离的函数 float Dis(float4 v1,float4 v2) { return sqrt(pow((v1.x-v2.x),2)+pow((v1.y-v2.y),2)); } //绘制线段 bool DrawLineSegment(float4 p1, float4 p2, float lineWidth,v2f i) { float4 center = float4((p1.x+p2.x)/2,(p1.y+p2.y)/2,0,0); //计算点到直线的距离 float d = abs((p2.y-p1.y)*i.vertex.x + (p1.x - p2.x)*i.vertex.y +p2.x*p1.y -p2.y*p1.x )/sqrt(pow(p2.y-p1.y,2) + pow(p1.x-p2.x,2)); //小于或者等于线宽的一半时,属于直线范围 float lineLength = sqrt(pow(p1.x-p2.x,2)+pow(p1.y-p2.y,2)); if(d<=lineWidth/2 && Dis(i.vertex,center)<lineLength/2) { return true; } return false; } //绘制多边形,这里限制了顶点数不超过6。可以自己根据需要更改。 bool pnpoly(int nvert, float4 vert[8], float testx, float testy) { int i, j; bool c=false; float vertx[6]; float verty[6]; for(int n=0;n<nvert;n++) { vertx = vert .x; verty = vert .y; } for (i = 0, j = nvert-1; i < nvert; j = i++) { if ( ((verty[i]>testy) != (verty[j]>testy)) && (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) ) c = !c; } return c; } v2f vert (appdata v) { v2f o; //将物体顶点从模型空间换到摄像机剪裁空间,也可采用简写方式——o.vertex = UnityObjectToClipPos(v.vertex); o.vertex = mul(UNITY_MATRIX_MVP,v.vertex); //2D UV坐标变换,也可以采用简写方式——o.uv = TRANSFORM_TEX(v.uv, _MainTex); //o.uv = v.uv.xy * _MainTex_ST.xy + _MainTex_ST.zw; return o; } fixed4 frag (v2f i) : SV_Target { //绘制多边形顶点 for(int j=0;j<PointNum;j++) { if(Dis(i.vertex, Value[j])<3) { return fixed4(1,0,0,0.5); } } //绘制多边形的边 for(int k=0;k<PointNum;k++) { if(k==PointNum-1) { if(DrawLineSegment(Value[k],Value[0],2,i)) { return fixed4(1,1,0,0.5); } } else { if(DrawLineSegment(Value[k],Value[k+1],2,i)) { return fixed4(1,1,0,0.5); } } } //填充多边形内部 if(pnpoly(PointNum, Value,i.vertex.x ,i.vertex.y)) { return fixed4(0,1,0,0.3); } return fixed4(0,0,0,0); //fixed4 col = tex2D(_MainTex, i.uv); //return col; } ENDCG SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { //选取Alpha混合方式 Blend SrcAlpha OneMinusSrcAlpha //在CGPROGRAM代码块中写自己的处理过程 CGPROGRAM //定义顶点函数和片段函数的入口分别为vert和frag #pragma vertex vert #pragma fragment frag //包含基本的文件,里面有一些宏定义和基本函数 #include "UnityCG.cginc" ENDCG } } }
C#绘制代码:
using UnityEngine; using System.Collections; [ExecuteInEditMode] public class Polygon : MonoBehaviour { public Material mat; //绑定材质 Vector3[] worldPos; //存储获取的3D坐标 Vector4[] screenPos; //存储待绘制的多边形顶点屏幕坐标 int maxPointNum=8; //多边形顶点总数 int currentpointNum =0; //当前已经获得的顶点数 int pointNum2Shader =0; //传递顶点数量给shader bool InSelection=true; //是否处于顶点获取过程 void Start () { worldPos = new Vector3[maxPointNum]; screenPos = new Vector4[maxPointNum]; } void Update () { mat.SetVectorArray("Value",screenPos); //传递顶点屏幕位置信息给shader mat.SetInt ("PointNum",pointNum2Shader); //传递顶点数量给shader //使用摄像机发射一条射线,以获取要选择的3D位置 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, 100)) { Debug.DrawLine(ray.origin, hit.point); } //利用鼠标点击来获取位置信息 if (Input.GetMouseButtonDown (0)&& InSelection) { if (currentpointNum < maxPointNum) { currentpointNum++; pointNum2Shader++; worldPos[currentpointNum-1] = hit.point; Vector3 v3 = Camera.main.WorldToScreenPoint (worldPos [currentpointNum-1]); screenPos[currentpointNum-1] = new Vector4(v3.x,Screen.height-v3.y,v3.z,0); } else { InSelection = false; } } //实时更新已选择的3D点的屏幕位置 for (int i = 0; i < maxPointNum; i++) { Vector3 v3 = Camera.main.WorldToScreenPoint (worldPos[i]); screenPos[i] = new Vector4(v3.x,Screen.height-v3.y,v3.z,0); } //检测是否有3D点移动到了摄像机后面,如果有,则停止绘制 for (int i = 0; i < currentpointNum; i++) { if (Vector3.Dot(worldPos[i]- Camera.main.transform.position,Camera.main.transform.forward)<=0) { pointNum2Shader=0; break; } pointNum2Shader= currentpointNum; } } //抓取当前的渲染图像进行处理 void OnRenderImage(RenderTexture src, RenderTexture dest) { Graphics.Blit(src, dest, mat); } }
相关文章推荐
- 【Unity Shader学习笔记】(五)使用鼠标绘制自由多边形(附完整工程源码)
- 【Bing Map学习系列】(6)——如何使用Bing Maps Silverlight Control绘制多边形
- 【转】Flex4 中skinclass使用Path绘制多边形
- opencv2 使用鼠标绘制矩形并截取和保存矩形区域图像
- Opencv用鼠标绘制填充多边形
- 使用jTopo给Html5 Canva中绘制的元素添加鼠标事件_html5教程技巧
- 使用鼠标自由旋转三维图形的算法和思路
- 使用View绘制矩形,多边形
- 使用鼠标(像QQ截图一样)自由截取Unity程序中的任意地方 && 获取本地文件夹下的所有图片
- 使用jTopo给Html5 Canva中绘制的元素添加鼠标事件
- opencv-- 使用鼠标绘制矩形并截取和保存矩形区域图像
- 使用View绘制矩形,多边形
- 在MFC下绘制直线,使用橡皮筋技术,可以使直线效果跟随鼠标移
- 使用html5,鼠标绘制贝赛尔曲线
- opencv2 使用鼠标绘制矩形并截取和保存矩形区域图像
- WEB前端使用VML绘制多边形
- vc 使用api绘制多边形
- opencv2 使用鼠标绘制矩形并截取和保存矩形区域图像
- 使用jTopo给Html5 Canva中绘制的元素添加鼠标事件_html5教程技巧
- 百度地图 鼠标绘制,获取矩形,多边形的顶点经纬度