在Unity中实现数学坐标系Shader(一)

本节教程为南京字节工坊原创文章,转载请留此信息:https://blog.csdn.net/gcj2450/article/details/104523738

南京字节工坊,专业从事各类互动软件定制开发,三维可视化应用开发定制,VR,AR类互动应用定制开发。

今天我们来学习通过Unity Shader实现数学直角坐标系的Shader,以让大家更加熟悉Unity Shader中常用的数学方法。数学坐标系由XY轴,XY轴方向的箭头以及单位网格构成。最终效果如下图

第一步我们使用基本的数学方法来绘制方格。在Unity中新建一个Unlit Shader。删除_MainTexture属性及相关的变量,定义网格shader所需的属性。属性定义如下所示

Properties
    {
        //背景色
        _BgColor("BgColor",color)=(1,1,1,1)
        //十分线颜色
        _LinesColor("LinesColor",color) = (0.70.70.7,1.0)
        //次级线颜色
        _SubLinesColor("SubLinesColor",color)=(0.950.950.95,1.0)
        //缩放
        _Scale("Scale",range(1,100)) = 10
        _Subdiv("Subdiv",range(1,10)) = 10
    }

这里的属性分别是背景色,十分线颜色,次级线的颜色,缩放值和最小刻度细分值。

在Fragment Shader中输入如下代码

               vec2 pos = i.uv;

定义一个pos变量,并将其缩放。
                pos *= _Scale;

通过取余运算,得到重复的值,加入_Scale=10,将在0-1之间重复10次
                pos=frac(pos);
               
                vec4 fragColor =  _BgColor;

通过step方法,返回左下角的值,这里step方法,相当于if判断,

step(a, x)Returns (x >= a) ? 1 : 0

               vec2 bl = step(0.01,pos);       // 左下
                vec2 tr = step(0.01,1.0-pos);   // 右上

将上面两次运算的结果相乘,就会得到全部>0的位置
                float alpha =bl.x * bl.y * tr.x * tr.y;

再通过mix方法,混合线的颜色和基础色。
                fragColor = mix(fragColor, _LinesColor, 1-alpha);
                将pos放大Subdiv倍,重复上面运算,得到十分位刻度的方格
                vec2 bl2 = step(0.01,frac(pos*_Subdiv));       // 左下
                vec2 tr2 = step(0.01,1.0-frac(pos*_Subdiv));   // 右上
                float alpha2 =bl2.x * bl2.y * tr2.x * tr2.y;
                fragColor = mix(fragColor, _SubLinesColor, 1-alpha2);
                返回最终颜色。
                
                return fragColor;

得到的最终上述效果完成后,得到最终效果如下:下图_Scale=2,_Subdive=5

完整代码如下:

Shader "Unlit/StepGrid"
{
    Properties
    {
        //背景色
        _BgColor("BgColor",color)=(1,1,1,1)
        //十分线颜色
        _LinesColor("LinesColor",color) = (0.70.70.7,1.0)
        //次级线颜色
        _SubLinesColor("SubLinesColor",color)=(0.950.950.95,1.0)
        //缩放
        _Scale("Scale",range(1,100)) = 10
        _Subdiv("Subdiv",range(1,10)) = 10
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define vec2 half2
            #define vec3 half3
            #define vec4 half4
            #define mix lerp
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            float _Scale;
            float _Subdiv;

            fixed4 _BgColor;
            fixed4 _LinesColor;
            fixed4 _SubLinesColor;


            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                vec2 pos = i.uv;
                pos *= _Scale;
                pos=frac(pos);
                
                vec4 fragColor =  _BgColor;
                vec2 bl = step(0.01,pos);       // 左下
                vec2 tr = step(0.01,1.0-pos);   // 右上
                float alpha =bl.x * bl.y * tr.x * tr.y;
                fragColor = mix(fragColor, _LinesColor, 1-alpha);
                
                vec2 bl2 = step(0.01,frac(pos*_Subdiv));       // 左下
                vec2 tr2 = step(0.01,1.0-frac(pos*_Subdiv));   // 右上
                float alpha2 =bl2.x * bl2.y * tr2.x * tr2.y;
                fragColor = mix(fragColor, _SubLinesColor, 1-alpha2);
                
                
                return fragColor;
                
            }
            ENDCG
        }
    }
}
通过上面的简单Shader,实现了一个基本的带十分刻度网格的Shader。下一节我们将继续对其进行优化。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity 坐标系转换是在游戏开发经常需要用到的一种技巧。在 Unity ,有三种坐标系:世界坐标系、局部坐标系和屏幕坐标系。下面我会分别介绍它们之间的转换方式。 1. 世界坐标系和局部坐标系Unity ,物体的坐标系分为世界坐标系和局部坐标系。世界坐标系是以场景心为原点建立的坐标系,而局部坐标系是以物体自身为原点建立的坐标系。 在进行物体坐标系的转换时,可以使用以下方法: 将一个物体的世界坐标系坐标转换为局部坐标系坐标: ```csharp Vector3 localPos = transform.InverseTransformPoint(worldPos); ``` 将一个物体的局部坐标系坐标转换为世界坐标系坐标: ```csharp Vector3 worldPos = transform.TransformPoint(localPos); ``` 2. 屏幕坐标系和世界坐标系Unity ,屏幕坐标系是以屏幕左下角为原点建立的坐标系。将屏幕坐标系转换为世界坐标系需要使用 Camera.ScreenToWorldPoint 方法,代码如下: ```csharp Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPos); ``` 其,screenPos 是屏幕坐标系下的坐标,Camera.main 表示主摄像机。 将世界坐标系转换为屏幕坐标系需要使用 Camera.WorldToScreenPoint 方法,代码如下: ```csharp Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos); ``` 其,worldPos 是世界坐标系下的坐标,Camera.main 表示主摄像机。 以上就是 Unity 坐标系转换的常用方法。在游戏,特别是在 UI 界面,经常需要进行坐标系的转换,掌握这些方法可以使开发更加便捷。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值