【Unity Shaders】法线贴图
2016-04-13 17:47
246 查看
本系列主要参考《Unity
Shaders and Effects Cookbook》一书(感谢原书作者),同时一位写过这个书籍理解博客的博主妈妈说女孩子要自立自强。
她的博客帮我更好的理解shader这本书籍。也因此希望可以延续这份分享。
本书所有的插图:https://www.packtpub.com/sites/default/files/downloads/5084OT_Images.pdf。
本书所需的代码和资源:http://download.csdn.net/detail/candycat1992/6798871
========================================== 分割线 ==========================================
2.在场景视图将它们设置到一个新物体上。
3.并且准备一张纹理贴图。
4.把导入的法线贴图的Texture Type调成normal map
2.在CGPROGRAM描述语句下的subshader内声明相应的属性,以便我们在CGT程序片段中能够访问上述的两个属性:
3.然后,我们需要确定我们已经使用合适的变量对Input结构体进行了更新,这样我们就可以将模型的UV应用到法线贴图上了。
4.最后,我们使用Unity内置的UnpackNormal()函数从法线贴图当中提取法线信息。然后你只需将这些新的发现信息应用到Surface
Shader 的输出即可:
下图展示的是应用法线贴图渲染之后的结果:
如果你查看Unity自带的UnityCG.cginc文件,会找到UnpackNormal()函数的定义。当你在着色器内声明该函数时,Unity将对你提供的发现贴图进行处理,并将运算后的正确数据直接返回给你,这样你就可以逐像素将法线信息应用到光照函数内了。
当使用UnpackNormal()函数对发现贴图进行处理后,会将处理后的值返回到SurfaceOutput结构体内,这样它就可以在光照函数中进行使用了。
这一步工作是由代码“o.Normal=normalMap.rgb;”来完成的。
1.在Properties块中另外又添加一个属性,将其命名为_NormalMapIntensity,如下代码所示:
2.确保你在SubShader函数中也声明了该属性:
3.将经过解压后的法线贴图变量值的x和y坐标值均乘上_NormalMapIntensity,将计算后的值作为法线贴图的变量值。现在就可以让用户在材质Inspector面板上调整发现贴图的强度了。
下图为使用我们提供的标量值来修改法线贴图的结果图:
Shaders and Effects Cookbook》一书(感谢原书作者),同时一位写过这个书籍理解博客的博主妈妈说女孩子要自立自强。
她的博客帮我更好的理解shader这本书籍。也因此希望可以延续这份分享。
本书所有的插图:https://www.packtpub.com/sites/default/files/downloads/5084OT_Images.pdf。
本书所需的代码和资源:http://download.csdn.net/detail/candycat1992/6798871
========================================== 分割线 ==========================================
写在前面
由于刚刚开始学习shader,所以理解还是很片面。但是我也希望可以努力学习,争取未来有更深入的理解。而且这是第一次写博客,还不知道如何写出好看的格式,我会慢慢改进的。准备工作
1.创建一个新的材质和着色器,命名为NormalMap。2.在场景视图将它们设置到一个新物体上。
3.并且准备一张纹理贴图。
4.把导入的法线贴图的Texture Type调成normal map
开始操作
1.在Properties块中添加一个颜色和一个纹理属性:Properties { _MainTint("Diffuse Tint",Color) = (1,1,1,1) _NormalTex("Normal Map",2D) = "bump"{} }
2.在CGPROGRAM描述语句下的subshader内声明相应的属性,以便我们在CGT程序片段中能够访问上述的两个属性:
sampler2D _NormalTex; float4 _MainTint;
3.然后,我们需要确定我们已经使用合适的变量对Input结构体进行了更新,这样我们就可以将模型的UV应用到法线贴图上了。
struct Input { float2 uv_NormalTex; };
4.最后,我们使用Unity内置的UnpackNormal()函数从法线贴图当中提取法线信息。然后你只需将这些新的发现信息应用到Surface
Shader 的输出即可:
void surf (Input IN, inout SurfaceOutput o) { float3 normalMap = UnpackNormal(tex2D(_NormalTex, IN.uv_NormalTex)); o.Normal = normalMap.rgb; o.Albedo = _MainTint.rgb; o.Alpha = _MainTint.a; }最终代码如下:
Shader "Custom/NormalMap" {
Properties {
//_MainTex ("Base (RGB)", 2D) = "white" {}
_MainTint("Diffuse Tint",Color) = (1,1,1,1)
_NormalTex("Normal Map",2D) = "bump"{}
}
SubShader{
Tags { "RenderType" = "Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert
//sampler2D _MainTex;
sampler2D _NormalTex; float4 _MainTint;
struct Input { float2 uv_NormalTex; };
void surf (Input IN, inout SurfaceOutput o) {
float3 normalMap = UnpackNormal(tex2D(_NormalTex, IN.uv_NormalTex));
o.Normal = normalMap.rgb;
o.Albedo = _MainTint.rgb;
o.Alpha = _MainTint.a;
}
ENDCG
}
FallBack "Diffuse"
}
下图展示的是应用法线贴图渲染之后的结果:
实现原理
表现发现贴图效果的数学原理其实超出了本章的学习范围,但Unity已经在很多方面帮我们做好了这一切。它是为我们提供了相应的函数,这样我们不需要重复地编写代码。这也解释了为什么表面着色器是一种非常高效的着色器编写方式。如果你查看Unity自带的UnityCG.cginc文件,会找到UnpackNormal()函数的定义。当你在着色器内声明该函数时,Unity将对你提供的发现贴图进行处理,并将运算后的正确数据直接返回给你,这样你就可以逐像素将法线信息应用到光照函数内了。
当使用UnpackNormal()函数对发现贴图进行处理后,会将处理后的值返回到SurfaceOutput结构体内,这样它就可以在光照函数中进行使用了。
这一步工作是由代码“o.Normal=normalMap.rgb;”来完成的。
更多内容
可以在发现贴图着色器内添加一些控件,以便让用户可以自行调整发现贴图的强度。我们可以很容易地通过修改法线贴图变量的x和y坐标来完成。然后将修改后的值返回到计算中。1.在Properties块中另外又添加一个属性,将其命名为_NormalMapIntensity,如下代码所示:
Properties { _MainTint("Diffuse Tint", Color) = (1,1,1,1) _NormalTex("Normal Map", 2D) = "bump" {} _NormalIntensity("Normal Map Intensity", Range(0,2)) = 1 }
2.确保你在SubShader函数中也声明了该属性:
//Link the property to the CG program
sampler2D _NormalTex; float4 _MainTint;
float _NormalIntensity;
3.将经过解压后的法线贴图变量值的x和y坐标值均乘上_NormalMapIntensity,将计算后的值作为法线贴图的变量值。现在就可以让用户在材质Inspector面板上调整发现贴图的强度了。
void surf(Input IN, inout SurfaceOutput o) { //Get teh normal Data out of the normal map textures //using the UnpackNormal() function. float3 normalMap = UnpackNormal(tex2D(_NormalTex, IN.uv_NormalTex)); normalMap = float3(normalMap.x * _NormalIntensity, normalMap.y * _NormalIntensity, normalMap.z); //Apply the new normals to the lighting model o.Normal = normalMap.rgb; o.Albedo = _MainTint.rgb; o.Alpha = _MainTint.a; }
下图为使用我们提供的标量值来修改法线贴图的结果图:
相关文章推荐
- Unity3d-tolua基础一
- Unity发布安卓Splash Image适应手机、平板
- Unity发布iOS上架总结
- Unity 使用ShareSDK 3.X 版本发布Xcode进入AR闪退
- Unity Sprite Packer 问题集合
- Unity 部分错误信息提示
- Unity 与 Android融合
- 【OpenGL】使用Unity来学习OpenGL
- unity 得到js的Json,类似\u624b\u8868这种转换为汉字的方法
- Unity JsonUtility类的用法
- Unity 3D 正交(Orthographic)摄像机尺寸学习笔记
- unity3d的GUI元素的界面坐标系统总结(有公式)
- unity3d插件Daikon Forge GUI 中文教程7-高级控件slider的使用
- unity3d插件Daikon Forge GUI 中文教程6-高级控件richtextlabel的使用
- Unity 控制摄像机跟随运动物体
- Unity 控制物体绕x,y,z 轴旋转
- unity3d插件Daikon Forge GUI 中文教程5-高级控件listbox和progress bar的使用
- unity3d插件Daikon Forge GUI 中文教程4-高级控件Checkbox和dropdownlis的使用
- unity3d插件Daikon Forge GUI 中文教程3-基础控件Button和Sprite的使用
- unity3d插件Daikon Forge GUI 中文教程2-基础控件Label的使用