zoukankan      html  css  js  c++  java
  • 基础光照模型、着色及效果(二)

    参考源Illumination Models and Shaing翻译声明仅供学习交流https://www.cnblogs.com/baolong-chen/category/1559372.html

    为了尽可能得到真实感图像画面,必须要模拟物体表面在多种光照条件影响下的图像呈现

    一、Lighting Model Method


    Lighting Model params

    light source参数

    • 位置-Position
    • 光谱光波-Electromagnetic Spectrum
    • 光源形状-Shape

    object sucface参数

    • 位置-Position
    • 反射率属性-Reflectance properties
    • 邻近面-Position of nearby surcface

    camera(eye)参数

    • 镜头位置-Position Sensor
    • spectrum sensitivities


    Ambient Illumination-环境光

    假定场景没有方向光只有环境光,且环境光入射到每个物体表面的量和方向是恒定的,这个理想的光照模型在现实世界基本不存在的。

    公式:Iamb = Ka·Ia

    Ia: 环境光强度,

    Ka∈[0,1]: 物体表面反射率

    最后把IRamb,IGamb,IBamb传递给模型顶点或像素颜色RGB

    Unity中环境光宏定义:#define UNITY_LIGHTMODEL_AMBIENT (glstate_lightmodel_ambient * 2)

     

    Diffuse Reflection-漫反射

    image图1

    漫反射公式:Idiff = Kd·Ip·Cos(θ) = Kd·Ip·(N·L)

    Lambert余弦定律:反射强度与表面的平滑度相关,与入射角度Sin(α)成反比或者Cos(θ)成正比

    Ip:光源强度,也可作为衰减光源fatt(r)Ip---光照颜色

    Kd∈[0,1]:物体表面反射率

    N:平面法线, (使用前要归一化运算)

    L:光源方向,(使用前要归一化运算)

    漫反射和环境光合并公式:I = Idiff + Iamb = Kd·Ip·(N·L) + Ka·Ia

    最后把IR IG IB 传递给模型顶点或像素颜色RGB即可

    //漫反射和环境光合并
    //可以转换到模型空间、切线空间、世界空间
    v2f vert(a2v a) {
        v2f v;
        v.pos = UnityObjectToClipPos(a.vertex);
        //模型空间
        /*fixed3 mn = normalize(a.normal);            
        fixed3 lightdir = normalize(ObjSpaceLightDir(a.vertex));
        fixed3 val =  max(0, dot(mn, lightdir));
        fixed3 diff = _Smoothness * _LightColor0.rgb * val * _Diffuse.rgb;
        v.color = UNITY_LIGHTMODEL_AMBIENT.xyz + diff;*/
        //世界空间---由于世界空间有许多信息例如环境映射、光照、视角,一般推荐转换到世界空间
        fixed3 wm = normalize(mul(a.normal, (float3x3)unity_WorldToObject));
        fixed3 lightdir = normalize(_WorldSpaceLightPos0.xyz);
        fixed3 val = max(0, dot(wm, lightdir));
        fixed3 diff = _Smoothness * _LightColor0.rgb * val * _Diffuse.rgb;
        v.color = UNITY_LIGHTMODEL_AMBIENT.xyz + diff;
        return v;
    }

     

    Specular Reflection-高光反射

    镜面(高光)反射,模拟陶瓷、金属等光滑表面材质,反射角影响反射强度。

    image图2

    image图3

    公式(Phong Model):Ispec = Ks·Ip·cosn(Φ) = Ks·Ip·(R·V)n

    Ks:物体表面高光反射率

    Ip:光源强度---光照颜色

    L:光源方向

    N:平面法线

    R:反射方向

    V:视线方向

    n:高光反射系数,决定着与理想高光反射模型的偏差

    R推导过程

    image图4

    R推导过程:理想的反射模型是等腰三角形(见图2)。L入射起点,R反射终点。

    矢量R = OR = LR–LO = 2LP-LO = 2(LO+OP)-LO = LO+2OP

    LO已知,那么求得LO在法向量上的投影OP即可,

    取得N的单位向量n:n=OP/|OP|=N/|N|

    取得三角函数值: image

    结合点积函数与三角函数可得image

    R = 2·dot(n, L)·n – L == reflect(-L,n)

    v2f vert(a2v a) {
        v2f v;
        v.position = UnityObjectToClipPos(a.vertex);
        fixed3 world_pos        = mul(a.vertex, unity_WorldToObject);
        fixed3 world_n          = normalize(mul(a.normal, (float3x3)unity_WorldToObject));
        fixed3 world_light_dir  = normalize(UnityWorldSpaceLightDir(world_pos));//顶点指向光源
        fixed3 world_view_dir   = normalize(_WorldSpaceCameraPos.xyz - world_pos);//顶点指向摄像机
        //reflect函数参数需要从入射光到顶点方向
        fixed3 world_ref_dir  = normalize(2 * dot(world_n,world_light_dir)*world_n - world_light_dir);//reflect(-world_light_dir,world_n);
        fixed3 spec_color   = _Ks * _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(world_ref_dir, world_view_dir)), _N);
        fixed3 diff_color   = _Kd * _LightColor0.rgb * saturate(dot(world_n, world_light_dir));
        fixed3 ambient      = UNITY_LIGHTMODEL_AMBIENT.xyz;
        fixed3 color        = ambient + diff_color + spec_color;
        v.color = color;
        return v;
     }



    组合环境光、漫反射、高光

    公式:I = Iamb + Idiff + Ispec = Ka·Ia + Ip (Kd· N ⋅ L + Ks (R⋅V)n)

    v2f vert(a2v a) {
        /*同上...*/
        fixed3 diff_color  = _Kd * _LightColor0.rgb * saturate(dot(world_n, world_light_dir));
        fixed3 ambient     = UNITY_LIGHTMODEL_AMBIENT.xyz;
        fixed3 color       = ambient + diff_color + spec_color;
    
        v.color = color;
         return v;
    }

    翻译声明仅供学习交流https://www.cnblogs.com/baolong-chen/category/1559372.html

    二、Polygon Rendering Methods


    Flat Shading-略

    UnityStore有一款插件:Poly World

    Gouraud Shading

    • 获取每个多边形的顶点法线
    • 带入光照模型计算每个顶点的光照强度
    • 在曲面多边形线性插值顶点强度

    根据上述三点,基本确定是在顶点着色内进行着色运算

    高洛德着色中,公共顶点法线(红点法线)来源于所有共点面法线的平均值,如下图。主要目的是对三个顶点组成的三角面内部进行着色,而其他三角面没有被照射到,就不会有光照效果。

    image图5

    实现代码,参考上面的vert(a2f a)函数即可

    Phong Shading

    • 获取每个多边形法线
    • 在曲面多边形线性插值顶点法线
    • 带入光照模型计算每个片元内像素点的光照强度

    上述三点,前面两点在顶点着色器计算,最后一步的着色计算在片元着色器

    v2f vert(a2v a) {
        v2f v;
        v.position          = UnityObjectToClipPos(a.vertex);
        v.world_normal      = UnityObjectToWorldNormal(a.normal);
        v.world_position    = mul(UNITY_MATRIX_M, a.vertex);
        v.world_light_dir   = UnityWorldSpaceLightDir(v.world_position);//顶点指向光源
        v.world_view_dir    = UnityWorldSpaceViewDir(v.world_position);//顶点指向摄像机
        return v;
    }
        fixed4 frag(v2f v) : SV_Target{
        fixed3 world_pos    = normalize(v.world_position);
        fixed3 world_n      = normalize(v.world_normal);
        fixed3 world_light_dir   = normalize(v.world_light_dir);
        fixed3 world_view_dir    = normalize(v.world_view_dir); 
        fixed3 world_ref_dir = normalize(2 * dot(world_n, world_light_dir) * world_n - world_light_dir);
        fixed3 spec_color = _Ks * _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(world_ref_dir, world_view_dir)), _N);
        fixed3 diff_color = _Kd * _LightColor0.rgb * saturate(dot(world_n, world_light_dir));
        fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
        fixed3 color   = ambient + diff_color + spec_color;
        return fixed4(color, 1.0f);
    }

    最后效果图:高洛德着色与冯着色效果如下图:

    image图6

  • 相关阅读:
    mysql是如何启动的?
    qt终于安装成功
    随笔
    博客首写
    为什么你预约不了政府特供口罩-太难了
    jQuery 选择器(转)
    [JS]Cookie精通之路
    存储过程分页 简单列子
    泛型集合List<T> Dictionary<K,V>
    数据绑定控件
  • 原文地址:https://www.cnblogs.com/baolong-chen/p/11669311.html
Copyright © 2011-2022 走看看