Cook-Torrance光照模型

Cook-Torrance光照模型

  该光照模型是基于物理材质的光照模型。光照射到物体表面发生漫反射、镜面反射、折射、透射等现象,在这里我们只考虑漫反射和镜面反射,Cook-Torrance是用来模拟不同材质的镜面反射效果。

  

    其中:

      ambient :环境光;

      K:决定高光部分和漫射的比例,一般而已,光复合能量守恒定律,即入射光的总能量和出射光的总能量相等;

      rs :镜面发射;

  

F项:菲涅尔反射

  即Fresnel,菲涅尔反射。我们在观察水面的时候,垂直看下去,清澈见底,看远处的水面,向镜子一样,这个就是菲涅尔效应。菲涅尔效应可以说是无处不在,不同的材质效果不同而已。

  

    v:视点的方向;

    h:半角向量,即视点和光线的中间向量;

D项:微平面法线分布函数

  该项模拟物体表面是由无数微小的像镜子一样的平面组成,每一个微平面对于光线会根据自身的方向反射光线,只有那些面向视点的平面贡献大。具体参见微平面法线分布的理论。

  

G项:几何项

   该项用于计算微平面中反射光重合部分的修正。

  

  

  

=============================================================================

Shader "JQM/Cook-Torrance"
{
    Properties
    {
        _Color("Base Color",Color) = (1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}

        _Roughness("Roughness",Range(0,1)) = 1
        _Fresnel("Fresnel",Range(0,1)) = 1
        _K("K",Range(0,1)) = 1
    }

    SubShader
    {

        Pass
        {
            Tags { "LightMode" = "ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            float4 _Color;
            //使用Unity定义的变量:灯光
            uniform float4 _LightColor0;

            float _Roughness;
            float _Fresnel;
            float _K;

            struct VertexOutput
            {
                float4 pos : SV_POSITION;
                float4 posWorld : TEXCOORD1;
                float2 uv : TEXCOORD2;
                float3 normal:Normal;

            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            VertexOutput vert (appdata_full v)
            {
                VertexOutput o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.posWorld = mul(_Object2World, v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.normal = v.normal;

                return o;
            }

            fixed4 frag (VertexOutput i) : COLOR
            {
                //将法线转到世界空间:乘以变换矩阵的逆的转置
                //float3 normalWorld  = mul(_Object2World,i.normal);
                float3 normalWorld  = mul(i.normal,_World2Object);

                //观察者
                float3 eyeDir = normalize(_WorldSpaceCameraPos -i.posWorld).xyz;

                //光源
                float3 lightDir = normalize(_WorldSpaceLightPos0).xyz;

                fixed4 col = tex2D(_MainTex, i.uv);

                ///计算漫反射
                float3 diffuse = _Color*saturate(dot(lightDir,normalWorld))*_LightColor0/3.14 ;

                //计算高光
                //float3 h = (eyeDir+lightDir)/2;
                //float3 r = normalize(reflect(-lightDir,normalWorld));
                //float3 specular = saturate(dot(lightDir,normalWorld))* _SpecularColor * pow(saturate(dot(r,eyeDir)),_SpecularPower);

                //计算Cook-Torrance高光
                float s;
                float ln = saturate(dot(lightDir,normalWorld));

                if(ln > 0.0)//在光照范围内
                {
                    float3 h = normalize(eyeDir+lightDir);
                    float nh = saturate(dot(normalWorld, h));
                    float nv = saturate(dot(normalWorld, eyeDir));
                    float vh = saturate(dot(eyeDir, h));

                    //G项
                    float nh2 = 2.0*nh;
                    float g1 = (nh2*nv)/vh;
                    float g2 = (nh2*ln)/nh;
                    float g = min(1.0,min(g1,g2));

                    //D项:beckmann distribution function
                    float m2 = _Roughness*_Roughness;
                    float r1 = 1.0/(4.0 * m2 *pow(nh,4.0));
                    float r2 = (nh*nh -1.0)/(m2 * nh*nh);
                    float roughness = r1*exp(r2);

                    //F项
                    float fresnel = pow(1.0 - vh,5.0);
                    fresnel *= (1.0-_Fresnel);
                    fresnel += _Fresnel;
                    s = saturate((fresnel*g*roughness)/(nv*ln*3.1415926));
                }

                float3 specular =_LightColor0*ln*(_K + s*(1-_K));
                float3 final = _K*diffuse + specular + UNITY_LIGHTMODEL_AMBIENT.xyz;
                return float4(final,1);
            }
            ENDCG
        }
    }
}

  

时间: 2024-11-03 20:52:53

Cook-Torrance光照模型的相关文章

unity3d shader的软高光的金属效果

软高光的金属效果 学了书里的这一章有很多知识我也很不了解,于是查了一些资料,渐渐的明朗了一些,,一下结合书里的知识和网上的资料与我的理解来说明 主要原理是Cook-Torrance光照模型的算法,是BRDF(双向反射分布函数)的一种,具体算法请看后面 新建一个shader 先浏览一下变量 _MainTint 主色调 _RoughnessTex   粗糙度贴图(控制高光大小) _Roughness 表面粗糙程度 _SpecularColor  高光颜色 _SpecPower  高光强度 _Fres

局部光照模型

提要 常见的光照模型一般包括四个部分ambient, diffuse, specular, 和emitted light. 即: vertex color = ambient + diffuse + specular + emitted light 当有多个光源的时候,最后的颜色就是多个结果的叠加. Ambient light:环境光,通常定义在光源的中,注意每个光源的衰减量. Diffuse:漫反射部分,光照找到物体的表面,由于物体的表面凹凸不平而反射到各个方向的光. Specular :相比

【Unity Shaders】学习笔记——SurfaceShader(十)镜面反射

[Unity Shaders]学习笔记——SurfaceShader(十)镜面反射 如果你想从零开始学习Unity Shader,那么你可以看看本系列的文章入门,你只需要稍微有点编程的概念就可以. 水平有限,难免有谬误之处,望指出. Unity内置的高光函数 Unity内置了一种高光光照模型——BlinnPhone. 使用方法如下: Shader "Custom/BlinnPhong"{ Properties { _MainTex ("Base (RGB)", 2D

OpenGL ES 2.0基本概念

1. OpenGL ES 2.0可编程管道 OpenGL负责把三维空间中的对象通过投影.光栅化转换为二维图像,然后呈现到屏幕上. 上图黄色部分(Vertex Shader和Fragment Shader)为此管道的可编程部分.整个管道包含以下两个规范: 1) OpenGL ES 2.0 API specification 2) OpenGL ES Shading Language Specification (OpenGL ES SL) 详细流程图如下: 此流程把三维数据变换为可以显示的二维数据

opengl ES

1. OpenGL ES 2.0可编程管道 OpenGL负责把三维空间中的对象通过投影.光栅化转换为二维图像,然后呈现到屏幕上. 上图黄色部分(Vertex Shader和Fragment Shader)为此管道的可编程部分.整个管道包含以下两个规范: 1) OpenGL ES 2.0 API specification 2) OpenGL ES Shading Language Specification (OpenGL ES SL) 详细流程图如下: 此流程把三维数据变换为可以显示的二维数据

Cook-Torrence Illumination Model 的一些数学说明

Cook-Torrence 光照模型如下: 这个Io就是计算后最终的光强,主要是用来计算镜面反射光,漫反射和环境光的计算和Phong模型一致. F:Fresnel反射系数.主要用来说明反射光强度占入射光强的比例.<3D计算机图形学(opengl版)>中由介绍.Fresnel系数和Snell系数的关系为: Fresnel确定反射或者折射的光的能量大小,就是亮度.Snell则是确定反射和折射的方向. D:微平面分布函数.它的一般表达式为D = f(θ),其中D是一个数值,它代表了一个平面中的能够将

Lambert光照模型

lambert光照模型只考虑环境光和漫反射光的影响. 因此在计算的时候,你只需要知道光源的位置和物体上受光点法线的方向即可,而无需知道视点在哪里. 通常来说,lambert光照的最终颜色为:ambient_color*ambient_factor+diffuse_color*diffuse_factor*Diffuse_intensity 光照强度跟物体表面的受光点到光源防线的向量,与物体表面法线的夹角有关.夹角越小,越亮,反之,越暗. 由Lambert渲染出来的物体表面没有最亮的那一点光斑.

CG基本光照模型备忘

Blinn-Phong光照模型: 其中..分别是光源的环境光(ambient).漫反射光(diffuse).镜面反射光(specular)亮度,..则描述了物体材质对这几类光的反射系数,是表面法线,-L是光的方向,是物体表面都eye的单位向量,是入射光线的反射方向,s是高光系数.Blinn-Phong是非物理的,因而其参数调整常常依赖与多次试验.一般而言,导体的镜面反射(高光)较强,而绝缘体的镜面反射很小. 平行光源: 点光源: 其中是光源到目标的距离.理论上,,这里添加它们并不"物理"

Unity3D ShaderLab 车辆喷漆光照模型实战

这一篇,我们来创建一个车辆喷漆的光照模型.首先就是准备场景,新建Shader & Material. 过程比较简单,直接看完成的代码吧: Shader "91YGame/CarOutLight" { Properties { _MainTint("Diffuse Tint",Color)=(1,1,1,1) _MainTex ("Base (RGB)", 2D) = "white" {} _SpecularColor(

Unity3D ShaderLab 自定义光照模型

接着上一篇BasicMyDiffuse来说,这次要说明的就是自定义的光照模型. 1.>//#pragma surface surf Lambert::这个是默认的光照模型 2.>#pragma surface surf CusDiffuse //自己定义的光照模型CusDiffuse; 3.>在SubShader 中加入光照模型函数: inline float4 LightingCusDiffuse(SurfaceOutput s,fixed3 lightDir,fixed atten)