• 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"
    }

     

     

  • 相关阅读:
    JSP环境探针-当前电脑所有系统参数
    SqlServer service broker 分布式系统(赵松桃)跳水 2005 数据库编程
    主机Window不能访问该虚拟机Linux Samba文件服务提供了一个文件夹
    hdu 4901 The Romantic Hero
    linux、hdfs、hive、hbase经常使用的命令
    Android 设计模式模式适配器
    PHP扩展memcache模
    算法——字符串匹配Rabin-Karp算法
    三个重要的散列演示
    CodeForces 10C. Digital Root
  • 原文地址:https://www.cnblogs.com/2Yous/p/4251444.html
Copyright © 2020-2023  润新知