首页 > 代码库 > Unity3D ShaderLab 漫反射卷积光照模型

Unity3D ShaderLab 漫反射卷积光照模型

Unity3D ShaderLab 漫反射卷积光照模型

漫反射卷积【Diffuse convolution】是一个模糊立方体的过程,它保留了立方图的整体光照强度,只模糊了细节。

这种效果在我们要活得一个更具全局光照表面效果的时候非常有用。

为了实现这种效果,我们需要创建一个卷积运算的立方图。比如ATI的工具制作CubeMapGen

下载地址:

http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/cubemapgen/

 技术分享

安装完毕后,我们通过右上角的LoadBasemap,LoadCubeMap配置贴图,在设置一下FilterTypeFilter Angle等参数后点击右下角的FilterCubeMap按钮。

等待一会就可以Filter完成,点击Save CubeMap to Images按钮,就可以保存我们的立方体图了。

 

然后就是新建ShaderMaterial。双击脚本,计入编辑器模式。

1>修改Properties

Properties {_MainTint("Global Tint",Color)=(1,1,1,1)_BumpMap ("Normal Map", 2D) = "bump" {}_AOMap("Ambient Occlusion Map",2D)="white"{}_CubeMap("Diffuse Convolution CubeMap",Cube)=""{}_SpecIntensity("Specular Intensity",Range(0,1))=0.4_SpecWitdth("Specular Width",Range(0,1))=0.2}

 

 

2>修改SubShader变量

CGPROGRAM#pragma surface surf DiffuseConvolution#pragma target 3.0 samplerCUBE _CubeMap;sampler2D _BumpMap;sampler2D _AOMap;float4 _MainTint;float _SpecIntensity;float _SpecWitdth; struct Input {float2 uv_MainTex;float2 uv_AOMap;float3 worldNormal;INTERNAL_DATA};

 

我们需要模型的世界法线,所以加入INTERNAL_DATA。因为着色器包含一张法线贴图,我们使用它获得修改后的法线。

3>完成光照函数

inline fixed4 LightingDiffuseConvolution(SurfaceOutput s,fixed3 lightDir,fixed3 viewDir,fixed atten){//计算光照向量;viewDir = normalize(viewDir);lightDir = normalize(lightDir);s.Normal = normalize(s.Normal);float NdotL = dot(s.Normal,lightDir);float3 halfVec = normalize(lightDir+viewDir);//计算高光;float spec = pow(dot(s.Normal,halfVec),s.Specular*128)*s.Gloss;//光照模型赋值;fixed4 c;c.rgb = (s.Albedo*atten)+spec;c.a = 1;return c;} 

 

4>surf处理贴图

void surf (Input IN, inout SurfaceOutput o) {half4 c = tex2D (_AOMap, IN.uv_AOMap);float3 normals = UnpackNormal(tex2D(_BumpMap,IN.uv_AOMap)).rgb;o.Normal = normals;float3 diffuseVal = texCUBE(_CubeMap,WorldNormalVector(IN,o.Normal)).rgb;o.Albedo = (c.rgb*diffuseVal)*_MainTint;o.Specular = _SpecWitdth;o.Gloss = _SpecIntensity*c.rgb;o.Alpha = c.a;}

 

完成了光照函数后,使用模型的世界法线来对卷积后的立方图进行纹理映射,然后把结果传入output结构体。

返回Unity编辑器,最终效果如下:

 技术分享

通过上面的函数,我们首先得到被法线贴图修改后的模型的世界法线,并利用法线数据来查找立方图上的位置以得到他的像素和颜色,

这就是我们要在Input结构体重申明float3 worldNormal,以及INTERNAL_DATA原因。

然后我们使用WorldNormalVector函数来得到最终的法线向量,并用于texCUBE的检索。

 

 

Shader "91YGame/CubeMapLight" {    Properties {        _MainTint("Global Tint",Color)=(1,1,1,1)        _BumpMap ("Normal Map", 2D) = "bump" {}        _AOMap("Ambient Occlusion Map",2D)="white"{}        _CubeMap("Diffuse Convolution CubeMap",Cube)=""{}        _SpecIntensity("Specular Intensity",Range(0,1))=0.4        _SpecWitdth("Specular Width",Range(0,1))=0.2    }    SubShader {        Tags { "RenderType"="Opaque" }        LOD 200                CGPROGRAM        #pragma surface surf DiffuseConvolution        #pragma target 3.0        samplerCUBE _CubeMap;        sampler2D _BumpMap;        sampler2D _AOMap;        float4 _MainTint;        float _SpecIntensity;        float _SpecWitdth;        struct Input {            float2 uv_MainTex;            float2 uv_AOMap;            float3 worldNormal;            INTERNAL_DATA        };        inline fixed4 LightingDiffuseConvolution(SurfaceOutput s,fixed3 lightDir,fixed3 viewDir,fixed atten){            //计算光照向量;            viewDir = normalize(viewDir);            lightDir = normalize(lightDir);            s.Normal = normalize(s.Normal);            float NdotL = dot(s.Normal,lightDir);            float3 halfVec = normalize(lightDir+viewDir);            //计算高光;            float spec = pow(dot(s.Normal,halfVec),s.Specular*128)*s.Gloss;            //光照模型赋值;            fixed4 c;            c.rgb = (s.Albedo*atten)+spec;            c.a = 1;            return c;        }         void surf (Input IN, inout SurfaceOutput o) {            half4 c = tex2D (_AOMap, IN.uv_AOMap);            float3 normals = UnpackNormal(tex2D(_BumpMap,IN.uv_AOMap)).rgb;            o.Normal = normals;            float3 diffuseVal = texCUBE(_CubeMap,WorldNormalVector(IN,o.Normal)).rgb;            o.Albedo = (c.rgb*diffuseVal)*_MainTint;            o.Specular = _SpecWitdth;            o.Gloss = _SpecIntensity*c.rgb;            o.Alpha = c.a;        }        ENDCG    }     FallBack "Diffuse"}

 

 

 

Unity3D ShaderLab 漫反射卷积光照模型