Unity3D ShaderLab 各向异性高光

各向异性时一种模拟物体表面沟槽方向性的高光反射类型,它会修改或延伸垂直方向上的高光。当我们想模拟金属拉丝高光的时候,它非常适合。下面就一步一步实现。

首先创建Shader,再创建材质球。然后双击Shader 打开编辑器。

1:修改Properties

Properties {

//添加属性;

_MainTint("Diffuse Tint",Color)=(,,,)

_MainTex ("Base (RGB)", 2D) = "white" {}

_SpecularColor("Specular Color",Color)=(,,,)

_SpecPower("Specular Power", Range(0.1,))=0.5

_Specular("Specular Amount",Range(0.1,))=0.5

_AnisoDir("Aniso Image",2D)=""{}

_AnisoOffset("Aniso Offset",Range(-,))=0.5

}

2:SubShader添加变量

CGPROGRAM

#pragma surface surf AnisoPhong

#pragma target 3.0

//设置变量;

sampler2D _MainTex;

sampler2D _AnisoDir;

float4 _MainTint;

float4 _SpecularColor;

float _AnisoOffset;

float _SpecPower;

float _Specular;

:加入SurfaceAnisoOutput输出结构体,修改输入结构体

struct Input {

float2 uv_MainTex;

float2 uv_AnisoDir;

};

//自定义输出结构体;

struct SurfaceAnisoOutput

{

fixed3 Albedo;

fixed3 Normal;

fixed3 Emission;

fixed3 AnisoDirection;

half Specular;

fixed Gloss;

fixed Alpha;

};

4:实现光照模型函数LightingAnisoPhong

//自定义光照模型;

inline fixed4 LightingAnisoPhong(SurfaceAnisoOutput s,fixed3 lightDir,half3 viewDir, fixed atten){

fixed3 halfVector = normalize(normalize(lightDir)+normalize(viewDir));

float NdotL = saturate( dot(s.Normal,lightDir) );

fixed HdotA = dot(normalize(s.Normal+s.AnisoDirection),halfVector);

float aniso = max(,sin(radians(HdotA+_AnisoOffset)*));

float spec = saturate(pow(aniso,s.Gloss*)*s.Specular);

fixed4 c;

c.rgb = (s.Albedo * _LightColor0.rgb*NdotL)+(_LightColor0.rgb * _SpecularColor.rgb*spec)*(atten*);

c.a=;

return c;

}

5:修改surf函数获取法线

void surf (Input IN, inout SurfaceAnisoOutput o) {

half4 c = tex2D (_MainTex, IN.uv_MainTex)*_MainTint;

float3 anisoTex = UnpackNormal(tex2D(_AnisoDir,IN.uv_AnisoDir));

o.AnisoDirection = anisoTex;

o.Specular = _Specular;

o.Gloss = _SpecPower;

o.Albedo = c.rgb;

o.Alpha = c.a;

}

返回unity。我们设置一下参数

最终效果如下:

在上面的编写过程中,我们主要关注我们自定义的光照函数。

首先,我们声明了自定义的输出结构体SurfaceAnisoOutput,这样做的目的是因为我们需要从各向异性法线贴图中得到每个像素信息,

而且在一个表面着色器中获得像素信息的唯一方法就是在surf函数中使用tex2D方法获取。通过我们自定义的SurfaceAnisoOutput输出结构体,

在光照函数和surf函数之间建立了数据传递方式。我们在surf函数中使用anisoTex 属性来存储每个像素的rgb讯息,然后通过输出结构体的AnisoDirection 属性传递给光照函数。

这样,我们就可以开始进行光照运算,采用半角矢量的方法,我们避免了全反射和散射的计算,也就只需要计算顶点发现和光线向量两者的点乘积。

fixed3 halfVector = normalize(normalize(lightDir)+normalize(viewDir));

float NdotL = saturate( dot(s.Normal,lightDir) );

然后,我们对镜面高光进行修改计算,将顶点法线和各向异性法线贴图上每个像素进行求和,再与halfVector进行点乘运算,

最后我们得到一个float值。该值为1,表面物体表面法线和halfVector平行,该值为0,他们是垂直的。

最终的sin函数计算后,我们就得到了中间有亮点且基于halfVector的环形效果。

fixed HdotA = dot(normalize(s.Normal+s.AnisoDirection),halfVector);

float aniso = max(0,sin(radians(HdotA+_AnisoOffset)*180));

最后在对aniso的值进行放大,得出s.Gloss求幂,通过s.Specular降低它的强度。

这样,我们就得到了上图的效果。整个Shader核心光照函数也就介绍完毕。

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

