Unity3D ShaderLab 使用贴图对模型的高光进行遮罩

前面研究了高光效果的实现,再说说现很多游戏用到的高光贴图技术,因为它可以让3D美工更容易控制最终的视觉效果。

这也就为我们提供了另外的方式,我们可以在同一个着色器上实现垫型表面和光亮表面,也可以使用贴图来控制镜面高光的范围或者高光强度,

以实现一个表面是广泛的镜面高光而另一面确是细小的高光。

新建一个shader,一个材质球。老规矩双击shader脚本,在编辑器中编写代码吧。

1.Properties:

  1. Properties {
  2.  
  3. _MainTint("Diffuse Tint",Color) = (,,,)
  4.  
  5. _MainTex ("Base (RGB)", 2D) = "white" {}
  6.  
  7. _SpecularColor("Specular Tint",Color)=(,,,)
  8.  
  9. _SpecularMask("Specular Texture",2D)="white"{}
  10.  
  11. _SpecularPower("Specular Power",Range(,))=
  12.  
  13. }

2.SubShader中修改CGPROGRAM,加入输出结构体SurfaceMyOutput,修改Input结构体:

  1. CGPROGRAM
  2.  
  3. #pragma surface surf TexPhong
  4.  
  5. sampler2D _MainTex;
  6.  
  7. float4 _MainTint;
  8.  
  9. float4 _SpecularColor;
  10.  
  11. sampler2D _SpecularMask;
  12.  
  13. float _SpecularPower;
  14.  
  15. struct SurfaceMyOutput{
  16.  
  17. fixed3 Albedo;
  18.  
  19. fixed3 Normal;
  20.  
  21. fixed3 Emission;
  22.  
  23. fixed3 SpecularColor;
  24.  
  25. half Specular;
  26.  
  27. fixed Gloss;
  28.  
  29. fixed Alpha;
  30.  
  31. };
  32.  
  33. struct Input {
  34.  
  35. float2 uv_MainTex;
  36.  
  37. float2 uv_SpecularMask;
  38.  
  39. };

3.实现自定义光照模型LightingTexPhong

  1. inline fixed4 LightingTexPhong(SurfaceMyOutput s,fixed3 lightDir,half3 viewDir, fixed atten){
  2.  
  3. float diff = dot(s.Normal,lightDir);
  4.  
  5. float3 reflection = normalize(3.0*s.Normal*diff-lightDir);
  6.  
  7. float spec = pow(max(,dot(reflection,viewDir)), _SpecularPower)*s.Specular;
  8.  
  9. float3 finalSpec = s.SpecularColor * spec*_SpecularColor.rgb;
  10.  
  11. fixed4 c;
  12.  
  13. c.rgb = (s.Albedo*_LightColor0.rgb*diff)+(_LightColor0.rgb*finalSpec);
  14.  
  15. c.a = s.Alpha;
  16.  
  17. return c;
  18.  
  19. }

4.修改surf函数

  1. void surf (Input IN, inout SurfaceMyOutput o) {
  2.  
  3. float4 c = tex2D (_MainTex, IN.uv_MainTex)*_MainTint;
  4.  
  5. float4 specMask = tex2D(_SpecularMask,IN.uv_SpecularMask)*_SpecularColor;
  6.  
  7. o.Albedo = c.rgb;
  8.  
  9. o.Specular = specMask.r;
  10.  
  11. o.SpecularColor = specMask.rgb;
  12.  
  13. o.Alpha = c.a;
  14.  
  15. }

修改完毕后,返回unity设置参数,最终效果如下。

在上面的代码编写过程中,我们需要将表面函数的信息传递给给光照函数,因为我们在光照函数内部不能得到一个物体表面的uv,

所以我们需要通过input结构体来访问数据,唯一途径就是使用surf函数,为了建立数据关系,我们自定义了结构体SurfaceMyOutput,

用这个结构体作为容器存储表面着色器中所有最终数据。这样光照函数和surf函数都可以访问它的内部数据。

然后,我们告诉surf函数和光照函数使用output结构体是我们自定义的SurfaceMyOutput结构体,而不是着色器内置的。

