学校,书本里教的Shader是如何写的?
基本功还是很重要得
一直以来不重视基本功,主要有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);
}