keyle的Shader-学习手札
前一段时间出去面试没有找到自己想要的工作,原因是shader熟练,虽然用的来ShaderForge但是面试官仍然会问到关于shader的基本知识,特写如下学习心得不断更新以此鞭策自己,少壮不努力老大徒伤悲(六月不学习,七月徒伤悲,八月忘穿秋水也找不到工作),接下来的日子好好补充数学与图形学知识,只有基础牢固才rong攻yi无zhuang不bi克 ! 另外给我们的开源项目做做宣传 https://git.oschina.net/keyle/SuperStrange ,创意3D跑酷手游,每个周末开发者一起协作开发,周期不限,欢迎大牛!
附件 1. CG标准函数库查询 链接: http://pan.baidu.com/s/1hq8Ir1i 密码: 3d3q
1.属性
_MyColor ("Some Color", Color) = (1,1,1,1) _MyVector ("Some Vector", Vector) = (0,0,0,0) _MyFloat ("My float", Float) = 0.5 _MyTexture ("Texture", 2D) = "white" {} _MyCubemap ("Cubemap", CUBE) = "" {}
2.基本内建指令
#pragma surface surf Lambert
#pragma surface surf BasicDiffuse #pragma surface surf SimpleLambert #pragma surface surf WrapLambert #pragma surface surf Ramp #pragma surface surf SimpleSpecular #pragma surface surf Standard #pragma surface surf Tonemapped
#pragma surface surf BlinnPhong
#pragma surface surf Phong
(1) #pragma surface surf Lambert 基础Lambert 光照模型:默认导入
(2) #pragma surface surf BasicDiffuse 基础漫反射光照模型
(3) #pragma surface surf SimpleLambert 简单Lambert,通过计算法线与光的方向夹角的点乘来判断光的衰减:出自官网介绍
It computes lighting by doing a dot product between surface normal and light direction, and then applies light attenuation and color.
(4) #pragma surface surf WrapLambert 环绕漫反射——漫反射光照的修改版,即照明环绕在物体的边缘。它对用来仿照表面下散射效果很有用。
(5) #pragma surface surf Ramp 渐变照明模式,使用一个渐变纹理定义光与法线夹角对surface影响,可用于卡通照明
(6) #pragma surface surf SimpleSpecular 简单光源反射,内置的blinnphong光照模型,
关于blinnphong光照模型可以参考ShaderForge博文中的这一篇 http://www.cnblogs.com/Keyle/p/4451887.html
(7) #pragma surface surf Standard 模仿内置的光照贴图解码工作,使用Unity自带的DecodeLightmap函数解码lightmap中储存的数据信息,以及使用自带的 UNITY_DIRBASIS宏定义方向光照贴图(Directional lightmap)的基本向量
We’ll start with a shader that mimics built-in lightmap decoding and uses Unity built-in function DecodeLightmap to decode information from data stored in lightmap textures and built-in UNITY_DIRBASIS macro defining basis vectors for Directional lightmaps:
(8) #pragma surface surf Tonemapped 色调映射
(9)#pagma surface surf BlinnPhong Phong光照模型优化版
(10)#pagma surface surf Phong
(11)#pagma surface surf CustomPhong
3.光照模型函数
当你声明一个光照模型函数,就可以创建一个新的光照模型,函数的格式是
half4 LightingYouName(SurfaceOutput s,half3 lightDir,float atten){} 本函数在不需要视角方向的先前着色时使用
half4 LightingYouName(SurfaceOutput s,half lightDir,half3 viewDir,half atten){} 用于需要视角方向着色时使用,考虑观察者视角方向
half4 LightingYouName(SurfaceOutput s,half4 light){} 此函数用于需要延迟着色的项
附件 今天的学习成果
#pragma surface surf BasicDiffuse inline float4 LightingKeyle(SurfaceOutput s,half3 dir,fixed aten) { float difLight = max(0,dot(s.Normal,dir)); difLight = difLight *0.5+0.5; float4 temp;//这个_LightingColor0是U3d内建变量获取环境光 s.Albedo是表面输出的反射率 temp.rgb = s.Albedo * _LightColor0.rgb*(difLight*aten*2);temp.a = s.Alpha; //拿到SurfaceOutput的透明通道 return temp; }
3.1 注意事项
1.如果不需要自己创建光照模型 可以将BasicDiffuse改回Lambert
2.在U3d5.0中自定义光照模型的名字时会报错类似 BasicDiffuse1, BlinnPhong, Lambert at line 11 (on ) ,此时改成默认的LightingBasicDiffuse,报错消失
3.位于光照模型参数列表中的atten 意为衰弱 注意:rgbA * rgbB 颜色会变暗,最终至全黑
4._LightColor0 通常为主光源的颜色
5._Time 内置时间函数通常配合text2D给图形做动态偏移 代码如下
6._Time 是一个float4类型,默认使用的时候输出_Time.x,官方翻译如下
Time (t/20, t, t*2, t*3), use to animate things inside the shaders.
7.灰阶公式
dot(float4, fixed3(.222,.707,.071));
8.#pragma target 版本 指定shader模型使用的版本
#pragma target 3.0 定义Shader模型为Shader Model 3.0
2.0 Direct3D 9 (默认缺省值) 支持32张贴图 + 64个计算
3.0 Direct3D 9 支持512张贴图 + 512个计算
4.0 只支持DirectX 11
5.0 只支持DirectX 11
9.Phong基础光照模型
float4 LightingPhong(SurfaceOutput s,fixed3 lightDir,half3 viewDir,fixed atten) 使用带观察者视角的方法签名 float3 reflectionVector = normalize(2.0* s.Normal * _Diffuse - lightDir); float specular = pow(max(0,dot(reflectionVector,viewDir)),POW); float3 finalSpecular = _SpecularColor.rgb*specular; float4 c; c.rgb = (s.Albedo * _LightColor0.rgb * _Diffuse )+(_LightColor0*finalSpecular); c.a = 1.0; 伪代码如上,核心算法 Dot( normailize(2*s.Normal*dot(s.Normal,lightDir) – lightDir) , viewDir)
10.BlinnPhong基础光照模型
inline float4 LightingPhong(SurfaceOutput s,fixed3 lightDir,half3 viewDir,fixed atten) 使用带观察者视角的方法签名 float3 halfDir = normalize(lightDir + viewDir); //半光照 float nh = dot(s.Normal,halfDir); float specular = pow(nh,_SpecularPower)*_SpecularColor; float4 c; c.rgb = (s.Albedo*_LightColor0.rgb*_Diffuse )+(_LightColor0*_SpecularColor.rgb*specular) * (atten*2); 伪代码如上,核心算法 dot(normalize(lightDir+viewDir) , s.Normal)
11.CustomPhong自定义Phong基础光照模型
结构体的名称必须为SurfaceCustomOutput
struct SurfaceCustomOutput {… fixed3 SpecularColor; };inline fixed4 LightingCustomPhong (SurfaceCustomOutput s, fixed3 lightDir, half3 viewDir, fixed atten) 签名中SurfaceOutput换成SurfaceCustomOutput在surf函数中赋值SpecularColor,在光照模型中使用
4.常用基本函数
1.tex2D(sampler2D,half2) 贴图采样返回对应坐标的像素值
2.fmod(float,float) 返回第一个数除以第二个数的余数
3.ceil(float) 向上取整
4.lerp(float3,float3,float) 插值,效果是叠加两张图在一个图片上,从第一个rgb渐变到第二个rgb数值,第三个参数是叠加的最后一个图的透明通道(Texture.a)
5.UnpackNormal(float4) 获得贴图信息
6.saturate 将颜色规范化0-1之间,类似于Vector2.Normalize函数