最后我们只需要使用tex2D函数就可以访问纹理讯息返回值,直接传递给SurfaceMyOutput结构体,完成了这些,我们就可以在光照函数中访问讯息纹理。

code start --------------------------------------------------------------------------

  1. Shader "91YGame/TexPhong" {
  2. Properties {
  3. _MainTint("Diffuse Tint",Color) = (,,,)
  4. _MainTex ("Base (RGB)", 2D) = "white" {}
  5.  
  6. _SpecularColor("Specular Tint",Color)=(,,,)
  7. _SpecularMask("Specular Texture",2D)="white"{}
  8. _SpecularPower("Specular Power",Range(0.5,))=
  9. }
  10. SubShader {
  11. Tags { "RenderType"="Opaque" }
  12. LOD
  13.  
  14. CGPROGRAM
  15. #pragma surface surf TexPhong
  16.  
  17. sampler2D _MainTex;
  18. float4 _MainTint;
  19. float4 _SpecularColor;
  20. sampler2D _SpecularMask;
  21. float _SpecularPower;
  22.  
  23. struct SurfaceMyOutput{
  24. fixed3 Albedo;
  25. fixed3 Normal;
  26. fixed3 Emission;
  27. fixed3 SpecularColor;
  28. half Specular;
  29. fixed Gloss;
  30. fixed Alpha;
  31. };
  32.  
  33. struct Input {
  34. float2 uv_MainTex;
  35. float2 uv_SpecularMask;
  36. };
  37.  
  38. inline fixed4 LightingTexPhong(SurfaceMyOutput s,fixed3 lightDir,half3 viewDir, fixed atten){
  39. float diff = dot(s.Normal,lightDir);
  40. float3 reflection = normalize(3.0*s.Normal*diff-lightDir);
  41.  
  42. float spec = pow(max(,dot(reflection,viewDir)), _SpecularPower)*s.Specular;
  43. float3 finalSpec = s.SpecularColor * spec*_SpecularColor.rgb;
  44.  
  45. fixed4 c;
  46. c.rgb = (s.Albedo*_LightColor0.rgb*diff)+(_LightColor0.rgb*finalSpec);
  47. c.a = s.Alpha;
  48. return c;
  49. }
  50.  
  51. void surf (Input IN, inout SurfaceMyOutput o) {
  52. float4 c = tex2D (_MainTex, IN.uv_MainTex)*_MainTint;
  53. float4 specMask = tex2D(_SpecularMask,IN.uv_SpecularMask)*_SpecularColor;
  54. o.Albedo = c.rgb;
  55. o.Specular = specMask.r;
  56. o.SpecularColor = specMask.rgb;
  57. o.Alpha = c.a;
  58. }
  59. ENDCG
  60. }
  61. FallBack "Diffuse"
  62. }

code end ---------------------------------------------------------------------------

Unity3D ShaderLab 使用贴图对模型的高光进行遮罩的更多相关文章

  1. Unity3D ShaderLab 静态贴图光照模型

    Unity3D ShaderLab 静态贴图光照模型 其实在unity的光照模型中,我们可以把光照讯息烘培进入一个2D贴图,来实现着色器的光照效果. 下面是在unity中关闭灯光和打开灯光的对比效果. ...

  2. Unity3D ShaderLab法线贴图

    Unity3D ShaderLab法线贴图 说到法线贴图,应该算是我们最常使用的一种增强视觉效果的贴图.将法线贴图的各个像素点座位模型的法线,这样我们的光照可以模拟出高分辨率的效果, 同时也保持较低的 ...

  3. Unity3D ShaderLab 立方体图的菲涅尔反射

    Unity3D ShaderLab 立方体图的菲涅尔反射 菲涅尔反射是反射类型中比较常见的一种类型,当我们的视线正对物体表面,那么反射量会明显增加, 我们几乎可以在任何支持反射类型的物体表面看到这种情 ...

  4. Unity3D ShaderLab立方体图的法线渲染

    Unity3D ShaderLab立方体图的法线渲染 某些情况下,我们希望立方体图的材质球上产生法线效果,来更多的表现细节,比如菱形花纹的玻璃,冰块的表面. 在帧数的协调下,我们可以通过input结构 ...

  5. Unity3D ShaderLab 立方体图的反射遮罩

    Unity3D ShaderLab 立方体图的反射遮罩 上一篇,简单的介绍了立方体图的反射,那么我们能不能使用一张纹理对其进行指定遮罩呢?这样美工可以更好的控制图像的效果. 我们接着使用上一篇的sha ...

  6. Unity3D ShaderLab 简单的立方体图反射

    Unity3D ShaderLab 简单的立方体图反射 反射是着色器模拟现实环境的一个关键因素,它能使我们的着色器渲染效果更加具备视觉冲击,因为他利用了我们周围的环境, 让着色器反射外界的场景信息并将 ...

  7. Unity3D ShaderLab压缩混合纹理贴图

    Unity3D ShaderLab压缩混合纹理贴图 纹理可以用于存储大量的数据,我们可以把多个图像打包存储在单一的RGBA纹理上,然后通过着色器代码提取这些元素, 我们就可以使用每个图片的RGBA通道 ...

  8. Unity3D 导入贴图、模型等资源文件时自动设置参数

    脚本继承至AssetPostprocessor, 存放在Editor目录下! using UnityEngine; using System.Collections; using UnityEdito ...

  9. Unity3D ShaderLab 漫反射卷积光照模型

    Unity3D ShaderLab 漫反射卷积光照模型 漫反射卷积[Diffuse convolution]是一个模糊立方体的过程,它保留了立方图的整体光照强度,只模糊了细节. 这种效果在我们要活得一 ...

