开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:1774

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 1937|回复: 26

[Moscibroda] Unity Shader 绘制点、直线、网格等基本图形

[复制链接]  [移动端链接]
排名
3558
昨日变化
4

11

主题

41

帖子

717

积分

Rank: 9Rank: 9Rank: 9

UID
139121
好友
7
蛮牛币
1405
威望
0
注册时间
2016-3-11
在线时间
232 小时
最后登录
2017-7-26

专栏作家

发表于 2016-12-23 08:52:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 Moscibroda 于 2016-12-26 11:29 编辑

前言
今天我们学习一种简单的使用Unity Shader在屏幕上绘制几何图形的方法。其中包含了基本的点(或者说是圆形)、直线(任意方向)和网格(横纵交错)的绘制方法。本文例程使用的是Unity 5.4.1。

1 准备工作
建立一个Unity工程,在摄像机前方放置一个Plane,需要填充满摄像机视野,放得正不正都没有关系,填满就行。利用Plane映射到屏幕上的像素坐标作为绘制图形的输入参数。(当然,如果我们使用OnRenderImage()函数,进行RenderTexture的材质修改,也可以实现本文的效果,原理都是一致的,这里我们主要看思路哈)


然后创建一个新的Material,名称随意,默认也可。再创建一个新的任意种类的Shader,取名为Draw。将Draw.shader文件中默认生成的shader代码全部删掉。将下面代码复制到你的Draw.shader文件中。
[C#] 纯文本查看 复制代码
Shader "Custom/Draw"  
{  
    Properties  
    {  
  
    }  
    SubShader  
    {  
  
        Pass  
        {  
            CGPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
             
            #include "UnityCG.cginc"  
  
            struct appdata  
            {  
                float4 vertex : POSITION;  
            };  
  
            struct v2f  
            {  
                float4 vertex : SV_POSITION;  
            };  
          
              
            v2f vert (appdata v)  
            {  
                v2f o;  
                o.vertex = UnityObjectToClipPos(v.vertex);  
                return o;  
            }  
              
            fixed4 frag (v2f i) : SV_Target  
            {  
                return fixed4(1,1,1,1);  
  
            }  
            ENDCG  
        }  
    }  
}  



将使用该shader的材质赋予Plane,这就完成了基本的准备工作了。

2 Shader代码编写
2.1 绘制点或圆形
点可以认为是只有一个像素的圆形,所以我们统一认为是绘制圆形。为了在屏幕上绘制圆形,我们需要知道圆形的位置和半径。
在Properties中添加要绘制的点位置信息,半径暂时不设置为可调的,后文在使用时用了固定值
[C#] 纯文本查看 复制代码
_Point1("Point1",vector) = (100,100,0,0)  
_Point2("Point2",vector) = (200,200,0,0)  



在SubShader的Pass中添加
[C#] 纯文本查看 复制代码
float4 _Point1;  
float4 _Point2;  


绘制圆形的代码:
[C#] 纯文本查看 复制代码
                            //绘制圆形,此处半径使用了固定值1000和500,当然大家也可以把他们写成可调的参数
                                if( pow((i.vertex.x- _Point1.x ),2) + pow((i.vertex.y- _Point1.y ),2) <1000   )
                                {
                                        return fixed4(0,1,0,1);
                                }
                                if( pow((i.vertex.x- _Point2.x ),2) + pow((i.vertex.y- _Point2.y ),2) <500   )
                                {
                                        return fixed4(1,0,0,1);
                                }




2.2 绘制直线
在Properties中添加要绘制的直线上两点位置及直线宽度
[C#] 纯文本查看 复制代码
                _LP1("linePoint1",vector) = (300,100,0,0)
                _LP2("linePoint2",vector) = (600,400,0,0)
                _LineWidth("LineWidth",range(1,20)) = 2.0


在SubShader的Pass中添加
[C#] 纯文本查看 复制代码
float4 _LP1;  
float4 _LP2;  
float _LineWidth;  


绘制直线上两点:
[C#] 纯文本查看 复制代码
//绘制直线上两点  
if( pow((i.vertex.x- _LP1.x ),2) + pow((i.vertex.y- _LP1.y ),2) <100   )  
{  
    return fixed4(0,0,1,1);  
}  
if( pow((i.vertex.x- _LP2.x ),2) + pow((i.vertex.y- _LP2.y ),2) <100   )  
{  
    return fixed4(0,0,1,1);  
}  

根据两点绘制直线。问题转化为计算哪些点在直线的线宽范围内。首先利用直线的两点式方程,过(x1,x2)和(y1,y2)的直线上任意点(x,y)满足下式

转化为一般式为

根据点到直线的距离公式,某一点(x0,y0)到上述直线的距离为

所以绘制直线的代码如下:
[C#] 纯文本查看 复制代码
//计算点到直线的距离  
float d = abs((_LP2.y-_LP1.y)*i.vertex.x + (_LP1.x - _LP2.x)*i.vertex.y +_LP2.x*_LP1.y -_LP2.y*_LP1.x )/sqrt(pow(_LP2.y-_LP1.y,2) + pow(_LP1.x-_LP2.x,2));  
//小于或者等于线宽的一半时,属于直线范围  
if(d<=_LineWidth/2)  
{  
    return fixed4(0.8,0.2,0.5,1);  
}  




2.3 绘制横纵网格
绘制网格直线代码:
[C#] 纯文本查看 复制代码
//绘制网格直线  
if( (unsigned int)i.vertex.x% (unsigned int)(0.25*_ScreenParams.x)==0 )  
{  
    return fixed4(0,0,1,1);  
}  
if( (unsigned int)i.vertex.y% (unsigned int)(0.1*_ScreenParams.x)==0 )  
{  
    return fixed4(0,0,1,1);  
} 




2.4 绘制效果
屏幕分辨率设置成了800*600。当然这是可以按照自己的意愿随意设置的,你可以改为自己喜欢的分辨率。

绘制图形

绘制图形



2.5 完整的shader代码
[C#] 纯文本查看 复制代码
Shader "Custom/Draw"  
{  
    Properties  
    {  
        _Point1("Point1",vector) = (100,100,0,0)  
        _Point2("Point2",vector) = (200,200,0,0)  
        _LP1("linePoint1",vector) = (300,100,0,0)  
        _LP2("linePoint2",vector) = (600,400,0,0)  
        _LineWidth("LineWidth",range(1,20)) = 2.0  
      
    }  
    SubShader  
    {  
        Pass  
        {  
            CGPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
             
            #include "UnityCG.cginc"  
  
            struct appdata  
            {  
                float4 vertex : POSITION;  
            };  
  
            struct v2f  
            {  
                float4 vertex : SV_POSITION;  
            };  
            float4 _Point1;  
            float4 _Point2;  
            float4 _LP1;  
            float4 _LP2;  
            float _LineWidth;         
              
            v2f vert (appdata v)  
            {  
                v2f o;  
                o.vertex = UnityObjectToClipPos(v.vertex);  
                return o;  
            }  
              
            fixed4 frag (v2f i) : SV_Target  
            {  
                //绘制圆形,此处半径使用了固定值1000和500,当然大家也可以把他们写成可调的参数  
                if( pow((i.vertex.x- _Point1.x ),2) + pow((i.vertex.y- _Point1.y ),2) <1000   )  
                {  
                    return fixed4(0,1,0,1);  
                }  
                if( pow((i.vertex.x- _Point2.x ),2) + pow((i.vertex.y- _Point2.y ),2) <500   )  
                {  
                    return fixed4(1,0,0,1);  
                }  
  
                //绘制直线上两点  
                if( pow((i.vertex.x- _LP1.x ),2) + pow((i.vertex.y- _LP1.y ),2) <100   )  
                {  
                    return fixed4(0,0,1,1);  
                }  
                if( pow((i.vertex.x- _LP2.x ),2) + pow((i.vertex.y- _LP2.y ),2) <100   )  
                {  
                    return fixed4(0,0,1,1);  
                }  
  
                //计算点到直线的距离  
                float d = abs((_LP2.y-_LP1.y)*i.vertex.x + (_LP1.x - _LP2.x)*i.vertex.y +_LP2.x*_LP1.y -_LP2.y*_LP1.x )/sqrt(pow(_LP2.y-_LP1.y,2) + pow(_LP1.x-_LP2.x,2));  
                //小于或者等于线宽的一半时,属于直线范围  
                if(d<=_LineWidth/2)  
                {  
                    return fixed4(0.8,0.2,0.5,1);  
                }  
  
                //绘制网格直线  
                if( (unsigned int)i.vertex.x% (unsigned int)(0.25*_ScreenParams.x)==0 )  
                {  
                    return fixed4(0,0,1,1);  
                }  
                if( (unsigned int)i.vertex.y% (unsigned int)(0.1*_ScreenParams.x)==0 )  
                {  
                    return fixed4(0,0,1,1);  
                }  
                //默认返回白色  
                return fixed4(1,1,1,1);  
  
            }  
            ENDCG  
        }  
    }  
}  


博客地址:http://blog.csdn.net/zzlyw/article/details/53813975

小结
我们已经可以使用Shader绘制简单的几何图形,今后可以进入更加复杂的图形绘制学习阶段,学习一下更复杂奇幻的图形了。



回复

使用道具 举报

4四处流浪
337/500
排名
10626
昨日变化
8

0

主题

228

帖子

337

积分

Rank: 4

UID
181594
好友
0
蛮牛币
143
威望
0
注册时间
2016-11-7
在线时间
47 小时
最后登录
2017-7-25
发表于 2016-12-23 09:32:22 | 显示全部楼层
Ding!!

回复

使用道具 举报

3偶尔光临
274/300
排名
6506
昨日变化
1

0

主题

53

帖子

274

积分

Rank: 3Rank: 3Rank: 3

UID
118445
好友
3
蛮牛币
381
威望
0
注册时间
2015-8-17
在线时间
79 小时
最后登录
2017-1-17
发表于 2016-12-23 10:08:26 | 显示全部楼层
UnityObjectToClipPos() 报错

回复 支持 反对

使用道具 举报

排名
3558
昨日变化
4

11

主题

41

帖子

717

积分

Rank: 9Rank: 9Rank: 9

UID
139121
好友
7
蛮牛币
1405
威望
0
注册时间
2016-3-11
在线时间
232 小时
最后登录
2017-7-26

专栏作家

 楼主| 发表于 2016-12-23 10:20:35 | 显示全部楼层
本帖最后由 Moscibroda 于 2016-12-23 10:22 编辑
yeluo 发表于 2016-12-23 10:08
UnityObjectToClipPos() 报错

UnityObjectToClipPos() 是一个预定义函数,应该是包含在头文件里的。你的Unity版本是多少?当然,最简单的是把这句替换为" o.vertex = mul(UNITY_MATRIX_MVP,v.vertex); "  两句是等价的。

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1091/1500
排名
20555
昨日变化
11

10

主题

633

帖子

1091

积分

Rank: 6Rank: 6Rank: 6

UID
158776
好友
1
蛮牛币
30
威望
0
注册时间
2016-7-26
在线时间
434 小时
最后登录
2017-7-27
发表于 2016-12-23 11:32:06 | 显示全部楼层
楼主能否绘制几何体,而且是随意几何体,比如鼠标随意点击五点然后再五点中生成几何体。

回复 支持 反对

使用道具 举报

排名
1806
昨日变化

10

主题

203

帖子

1404

积分

Rank: 9Rank: 9Rank: 9

UID
18798
好友
6
蛮牛币
4621
威望
0
注册时间
2014-3-24
在线时间
567 小时
最后登录
2017-7-25

专栏作家VIP

QQ
发表于 2016-12-23 11:43:16 | 显示全部楼层
哇,太棒了,最需要这种基础讲解的文章了!感谢ing

回复 支持 反对

使用道具 举报

排名
3558
昨日变化
4

11

主题

41

帖子

717

积分

Rank: 9Rank: 9Rank: 9

UID
139121
好友
7
蛮牛币
1405
威望
0
注册时间
2016-3-11
在线时间
232 小时
最后登录
2017-7-26

专栏作家

 楼主| 发表于 2016-12-23 11:57:40 | 显示全部楼层
Hao521314 发表于 2016-12-23 11:32
楼主能否绘制几何体,而且是随意几何体,比如鼠标随意点击五点然后再五点中生成几何体。 ...

我倒还没有试过,可以下次试试。应该是没问题的。

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1091/1500
排名
20555
昨日变化
11

10

主题

633

帖子

1091

积分

Rank: 6Rank: 6Rank: 6

UID
158776
好友
1
蛮牛币
30
威望
0
注册时间
2016-7-26
在线时间
434 小时
最后登录
2017-7-27
发表于 2016-12-23 14:29:17 | 显示全部楼层
Moscibroda 发表于 2016-12-23 11:57
我倒还没有试过,可以下次试试。应该是没问题的。

http://www.manew.com/forum.php?m ... p;page=1#pid1274752

看看能不能实现这样子二代效果
[发帖际遇]: Hao521314 被钱袋砸中进医院,看病花了 1 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1245/1500
排名
4947
昨日变化
3

2

主题

776

帖子

1245

积分

Rank: 6Rank: 6Rank: 6

UID
92518
好友
1
蛮牛币
2466
威望
0
注册时间
2015-4-15
在线时间
277 小时
最后登录
2017-4-6
发表于 2016-12-23 16:02:33 | 显示全部楼层

哇,太棒了,最需要这种基础讲解的文章了!感谢ing
[发帖际遇]: 825 乐于助人,奖励 3 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

7日久生情
1853/5000
排名
662
昨日变化
3

1

主题

501

帖子

1853

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
111260
好友
0
蛮牛币
6860
威望
0
注册时间
2015-6-30
在线时间
313 小时
最后登录
2017-7-27
发表于 2016-12-26 09:34:52 | 显示全部楼层
哇,太棒了,最需要这种基础讲解的文章了!感谢ing

回复 支持 反对

使用道具 举报

5熟悉之中
599/1000
排名
3514
昨日变化
6

0

主题

181

帖子

599

积分

Rank: 5Rank: 5

UID
179635
好友
1
蛮牛币
863
威望
0
注册时间
2016-10-31
在线时间
114 小时
最后登录
2017-7-25
发表于 2016-12-26 10:25:08 | 显示全部楼层
漫无边际 发表于 2016-12-26 09:34
哇,太棒了,最需要这种基础讲解的文章了!感谢ing

哇,太棒了,最需要这种基础讲解的文

回复 支持 反对

使用道具 举报

排名
19403
昨日变化
15

0

主题

11

帖子

83

积分

Rank: 2Rank: 2

UID
156355
好友
0
蛮牛币
143
威望
0
注册时间
2016-8-22
在线时间
57 小时
最后登录
2017-4-7
发表于 2016-12-26 10:32:27 | 显示全部楼层
很棒,谢谢分享

回复

使用道具 举报

7日久生情
2970/5000
排名
83
昨日变化

0

主题

387

帖子

2970

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
239
好友
3
蛮牛币
5371
威望
0
注册时间
2013-6-6
在线时间
603 小时
最后登录
2017-7-26
发表于 2016-12-26 15:09:25 | 显示全部楼层
路过看看!!!!!!!!!!!!

回复

使用道具 举报

6蛮牛粉丝
1113/1500
排名
2023
昨日变化

19

主题

284

帖子

1113

积分

Rank: 6Rank: 6Rank: 6

UID
52577
好友
4
蛮牛币
390
威望
0
注册时间
2014-11-2
在线时间
294 小时
最后登录
2017-7-21

活力之星

发表于 2016-12-26 18:31:46 | 显示全部楼层
不错哦!!直线方程终于用到了!

回复 支持 反对

使用道具 举报

7日久生情
1651/5000
排名
799
昨日变化

0

主题

346

帖子

1651

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
88896
好友
0
蛮牛币
6320
威望
0
注册时间
2015-4-2
在线时间
355 小时
最后登录
2017-7-27
发表于 2016-12-26 19:22:55 | 显示全部楼层
收藏一下,但还是没搞懂,以后研究。return fixed4(0.8,0.2,0.5,1); 返回的是颜色吧

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表