第一个Unity Shader
本文为参照这篇文章所做练习之笔记。由于笔者已经看过一遍计算机图形学急出,所以不再赘述相关内容。
创建Shader
点击create,选择shader,创建一个Standard Surface Shader。创建之后改名为Diffuse。
shader代码
直接贴代码:
1 | Shader "Custom/NewSurfaceShader" { |
根据不同的光照模型的不同,函数的输出类型是不同的。如果光照模型是Standard,那么输出的类型就是StandardSurfaceOutput。
应用到material
确保shader没有语法错误之后,新建一个材质,更改为刚才新建的shader,然后换上纹理。
最后把这个材质拖到3d物体上就能看到效果了。
使用分离的shader而非Surface
1 | Shader "Custom/DiffuseVertFrag" { |
和SurfaceShader的区别是一定要用pass包起来,而且要定义两个pragma来标注两个函数名。输出和输入的结构体一样需要自己定义,输入来源要写unity自带的关键字(宏?)。
Lambert带纹理的shader
代码参考github
1 | // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' |
注意内建变量。
在顶点着色器中,首先要获得世界坐标下的法向量和光照向量。
转换法向量的方法是把(物体坐标下的)法向量拿去乘以一个转换矩阵(一个内建矩阵 unity_WorldToObject
)。
光照向量直接拿unity提供的世界坐标下的光照向量就行了,不过我们只要它的xyz,拿到之后重新normalize一下。
于是漫反射亮度就是用光的颜色去乘以法向量与光照向量的点积了,光的颜色同样是个内建变量_LightColor0
。
至于变换顶点坐标,本来要用老的形式mul(UNITY_MATRIX_MVP, input.pos)
的,因为封装了方法,所以直接用封装后的方法UnityObjectToClipPos(input.pos)
。
接下来就是到片元着色器里,把光照强度拿去乘以纹理,得到最终的颜色。