Shader "91YGame/AnisotropicSpecular" {
Properties {
//添加属性;
_MainTint("Diffuse Tint",Color)=(,,,)
_MainTex ("Base (RGB)", 2D) = "white" {}
_SpecularColor("Specular Color",Color)=(,,,)
_SpecPower("Specular Power", Range(0.1,))=0.5
_Specular("Specular Amount",Range(0.1,))=0.5
_AnisoDir("Aniso Image",2D)=""{}
_AnisoOffset("Aniso Offset",Range(-,))=0.5
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD CGPROGRAM
#pragma surface surf AnisoPhong
#pragma target 3.0
//设置变量;
sampler2D _MainTex;
sampler2D _AnisoDir;
float4 _MainTint;
float4 _SpecularColor;
float _AnisoOffset;
float _SpecPower;
float _Specular; struct Input {
float2 uv_MainTex;
float2 uv_AnisoDir;
};
//自定义输出结构体;
struct SurfaceAnisoOutput
{
fixed3 Albedo;
fixed3 Normal;
fixed3 Emission;
fixed3 AnisoDirection;
half Specular;
fixed Gloss;
fixed Alpha;
};
//自定义光照模型;
inline fixed4 LightingAnisoPhong(SurfaceAnisoOutput s,fixed3 lightDir,half3 viewDir, fixed atten){
fixed3 halfVector = normalize(normalize(lightDir)+normalize(viewDir));
float NdotL = saturate( dot(s.Normal,lightDir) ); fixed HdotA = dot(normalize(s.Normal+s.AnisoDirection),halfVector);
float aniso = max(,sin(radians(HdotA+_AnisoOffset)*)); float spec = saturate(pow(aniso,s.Gloss*)*s.Specular); fixed4 c;
c.rgb = (s.Albedo * _LightColor0.rgb*NdotL)+(_LightColor0.rgb * _SpecularColor.rgb*spec)*(atten*);
c.a=;
return c;
} void surf (Input IN, inout SurfaceAnisoOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex)*_MainTint;
float3 anisoTex = UnpackNormal(tex2D(_AnisoDir,IN.uv_AnisoDir));
o.AnisoDirection = anisoTex;
o.Specular = _Specular;
o.Gloss = _SpecPower;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}

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

Unity3D ShaderLab 各向异性高光的更多相关文章

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

    Unity3D ShaderLab 使用贴图对模型的高光进行遮罩 前面研究了高光效果的实现,再说说现很多游戏用到的高光贴图技术,因为它可以让3D美工更容易控制最终的视觉效果. 这也就为我们提供了另外的 ...

  2. Unity3D ShaderLab 使用BlinnPhong高光类型

    Unity3D shaderLab 使用BlinnPhong高光类型 上一篇我们实现了自定义高光类型,这一篇,我们说Blinn高光,它是另一种计算和估算高光更高效的方式,它是通过视线防线和光线方向,所 ...

  3. Unity3D ShaderLab 创建自定义高光类型

    Unity3D ShaderLab 创建自定义高光类型 在上一篇,我们认识了Unity基础的高光实现,本次主要是研究如何对Phong高光类型进行顶点操作,以及在表面着色器中使用Input结构体的新参数 ...

  4. Unity3D ShaderLab 基础的高光实现

    Unity3D ShaderLab 基础的高光实现 关于高光: 在一个物体表面的高光属性就是为了描述它是如何表现光泽.这种类型的效果在着色器的世界中通常称为视点相关效果. 之所以这样说,是因为为了实现 ...

  5. Unity3D ShaderLab 布料着色器

    Unity3D ShaderLab布料着色器 布料着色器是我们在虚拟现实中经常使用的着色器.本篇就来完成一个较为简单的布料着色器. 新建Shader,Material,InteractiveCloth ...

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

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

  7. Unity3D ShaderLab 修改渲染队列进行深度排序

    Unity3D ShaderLab 修改渲染队列进行深度排序 为了更深刻的理解透明度,我们还需要学习一下深度排序,简单来说就是物体被渲染的先后顺序. Unity允许我们通过代码来控制某个特定物体渲染到 ...

  8. Unity3D ShaderLab 透明裁剪着色器

    Unity3D ShaderLab 透明裁剪着色器 上一篇,我们介绍了使用Alpha实现透明的手法,其实Unity为我们的#pragma提供了另一种参数,是我们能做出更高效 简单的透明效果,也就是裁剪 ...

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

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

随机推荐

  1. K2工作流的使用

    K2的工作流作为工作流中的战斗机,被各大企业争相抢购着,当然我们公司也买了,用起来确实方便也的确很强大. 主要分两的模块: 一.K2.net 2003 Service Manager 以上是对配置用户 ...

  2. linux web php 安全相关设置

    1 隐藏apache 或者 nginx的版本号 2 隐藏php的版本号 3 php 程序做好基本的防注入 xss之类的攻击 4 禁用PHP一些危险的函数 比如 phpinfo.system之类的 5 ...

  3. git 将本地项目添加到远程

    git init git add README.md git commit -m "first commit" git remote add origin git@github.c ...

  4. mysql的REGEXP 和like的详细研究和解释

    1 regexp ^ 匹配字符串的开始部分 $ 匹配字符串的结束部分 . 匹配任何字符(包括回车和新行) a* 匹配0或多个a字符的任何序列 a+ 匹配1个或多个a字符的任何序列 a? 匹配0个或1个 ...

  5. [示例]NSEnumerator-使用枚举类型实现数组的逆序输出

    代码: #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepo ...

  6. jQuery中的quickExpr

    jQuery 源码中的 quickExpr 是用来检测参数 selector 是否是复杂的 HTML 代码(如“abc<div>”)或 #id,匹配结果存放在数组 match 中 // A ...

  7. 多线程同步内功心法——PV操作上(未完待续。。。)

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  8. DotNetBar v12.1.0.0 Fully Cracked

    更新信息: http://www.devcomponents.com/customeronly/releasenotes.asp?p=dnbwf&v=12.1.0.0 如果遇到破解问题可以与我 ...

  9. VS2013项目配置directx11

    假定你已经安装好了direct11 SDK(官方下的既是最新版本)和VS2013,并在VS2013中建立了一个新工程. 用VS2013打开工程后,点击右键属性,选择VC++目录: 其中在包含目录中添加 ...

  10. VS2010下配置OCI编程

    OCI是Oracle官方出品的用于C/C++语言连接.操作Oracle数据库的API.在windows操作系统下使用VS等IDE编写.编译C++程序十分方便.简单,不需要使用Makefile.使用OC ...