zoukankan      html  css  js  c++  java
  • Unity3D ShaderLab 漫反射卷积光照模型

    http://www.cnblogs.com/2Yous/p/4251444.html

     

    Unity3D ShaderLab 漫反射卷积光照模型

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

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

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

    下载地址:

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

     

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

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

     

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

    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"
    }
  • 相关阅读:
    Two strings CodeForces
    Dasha and Photos CodeForces
    Largest Beautiful Number CodeForces
    Timetable CodeForces
    Financiers Game CodeForces
    AC日记——整理药名 openjudge 1.7 15
    AC日记——大小写字母互换 openjudge 1.7 14
    AC日记——将字符串中的小写字母换成大写字母 openjudge 1.7 13
    AC日记——加密的病历单 openjudge 1.7 12
    AC日记——潜伏着 openjudge 1.7 11
  • 原文地址:https://www.cnblogs.com/alps/p/7112900.html
Copyright © 2011-2022 走看看