标签:第一个 add sharp ams log 校正 五子棋 off include
尊重原创,转载请注明出处凯尔八阿哥专栏
上一章点击打开链接中已经画出了一个棋盘网格,首先来完善一下这个画网格的Shader,添加属性,属性包括网格的线的宽度,网格的颜色等。代码如下:
Shader "Unlit/Chapter2-2"
{
	Properties
	{
		_backgroundColor("面板背景色",Color) = (1.0,1.0,1.0,1.0)
		_axesColor("坐标轴的颜色",Color) = (0.0,0.0,1.0)
		_gridColor("网格的颜色",Color) = (0.5,0.5,0.5)
		_tickWidth("网格的密集程度",Range(0.1,1))=0.1
		_gridWidth("网格的宽度",Range(0.0001,0.01))=0.008
		_axesXWidth("x轴的宽度",Range(0.0001,0.01))=0.006
		_axesYWidth("y轴的宽度",Range(0.0001,0.01))=0.007
	}
	SubShader
	{
		//去掉遮挡和深度缓冲
		Cull Off
		ZWrite Off
		//开启深度测试
		ZTest Always
		CGINCLUDE
		//添加一个计算方法
		float mod(float a,float b)
		{
			//floor(x)方法是Cg语言内置的方法,返回小于x的最大的整数
			return a - b*floor(a / b);
		}
		ENDCG
		Pass
		{
			CGPROGRAM
			//敲代码的时候要注意:“CGPROGRAM”和“#pragma...”中的拼写不同,真不知道“pragma”是什么单词
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			uniform float4 _backgroundColor;
			uniform float4 _axesColor;
			uniform float4 _gridColor;
			uniform float _tickWidth;
			uniform float _gridWidth;
			uniform float _axesXWidth;
			uniform float _axesYWidth;
			struct appdata
			{
				float4 vertex:POSITION;
				float2 uv:TEXCOORD0;
			};
			struct v2f
			{
				float2 uv:TEXCOORD0;
				float4 vertex:SV_POSITION;
			};
			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
				o.uv = v.uv;
				return o;
			}
			fixed4 frag(v2f i) :SV_Target
			{
				//将坐标的中心从左下角移动到网格的中心
				fixed2 r = 2.0*fixed2(i.uv.x - 0.5,i.uv.y - 0.5);
				fixed3 backgroundColor = _backgroundColor.xyz;
				fixed3 axesColor = _axesColor.xyz;
				fixed3 gridColor = _gridColor.xyz;
				fixed3 pixel = backgroundColor;
				//定义网格的的宽度
				const float tickWidth = _tickWidth;
				if (mod(r.x, tickWidth) < _gridWidth)
				{
					pixel = gridColor;
				}
				if (mod(r.y, tickWidth) < _gridWidth)
				{
					pixel = gridColor;
				}
				//画两个坐标轴
				if (abs(r.x) < _axesXWidth)
				{
					pixel = axesColor;
				}
				if (abs(r.y) < _axesYWidth)
				{
					pixel = axesColor;
				}
				return fixed4(pixel, 1.0);
			}
				ENDCG
		}
	}
}
通过以下代码将网格的轴心移动到中心位置
fixed2 r = 2.0*fixed2(i.uv.x - 0.5,i.uv.y - 0.5);效果图如图所示:
原理:圆的方程为(x-a)^2+(y-b)^2=r^2,根据方程即可以添加如下方法来计算预定圆盘的颜色值信息
//添加第二个计算方法,根据半径,原点、原点的偏移量r和颜色来绘制圆盘	
		fixed3 disk(fixed2 r,fixed2 center,fixed radius,fixed3 color,fixed3 pixel)
		{
			fixed3 col=pixel;
			if (length(r - center) < radius)
			{
				col = color;
			}
			return col;
		}效果如图所示:
