Unity3D ShaderLab 各向异性高光

Unity3D ShaderLab 各向异性高光

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

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

1:修改Properties

Properties {

//添加属性;

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

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

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

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

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

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

_AnisoOffset("Aniso Offset",Range(-1,1))=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;

3:加入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(0,sin(radians(HdotA+_AnisoOffset)*180));

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

fixed4 c;

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

c.a=1;

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)=(1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _SpecularColor("Specular Color",Color)=(1,1,1,1)
        _SpecPower("Specular Power", Range(0.1,1))=0.5
        _Specular("Specular Amount",Range(0.1,1))=0.5
        _AnisoDir("Aniso Image",2D)=""{}
        _AnisoOffset("Aniso Offset",Range(-1,1))=0.5
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        
        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(0,sin(radians(HdotA+_AnisoOffset)*180));

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

fixed4 c;
            c.rgb = (s.Albedo * _LightColor0.rgb*NdotL)+(_LightColor0.rgb * _SpecularColor.rgb*spec)*(atten*2);
            c.a=1;
            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 ------------------------------------------------------------------

时间: 2025-01-08 00:49:19

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

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

Unity3D ShaderLab 使用贴图对模型的高光进行遮罩 前面研究了高光效果的实现,再说说现很多游戏用到的高光贴图技术,因为它可以让3D美工更容易控制最终的视觉效果. 这也就为我们提供了另外的方式,我们可以在同一个着色器上实现垫型表面和光亮表面,也可以使用贴图来控制镜面高光的范围或者高光强度, 以实现一个表面是广泛的镜面高光而另一面确是细小的高光. 新建一个shader,一个材质球.老规矩双击shader脚本,在编辑器中编写代码吧. 1.Properties: Properties {

Unity3D ShaderLab 使用BlinnPhong高光类型

Unity3D shaderLab 使用BlinnPhong高光类型 上一篇我们实现了自定义高光类型,这一篇,我们说Blinn高光,它是另一种计算和估算高光更高效的方式,它是通过视线防线和光线方向,所形成的半角向量来完成. 这种方式比我们自己形成反射向量来进行计算更加高效.在UnityCG.cginc文件中内置的BlinnPhong光照模型就是半角矢量完成的. 首先还是创建一个shader,一个材质球,双击shader,打开编辑器. 1:Properties Properties { _Main

Unity3D ShaderLab 创建自定义高光类型

Unity3D ShaderLab 创建自定义高光类型 在上一篇,我们认识了Unity基础的高光实现,本次主要是研究如何对Phong高光类型进行顶点操作,以及在表面着色器中使用Input结构体的新参数进行像素操作. 所以还是新建Shader,再建材质球然后打开编辑器进行shader的编辑. 1.修改Properties Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _MainTint("Diff

Unity3D ShaderLab 基础的高光实现

Unity3D ShaderLab 基础的高光实现 关于高光: 在一个物体表面的高光属性就是为了描述它是如何表现光泽.这种类型的效果在着色器的世界中通常称为视点相关效果. 之所以这样说,是因为为了实现着色器逼真的镜面效果,我们需要考虑相机或者观察者面向物体表面的方向,然而高光还需要一个元素来实现视觉的真实效果---光的入射方向! 通过结合2个方向,我们可以在物体的表面得到一个热点或者说亮点,它位于视角方向和光源方向中间位置.这种中间位置的方向可以成为半角矢量,我们通过他可以实现高光效果和镜面等.

Unity3D ShaderLab 布料着色器

Unity3D ShaderLab布料着色器 布料着色器是我们在虚拟现实中经常使用的着色器.本篇就来完成一个较为简单的布料着色器. 新建Shader,Material,InteractiveCloth[布料].完成的代码如下 Shader "91YGame/ClothShader" { Properties { //参数; _MainTint("Base Color",Color)=(1,1,1,1) _BumpMap ("Normal Map"

Unity Shaders and Effects Cookbook (3-6) 创建各向异性高光类型(Anisotropic) 模拟金属拉丝效果

这一次学习各向异性高光类型,名字真拗口,Anisotropic 这个英文单词也很拗口. 各向异性是模拟物体表面 沟槽方向性的高光反射类型,他会修改或延伸垂直方向上的高光. 比如模拟金属拉丝的效果,就可以使用各向异性来模拟. 转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn 首先需要准备一张各向异性 的法线贴图,代表各向异性镜面高光的方向性. 注意法线贴图导入到Unity之后要在属性面板中勾选类型为 Normal Map. 首先在

Unity3D ShaderLab 透明裁剪着色器

Unity3D ShaderLab 透明裁剪着色器 上一篇,我们介绍了使用Alpha实现透明的手法,其实Unity为我们的#pragma提供了另一种参数,是我们能做出更高效 简单的透明效果,也就是裁剪透明. 这种透明使用一个值来简单的控制某些特定的像素无需渲染到屏幕上,所以我们也可以通过他实现一个要么完全透明或完全不透的着色器. 我们即将利用灰度的值来控制材质的透明度. 准备工作还是新建Shader Material,一张灰度变化图.同样是分分钟完成的代码,请看完成: Shader "91YGa

Unity3D ShaderLab 简单的立方体图反射

Unity3D ShaderLab 简单的立方体图反射 反射是着色器模拟现实环境的一个关键因素,它能使我们的着色器渲染效果更加具备视觉冲击,因为他利用了我们周围的环境, 让着色器反射外界的场景信息并将他们反射到材质表面来模拟外部环境,所以我们会使用立方图[CubeMap]的6张纹理来模拟环境的色彩情况. 首先,创建Shader,创建材质球,准备立方图,双击Shader,进入代码编辑器. 从Properties 到CGPROGRAM,再到surf,本次功能较为简单,先看代码. code start

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

Unity3D ShaderLab 立方体图的菲涅尔反射 菲涅尔反射是反射类型中比较常见的一种类型,当我们的视线正对物体表面,那么反射量会明显增加, 我们几乎可以在任何支持反射类型的物体表面看到这种情况,我们接下来就来实现这种反射效果过. 还是先创建Shader和 Material,沿用上一节的立方体图.代码变动较少,直接看下面的完成代码: code start -------------------------------------------------------------------