Unity Shader 之 基础光照

摄像机是如何看这个世界的

  游戏中摄像机所看到的世界与我们现实中所看到的几乎是一样的。

  • 首先,光线从光源中发射出来。
  • 然后,光线和场景中的一些物体相交(散射,吸收)。
  • 最后,摄像机吸收了一些光,产生一张图像。

  光线与物体相交的结果有两个:散射(scattering)和吸收(absorption)

  • 散射:只改变光线的方向,但不改变光线的密度和颜色,有两种方向:内部与外部,对应折射与反射。

    • 折射(refraction):散射到物体内部,用漫反射(diffuse)模型来计算。
    • 反射(reflection):散射的物体外部,用高光反射(specular)模型来计算。
  • 吸收:只改变光线的密度和颜色,但不改变光线的方向。

  用不同的光照模型来计算两种不同的散射方向:漫反射模型和高光反射模型。

  • 漫反射:表示有多少光线会被折射、吸收和散射出表面。
  • 高光反射:表示物体表面是如何反射光线的。

标准光照模型

  把进入到摄像机内的光线分为4个部分,每个部分使用一种方法来计算它的贡献度。

  • 自发光(emissive):当给定一个方向时,一个表面本身会发射多少辐射量。(并不能照亮周围的物体,只是显得亮而已)
  • 高光反射(specular):当光线从光源照射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量。
  • 漫反射(diffuse):当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量。
  • 环境光(ambient):描述其他所有的间接光照。

  自发光

  直接采用了该材质的自发光颜色。

  高光反射

  Phong模型公式

    specular = (light · shininess)max(0, v · r)^gloss

    • light:光源颜色
    • shininess:反光度  
    • v:物体到摄像机的方向向量  
    • r:光线的反射方向向量(利用法线方向和光线入射方向可以计算出来,公式为:r = 2(n · l)l)  
    • gloss:光泽度(数值越大亮点越小)

  Blinn模型公式

    specular = (light · shininess)max(0, v · h)^gloss

    • light:光源颜色  
    • shininess:反光度    
    • v:物体到摄像机的方向向量    
    • h:对vl取平均后再归一化,公式:h = v + l / | v + l |
    • gloss:光泽度(数值越大亮点越小)  

  漫反射

  兰伯特定律  

    diffuse = (light · diffuseColor)max(0, n · l)

    • light:光源颜色    
    • diffuseColor:材质漫反射颜色    
    • n:表面法线方向      
    • l:光源的单位矢量  

代码示例(环境光+漫反射+高光反射)

Shader "Unity My Shader/Diffuse Light"
{
    Properties
    {
        _Color("Color", Color) = (1,1,1,1)
        _Specular("Specular", Color) = (1,1,1,1)
        _Gloss("Gloss", Range(8.0, 256)) = 20
    }
    SubShader
    {
        Pass
        {
            Tags{"LightMode"="ForwardBase"}

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            fixed4 _Color;
            fixed4 _Specular;
            float _Gloss;

            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float3 worldPos : TEXCOORD0;
                float3 worldNormal : TEXCOORD1;
            };

            v2f vert (a2v v)
            {
                v2f o;

                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex); // 模型坐标顶点转换世界坐标顶点
                o.worldNormal = UnityObjectToWorldNormal(v.normal); // 模型坐标法线转换世界坐标法线

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNormal = normalize(i.worldNormal); // 法线方向
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos)); // 光照方向
                fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos)); // 视角方向

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; //环境光

                fixed3 diffuse = _LightColor0.rgb * _Color.rgb * max(0, dot(worldNormal, worldLightDir)); // 漫反射

                fixed3 halfDir = normalize(worldViewDir + worldLightDir); // Blinn模型 计算 h
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldViewDir, halfDir)), _Gloss); // 高光反射

                return fixed4(ambient + diffuse + specular, 1); // 相加后输出颜色
            }
            ENDCG
        }
    }
}
时间: 2024-08-03 09:54:43

Unity Shader 之 基础光照的相关文章

Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交:一些光线被物体吸收了,而另一些光线被散射到其他方向. 最后,摄像机吸收了一些光,产生了一张图像. 在光学中,我们使用辐照度来量化光.对于平行光来说,它的辐照度可通过计算在垂直于l的单位面积上单位时间内穿过的能量来得到.在计算光照模型时,我们需要知道一个物体表面的辐照度,而物体表面往往是和l不垂直的,我们可以

第五章 Unity中的基础光照(2)

