zoukankan      html  css  js  c++  java
  • 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"
    }

     

     

  • 相关阅读:
    netty+springboot+oracle+protobuf 搭建客户端服务端
    netty框架学习记录
    sql查询替换逗号拼接的字符窜
    Node的webpack打包的核心思想就是单页面富应用(SPA)
    Javascript 中的 CJS, AMD, UMD 和 ESM是什么
    springboot读取jar中resource下的文件
    zmq模块的理解和使用二
    问问题
    Java解析kml文件
    练习本
  • 原文地址:https://www.cnblogs.com/2Yous/p/4251444.html
Copyright © 2011-2022 走看看