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"
    }
  • 相关阅读:
    java面试题2
    java面试题
    查询数据库表字段名和字段类型等信息
    安装eclipse
    redis启动
    eclipse离线安装sonarlint插件
    大白菜安装win10系统
    制作window.ios镜像
    大白菜装机系统
    传递中文字符串时,转换编码格式
  • 原文地址:https://www.cnblogs.com/alps/p/7112900.html
Copyright © 2011-2022 走看看