随机推荐

  1. 原生JavaScript实现mouseenter

    mouseenter和Mouseleave都是jquery的事件,JavaScript的mouseover和mouseout每个子元素都会触发,从子元素移到父元素也会触发,用起来不很方便,而且触发的太 ...

  2. WebForm MapPageRoute 路由配置(转载)

    使用场景是:MVC 混合使用 WebForm,然后对 WebForm 进行路由配置 http://www.cnblogs.com/xishuai/archive/2015/02/26/web-form ...

  3. SAP资产明细报表

    前两年别人写的,无自定义表字段...直接使用: *&---------------------------------------------------------------------* ...

  4. Android中 在显示ImageView时图片上面和下面都出现一段空白区间的解决办法

    开始的时候是在ScrollView中显示ImageView的时候出现这样的问题,以为是要对ScrollView进行设置的,后来发现单独显示一个ImageView的时候也会出现这样的问题,由此才知道是应 ...

  5. ASP.NET-【缓存】-使用ASP.NET缓存

    缓存一个List 泛型结构 1.显示 var s = Get("personsl"); foreach (var item in s) { Response.Write(item. ...

  6. mysql 远程连接速度慢的解决方案

    PHP远程连接MYSQL速度慢,有时远程连接到MYSQL用时4-20秒不等,本地连接MYSQL正常,出现这种问题的主要原因是,默认安装的MYSQL开启了DNS的反向解析,在MY.INI(WINDOWS ...

  7. eclipse隐藏菜单栏实现全部酷黑主题

    将eclipse升级到了最新版的neon,将主题颜色设置为了dark,瞬间高大上了很多,唯独菜单栏还是白色的,很刺眼.况且菜单栏不是很常用,所以我们可以将菜单栏隐藏起来,以达到全部黑色的效果. 步骤: ...

  8. HDU 4035 Maze 概率dp,树形dp 难度:2

    http://acm.hdu.edu.cn/showproblem.php?pid=4035 求步数期望,设E[i]为在编号为i的节点时还需要走的步数,father为dfs树中该节点的父节点,son为 ...

  9. HDU 4890 One to Four(2014 Multi-University Training Contest 3)

    题意:给定一个长方形网格,要把它切成完全相同4个部分(这里完全相同指可以旋转平移后能重叠).把4个重叠后每个网格对应有四个数字相加,得到一种方案,所有格子中和最小就是该种方案的值,在多种方案中,最后问 ...

  10. 使用WBI SAP Adapter 实现IDoc的同步处理(转)

    1. 应用背景 某汽车制造企业(以下称为厂商A)与其仓储系统提供商(以下称为厂商B)需要进行数据交换.汽车厂商A使用SAP系统作ERP管理,所有数据都要进入SAP进行处理,仓储系统提供商使用的是自有的 ...