Shader语法——UNITY HLSL语法之(一)这一个文章搞定所有Unity Shader语法

学校,书本里教的Shader是如何写的?

基本功还是很重要得

一直以来不重视基本功,主要有2个原因

  1. 男篮基本功很强的,最近几年男篮的基本功更强了
  2. 国足那个基本功简直啊,很多项数值,例如转身速度,灵活性等据说世界一等一

 

Shader要如何开始写

GEM书里Shader, OpenGl 的Shader 是如何写的,我是不知道的,因为好像一开始就是UnityShader,很长时间都以为vert 和 fragment就是天生一对的,结果,后面还发现,很多框架的Shader都是分开的,开始的时候也是糊里糊涂的,有人说简单,也有人说复杂,有人又说其实就一个算法

Unity的Shader确实做到了又简单,又复杂

入门比较复杂,操作比较简单,精通又比较复杂

假如你和我一样有多年程序经验

就知道其实写Shader和写脚本一样,高级语言特性一个没有,脚本该有的弱点一点不落下,一些脚本式的编程技巧却又很能用

可编程管线Shader终究也还算是一种编程语言

知道这个关键后,其实也会释然很多,Shader也就只是一个编程语言嘛

其实,大家都知道,有一个非常有用,流传多年的写脚本的技巧

那就是

Ctrl + C , Ctrl + V

这你没法避开,任何一个你不熟的语言,首先得不是hello world,而是开始敲键盘

所以,从Control + C 开始吧

等等,下面的代码还是按正规记录

一些脚本语言对普通人十分不友好,因为没有“”变量类型“”

o.screenPosition = ComputeScreenPos(v.vertex); 

个人还是觉得这样的语法,“”“”友善“”“”很多

float3 worldPos = mul(unity_ObjectToWorld, vertex).xyz;

第二个写法,炸看可能觉得有点懵,但是只要你细心看,耐心看,还是至少能知道这是一个浮点矢量,然后mul()乘法也是清晰明了。

但为什么还这么多人还是按第一种写法,写ComputeScreenPos()呢,首先你不知道方法在哪里定义;这时候或者你会跳出来说你傻吧,程序员都不知道怎么找方法的实现逻辑;很多大牛也这么写,javascript也这么写啊;所以现在你知道cocos2dx+html5失败的原因了;

除了不知道方法在哪里定义,传入参数不确定,输出不确定,o.screen用了对象+属性,4重不确定,包含在一个代码里,是写的多差才能写出来的一行代码?

但很多大牛用第一种写法,我们也无法说什么,最大问题是,很多普通人也这么用

(大牛用第一种写法也是无可非议,首先得得掌握:低级语言,高级写法,代码输出控制,等等就不再这里展开了说了)

大牛这么做或者有其原因,但不是你这么抄的理由

(简写和命名准确,是很多脚本编程所必须的,除了历史原因,和一部分程序员原因,也是其脚本基因决定的,脚本代码很难理解和维护,这都2020年了,不需要再证明和举例子吧?)

这里稍微记录和分享一些写法:

UsePass使用

相当于call function

	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100
		UsePass "Unlit/TryUsePass/THISPASS"

。。。

注意几点吧:

另外一个 Shader 的 Name 必须大写

UsePase的作用,是而且只能是引用其他项目的 Pass

2个 Shader 都要保证正确(对于Unity,真正做到了“所见即所得”, Shader是实时编译的!!!)

如果调用自身的Shader的Pass会如何?把pass当成一个方法调用,可以吗?

使用Inculde 引用外国库

相当于C# 的 require

宏定义

https://blog.csdn.net/avi9111/article/details/105159827

获取顶点,Uv和法线

o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
v.normal = normalize(v.normal);
OUT.Normal = UnpackNormal(tex2D(_BumpMap, IN.mainTexUV));
var wNormal = UnityObjectToWorldNormal(v.normal);
v.normal = normalize(v.normal);

获取法线扩展

normal = DecodeViewNormalStereo (enc);
normal = NormalizePerPixelNormal(normal);
half3 binormal = cross(normal, tangent) * sign;

获取世界坐标

o.screenPosition = ComputeScreenPos(v.vertex); 
float3 worldPos = mul(unity_ObjectToWorld, vertex).xyz;

获取光:

 

练习一下吧:

一开始可能并不知道绿色,蓝色什么东西,移动一下

目测,每一个点都是固定的,而且每一个点并不相同

代码如下:

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				UNITY_TRANSFER_FOG(o,o.vertex);

				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				// sample the texture
				//fixed4 col = tex2D(_MainTex, i.uv);
				// apply fog
				//UNITY_APPLY_FOG(i.fogCoord, col);
				//return col;
				return fixed4(i.worldPos,1);
			}

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

avi9111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值