目录 1. Unity中的环境光和自发光 2. 在UnityShader中实现漫反射光照模型 2.1 实践:逐顶点光照 2.2 实践:逐像素光照 2.3 半兰伯特模型 1. Unity中的环境光和自发光 在标准光照模型中,环境光和自发光的计算是最简单的. 在Unity中,场景中的环境光可以在Window->Lighting->Ambient Source/Ambient Intensity中控制,如下图所示.在Shader中,我们只需要通过Unity的内置变量UNITY_LIGHTMODEL_

Unity Shader 光照模型(基础公式和代码实现)

标准光照模型只关心直接光照(direct light).它把进入摄像机的光照分为4个部分: 自发光(emissive),这部分用于给定一个方向时,物体表面会向这个方向产生多少的光,当没有使用全局光照时,自发光物体不会照亮周围物体,只是本身看起来更亮而已.高光反射(specular),这个部分用于描述当光线从光源照到物体表面时,物体镜面反射产生的光.漫反射(diffuse)这个部分是光线从光源照到物体表面时,物体向各个方向产生的光.环境光(ambient)这个部分用来描述其他间接的光. 1 漫反射

[Unity Shader] 逐顶点光照和逐片元光照

书中的6.4节讲的是漫反射的逐顶点光照和逐片元光照. 前一种算法是根据漫反射公式计算顶点颜色(顶点着色器),对颜色插值(光栅化过程)返回每个像素的颜色值(片元着色器). 第二种算法是获得顶点的法线(顶点着色器),对法线插值(光栅化过程),根据漫反射公式计算像素颜色(片元着色器). 注:漫反射公式:(光源颜色 * 材质漫反射颜色)* (表面法线矢量 · 表面到光源的矢量) 书中对上两种算法的实现如下: 1 Shader "Unity Shaders Book/Chapter 6/Diffuse V

Unity Shader入门精要学习笔记 - 第3章 Unity Shader 基础

来源作者:candycat   http://blog.csdn.net/candycat1992/article/ 概述 总体来说,在Unity中我们需要配合使用材质和Unity Shader才能达到需要的效果.一个最常见的流程是. 1)创建一个材质 2)创建一个Unity Shader,并把它赋给上一步创建的材质 3)把材质赋给要渲染的对象 4)在材质面板中调整Unity Shader的属性,以得到满意的效果 下图显示了Unity Shader和材质是如何一起工作来控制物体的渲染的. Uni

【我的书】Unity Shader的书 — 目录(2015.09.04更新)

写在前面 感谢所有点进来看的朋友.没错,我目前打算写一本关于Unity Shader的书. 出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人一个借鉴.我非常明白学Shader的艰难,在群里也见了很多人提出的问题.我觉得学习Shader还是一件有规律可循的事情,但问题是中文资料难觅,而大家又不愿意去看英文...这对我有什么好处呢?强迫我对知识进行梳理,对细节问题把握更清楚. 第二个原因你懂的. 关于本书的定位问题: 面向Unity Shader初学者,但要: 有一定的

【我的书】Unity Shader的书 — 目录(2016.1.29更新)

写在前面 感谢所有点进来看的朋友.没错,我目前打算写一本关于Unity Shader的书. 出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人一个借鉴.我非常明白学Shader的艰难,在群里也见了很多人提出的问题.我觉得学习Shader还是一件有规律可循的事情,但问题是中文资料难觅,而大家又不愿意去看英文...这对我有什么好处呢?强迫我对知识进行梳理,对细节问题把握更清楚. 第二个原因你懂的. 关于本书的定位问题: 面向Unity Shader初学者,但要: 有一定的

【我的书】Unity Shader的书 — 文件夹(2015.12.21更新)

写在前面 感谢全部点进来看的朋友.没错.我眼下打算写一本关于Unity Shader的书. 出书的目的有以下几个: 总结我接触Unity Shader以来的历程,给其它人一个借鉴.我非常明确学Shader的艰难,在群里也见了非常多人提出的问题. 我认为学习Shader还是一件有规律可循的事情,但问题是中文资料难觅,而大家又不愿意去看英文...这对我有什么优点呢?强迫我对知识进行梳理,对细节问题把握更清楚. 第二个原因你懂的. 关于本书的定位问题: 面向Unity Shader刚開始学习的人,但要

【我的书】Unity Shader的书 — 目录(实时更新中)

写在前面 感谢所有点进来看的朋友.没错,我目前打算写一本关于Unity Shader的书. 出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人一个借鉴.我非常明白学Shader的艰难,在群里也见了很多人提出的问题.我觉得学习Shader还是一件有规律可循的事情,但问题是中文资料难觅,而大家又不愿意去看英文...这对我有什么好处呢?强迫我对知识进行梳理,对细节问题把握更清楚. 第二个原因你懂的. 关于本书的定位问题: 面向Unity Shader初学者,但要: 有一定的