Shader "Unlit/Chapter3-2"
{
	Properties
	{
		_backgroundColor("面板背景色",Color) = (1.0,1.0,1.0,1.0)
		_col1("圆盘1的颜色",Color) = (0.216, 0.471, 0.698) // blue
		_col2("圆盘2的颜色",Color) = (1.00, 0.329, 0.298) // red
		_col3("圆盘3的颜色",Color) = (0.867, 0.910, 0.247) // yellow
		_center2X("第三个圆盘的原点X的位置",Range(0.0,1.0)) = 0.9
		_center2Y("第三个圆盘的原点Y的位置",Range(0.0,1.0)) = -0.4
		_radius1("第一个圆盘的半径",Range(0.1,1)) = 0.8
		_radius2("第二个圆盘的半径", Range(0.1, 1)) = 0.3
		_radius3("第三个圆盘的半径", Range(0.1, 1)) = 0.6
	}
	SubShader
	{
		//去掉遮挡和深度缓冲
		Cull Off
		ZWrite Off
		//开启深度测试
		ZTest Always
		CGINCLUDE
		//添加一个计算方法
		float mod(float a,float b)
		{
			//floor(x)方法是Cg语言内置的方法,返回小于x的最大的整数
			return a - b*floor(a / b);
		}
		//添加第二个计算方法,根据半径,原点、原点的偏移量r和颜色来绘制圆盘	
		fixed3 disk(fixed2 r,fixed2 center,fixed radius,fixed3 color,fixed3 pixel)
		{
			fixed3 col=pixel;
			if (length(r - center) < radius)
			{
				col = color;
			}
			return col;
		}
		ENDCG
		Pass
		{
			CGPROGRAM
			//敲代码的时候要注意:“CGPROGRAM”和“#pragma...”中的拼写不同,真不知道“pragma”是什么单词
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			uniform float4 _backgroundColor;
			uniform float4 _col1;
			uniform float4 _col2;
			uniform float4 _col3;
			uniform float _radius1;
			uniform float _radius2;
			uniform float _radius3;
			uniform float _center2X;
			uniform float _center2Y;
		struct appdata
		{
			float4 vertex:POSITION;
			float2 uv:TEXCOORD0;
		};
		struct v2f
		{
			float2 uv:TEXCOORD0;
			float4 vertex:SV_POSITION;
		};
		v2f vert(appdata v)
		{
			v2f o;
			o.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
			o.uv = v.uv;
			return o;
		}
	
		fixed4 frag(v2f i) :SV_Target
		{
			float2 r = 2.0*(i.uv - 0.5);
			float aspectRatio = _ScreenParams.x / _ScreenParams.y;
			r.x *= aspectRatio;
			fixed3 backgroundColor = _backgroundColor.xyz;
			fixed3 col1 = _col1.xyz;
			fixed3 col2 = _col2.xyz;
			fixed3 col3 = _col3.xyz;
			fixed3 pixel = _backgroundColor;
			//画第一个圆盘
			pixel = disk(r,fixed2(0.1,0.3), _radius1,col3,pixel);
			//画第二个圆盘
			pixel= disk(r, fixed2(_center2X, _center2Y), _radius2, col2, pixel);
			//画第三个圆盘
			pixel= disk(r, fixed2(-0.8, 0.6), _radius3, col1, pixel);
			return fixed4(pixel, 1.0);
		}
		ENDCG
	}
	}
}
void Update () {
        if(Input.GetMouseButtonDown(0))
        {
            vec_mouseBtnPos = Input.mousePosition;
            //将鼠标的位置除以屏幕参数得到范围为0~1的坐标范围
            vec_mouseBtnPos = new Vector2(vec_mouseBtnPos.x / Screen.width, vec_mouseBtnPos.y / Screen.height);
            //设定坐标原点为中点
            vec_mouseBtnPos -= new Vector2(0.5f,0.5f);
            vec_mouseBtnPos *= 2;
            vec_mouseBtnPos.y = -vec_mouseBtnPos.y;}基本上和Shader代码中的计算方法相同,得到的效果图如图所示:using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 这个脚本实现的点击单个点的效果
/// </summary>
public class GameControl : MonoBehaviour {
    public Material mat;
    //设置点中的最小误差
    public float clickMinError;
    //网格点的坐标集
    private List<Vector2> list_gridIntersectionPos = new List<Vector2>();
    //网格点的数量
    private int gridIntersectionNums;
    private float gridSpace;
    private Vector2 vec_mouseBtnPos;
    // Use this for initialization
    void Start()
    {
        gridSpace = mat.GetFloat("_tickWidth");
        //单个坐标轴上网格点的数量等于横轴坐标间距除以网格间距
        gridIntersectionNums = (int)Mathf.Floor(1.0f / gridSpace); //这里不能只用强制类型转换,如果使用强制类型转换会丢失数据,比如1.0/0.1最后的结果是9
        for (int i = -gridIntersectionNums; i <= gridIntersectionNums; i++)
        {
            float x = gridSpace * i;
            for (int j = -gridIntersectionNums; j <= gridIntersectionNums; j++)
            {
                float y = gridSpace * j;
                list_gridIntersectionPos.Add(new Vector2(x, y));
            }
        }
    }
	
	// Update is called once per frame
	void Update () {
        if(Input.GetMouseButtonDown(0))
        {
            vec_mouseBtnPos = Input.mousePosition;
            //将鼠标的位置除以屏幕参数得到范围为0~1的坐标范围
            vec_mouseBtnPos = new Vector2(vec_mouseBtnPos.x / Screen.width, vec_mouseBtnPos.y / Screen.height);
            //设定坐标原点为中点
            vec_mouseBtnPos -= new Vector2(0.5f,0.5f);
            vec_mouseBtnPos *= 2;
            vec_mouseBtnPos.y = -vec_mouseBtnPos.y;
          /*  mat.SetFloat("_MouseBtnPosX", vec_mouseBtnPos.x);
            mat.SetFloat("_MouseBtnPosY", vec_mouseBtnPos.y);*/
               //如果点中了网格的交叉点出就显示圆点
               int index = CheckClikedIntersection(vec_mouseBtnPos);
               if (index != -1)
               {
                   //将准确的网格点的位置赋值给vec_mouseBtnPos
                   vec_mouseBtnPos = list_gridIntersectionPos[index];
                   mat.SetFloat("_MouseBtnPosX", vec_mouseBtnPos.x);
                   mat.SetFloat("_MouseBtnPosY", vec_mouseBtnPos.y);  
               }
               Debug.Log("x:" + vec_mouseBtnPos.x + "y:" + vec_mouseBtnPos.y);
        }
	
	}
    /// <summary>
    /// 判断鼠标点中的地方是否在网格的交叉点处
    /// </summary>
    /// <param name="vec2"></param>
    /// <returns></returns>
    private int CheckClikedIntersection(Vector2 vec2)
    {
        int clickIndex = -1;
        for (int i = 0; i < list_gridIntersectionPos.Count; i++)
        {
            float errorx = Mathf.Abs(vec2.x- list_gridIntersectionPos[i].x);
            float errory = Mathf.Abs(vec2.y - list_gridIntersectionPos[i].y);
            //如果误差的值小于预设的值则判定点中了
            float error = Mathf.Sqrt(errorx * errorx + errory * errory);
            if(error<clickMinError)
            {
                clickIndex = i;
                break;
            }
        }
        return clickIndex;
    }
}
这里使用了“CheckClikedIntersection”方法来进行判断和校正,并设置了一个最小误差“clickMinError”。Shader "Unlit/Backgammon"
{
	Properties
	{
		_backgroundColor("面板背景色",Color) = (1.0,1.0,1.0,1.0)
		_axesColor("坐标轴的颜色",Color) = (0.0,0.0,1.0)
		_gridColor("网格的颜色",Color) = (0.5,0.5,0.5)
		_tickWidth("网格的间距",Range(0.1,1)) = 0.1
		_gridWidth("网格的宽度",Range(0.0001,0.01)) = 0.008
		_axesXWidth("x轴的宽度",Range(0.0001,0.01)) = 0.006
		_axesYWidth("y轴的宽度",Range(0.0001,0.01)) = 0.007
		_MouseBtnPosX("鼠标点击的X方向位置",float) = 0.0
		_MouseBtnPosY("鼠标点击的Y方向位置",float) = 0.0
		_MouseBtnRadius("鼠标点中位置圆盘的半径",float) = 0.001
		_MouseDownColor("鼠标点中的颜色",Color) = (1.00, 0.329, 0.298,1.0)
	}
	SubShader
	{
		//去掉遮挡和深度缓冲
		Cull Off
		ZWrite Off
		//开启深度测试
		ZTest Always
		CGINCLUDE
		//添加一个计算方法
		float mod(float a,float b)
		{
			//floor(x)方法是Cg语言内置的方法,返回小于x的最大的整数
			return a - b*floor(a / b);
		}
		//添加第二个计算方法,根据半径,原点和颜色来绘制圆盘	
		fixed3 disk(fixed2 r,fixed2 center,fixed radius,fixed3 color,fixed3 pixel)
		{
			fixed3 col = pixel;
			if (length(r - center) < radius)
			{
				col = color;
			}
			return col;
		}
		ENDCG
		Pass
		{
			CGPROGRAM
			//敲代码的时候要注意:“CGPROGRAM”和“#pragma...”中的拼写不同,真不知道“pragma”是什么单词
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			uniform float4 _backgroundColor;
			uniform float4 _axesColor;
			uniform float4 _gridColor;
			uniform float _tickWidth;
			uniform float _gridWidth;
			uniform float _axesXWidth;
			uniform float _axesYWidth;
			uniform float _MouseBtnPosX;
			uniform float _MouseBtnPosY;
			uniform float _MouseBtnRadius;
			uniform float4 _MouseDownColor;
			struct appdata
			{
				float4 vertex:POSITION;
				float2 uv:TEXCOORD0;
			};
			struct v2f
			{
				float2 uv:TEXCOORD0;
				float4 vertex:SV_POSITION;
			};
			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
				o.uv = v.uv;
				return o;
			}
			fixed4 frag(v2f i) :SV_Target
			{
				//将坐标的中心从左下角移动到网格的中心
				float2 r = 2.0*(i.uv - 0.5);
				float aspectRatio = _ScreenParams.x / _ScreenParams.y;
				//r.x *= aspectRatio;
				fixed3 backgroundColor = _backgroundColor.xyz;
				fixed3 axesColor = _axesColor.xyz;
				fixed3 gridColor = _gridColor.xyz;
				fixed3 pixel = backgroundColor;
				//定义网格的的间距
				const float tickWidth = _tickWidth;
				if (mod(r.x, tickWidth) < _gridWidth)
				{
					pixel = gridColor;
				}
				if (mod(r.y, tickWidth) < _gridWidth)
				{
					pixel = gridColor;
				}
				//画两个坐标轴
				if (abs(r.x) < _axesXWidth)
				{
					pixel = axesColor;
				}
				if (abs(r.y) < _axesYWidth)
				{
					pixel = axesColor;
				}
				//画一个点
				pixel = disk(r, fixed2(_MouseBtnPosX, _MouseBtnPosY), _MouseBtnRadius, _MouseDownColor, pixel);
				return fixed4(pixel, 1.0);
			}
			ENDCG
		}
	}
}
代码中添加了用来接收C#脚本传递的鼠标点击的位置标签:第一个 add sharp ams log 校正 五子棋 off include
原文地址:http://blog.csdn.net/zhangxiao13627093203/article/details/52966213