Shader学习笔记(三):Shader中的光照

Unity 3D 静态对象 Lightmap Lightmap 技术的原理是将场景中的灯光与物体产生的光照与阴影信息烘培在一张或者多张Lightmap 贴图中,这些物体将不再参与实时光照计算,从而减少了大量的性能开销。 它的缺点就是参与烘培计算的对象在游戏过程中不能发生移动。 所以游戏中通常会将物体分成两类:一类是可发生位移变化的对象,他们使用实时光照计算;另一类是不可发生位移变化的,他们采取预先烘培Lightmap。 //--设置烘培... 阅读详情

这篇文章讨论shader中用到的光照。

理解光照

Unity中的光照技术包括:

  • 实时光照(realtime lighting)
  • 烘焙后的光照贴图(baked lightmaps)
  • 预计算的实时全局光照(precomputed realtime global illumination)
实时光照

Unity最基础的光照方式,能够随光线和物体移动实时变化。但是只能处理直射光,无法处理反射光,所以只是一种局部光照。

烘焙后的光照贴图

Unity可以将静态物体的光照信息(包括直射光和反射光)预先烘焙到一张贴图(lightmap)上,供运行时使用,从而避免动态计算。

lightmap的原理是:预先计算整个光照路径(只除去物体表面到摄像机的一段)。

它的优点是省去了运行时计算的代价,缺点是运行时无法改变。

另外一种烘焙方式叫光照探针(light probe)。与lightmap的不同点在于:lightmap烘焙的是射到物体表面的光;而light probe烘焙的是空间中的传播光,可用于静态物体到动态物体的反射。

Unity将光照数据存储在名为Lighting Data Asset的文件中。它是Unity 5.3新增的文件,替代原来的Snapshot。用于存储GI数据,以及render、lightmap、light probe等的引用。

预计算的实时全局光照

预计算静态物体之间所有可能的反射并编码,在运行时再生成间接光照。运行时可以随光源位置、方向、颜色的改变而改变。Unity 5.0支持的新功能,需要设置开启。

优点是既能随光源动态改变,也能降低运行时消耗;缺点是只能针对静态物体。

各种光照技术比较

三种技术典型的应用场景包括:

  • 实时光照:移动的角色。
  • 烘焙后的光照贴图:场景中静态的物体。
  • 预计算的实时全局光照:一天之内的阳光,随时间变化而角度、强度各不相同。

在移动设备上适合用baked lightmaps,在PC上适合用precomputed realtime GI。

光源类型
名字英文名解释
点光源point light从一个点向四面八方发射,类似电灯泡
锥形光spot light从一个点以锥形发出,类似手电筒
有向光directional light以固定方向平行发出,类似太阳
区域光area light光线限制在一个矩形区域内,固定从一侧以任意角度发出
环境光ambient light光在场景中无处不在,不从特定物体发出

理解阴影

unity中的阴影分为实时阴影和阴影贴图。

  • 实时阴影:实时光产生的阴影。要使用这种阴影,需要在产生的物体上开启投射(cast),在投影到的物体上开启接收(receive)。
  • 阴影贴图:以贴图方式实现的阴影。这种方式可以降低运行时消耗,但是阴影的大小、形状都是固定的。

shader中的光照

光照是如何影响我们的视觉的呢?事实上,我们之所以能看到物体,除去那些能自发光的物体外(如灯泡),都是因为光线射到物体表面再反射到我们眼睛中。一个物体之所以呈现不同颜色,那是因为它对光的不同颜色分量的反射率不一样。例如,红色的物体对于红光几乎全部反射,而对于绿光和蓝光几乎全部吸收。所以,物体最终呈现在我们眼中的颜色,取决于反射光和自发光的叠加。

不同的光照模型对于反射光的处理大不一样。Unity中内置了两种光照模型:Lambert光照是漫反射,光线射过去向四面八方反射,适合于普通较粗糙的材质;BlingPhong光照是镜面反射,适合光滑如镜的材质。这两种光照就可以涵盖绝大多数情况。除此之外,我们也可以根据需求自己定制光照模型。

Unity中可以使用Surface Shader或者Vertex/Fragment Shader来处理光照。对于前者,需要自定义光照处理函数;对于后者,则需要在vert函数中做varying变量的赋值,而在frag函数中处理光照。对于Surface Shader和光照函数在渲染管线中的位置,可以看图(来自知乎):
这里写图片描述

可以看到,surf函数和光照都位于Fragment Shader中,两者是紧挨着的关系。

实例解析

以下均为Unity Manual中的例子。

Surface Shader中的光照
  • DiffuseTexture:与Lambert光照等效的实现。自定义光照类型SimpleLambert,对应的函数在surf之后执行。计算顶点颜色涉及到的参数:片元的法向量、光入射角度、光的rgba和衰减、片元的Albedo。

这里写图片描述

   Shader "Example/Diffuse Texture" {
        Properties {
            _MainTex ("Texture", 2D) = "white" {}
        }
        SubShader {
        Tags { "RenderType" = "Opaque" }
        CGPROGRAM
          #pragma surface surf SimpleLambert

          half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) {
              half NdotL = dot (s.Normal, lightDir);
              half4 c;
              c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten);
              c.a = s.Alpha;
              return c;
          }

        struct Input {
            float2 uv_MainTex;
        };

        sampler2D _MainTex;

        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
        }
        ENDCG
        }
        Fallback "Diffuse"
    }
  • SimpleSpecular:与BlingPhong光照等效的实现。计算顶点颜色涉及到的参数:视角、片元的法向量、光入射角度、光的rgba和衰减、片元的Albedo。

这里写图片描述

    ...ShaderLab code...
    CGPROGRAM
    #pragma surface surf SimpleSpecular

    half4 LightingSimpleSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
        half3 h = normalize (lightDir + viewDir);

        half diff = max (0, dot (s.Normal, lightDir));

        float nh = max (0, dot (s.Normal, h));
        float spec = pow (nh, 48.0);

        half4 c;
        c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * atten;
        c.a = s.Alpha;
        return c;
    }

    struct Input {
        float2 uv_MainTex;
    };

    sampler2D _MainTex;

    void surf (Input IN, inout SurfaceOutput o) {
        o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
    }
    ENDCG
    ...ShaderLab code...
Vertex/Fragment Shader中的光照

要使用光照,首先需要在pass tag中设置LightMode,从而定义各种rendering path。常见的选择有:

关键字意义解释
ForwardBaseforward rendering使用关键光照信息立即渲染
Deferreddeferred shading使用所有光照信息延迟渲染
ShadowCastershadow caster投射阴影所必需,通常与ForwardBase或Deferred配合使用
  • SimpleDiffuse:与Lambert光照等效。需要在vert和frag中做处理。

这里写图片描述

Shader "Lit/Simple Diffuse"
{
    Properties
    {
        [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Pass
        {
            // indicate that our pass is the "base" pass in forward
            // rendering pipeline. It gets ambient and main directional
            // light data set up; light direction in _WorldSpaceLightPos0
            // and color in _LightColor0
            Tags {"LightMode"="ForwardBase"}

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc" // for UnityObjectToWorldNormal
            #include "UnityLightingCommon.cginc" // for _LightColor0

            struct v2f
            {
                float2 uv : TEXCOORD0;
                fixed4 diff : COLOR0; // diffuse lighting color
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata_base v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;
                // get vertex normal in world space
                half3 worldNormal = UnityObjectToWorldNormal(v.normal);
                // dot product between normal and light direction for
                // standard diffuse (Lambert) lighting
                half nl = max(0, dot(worldNormal, _WorldSpaceLightPos0.xyz));
                // factor in the light color
                o.diff = nl * _LightColor0;
                return o;
            }

            sampler2D _MainTex;

            fixed4 frag (v2f i) : SV_Target
            {
                // sample texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // multiply by lighting
                col *= i.diff;
                return col;
            }
            ENDCG
        }
    }
}
  • ShadowCasting:实现阴影投射。定义了两个Pass,LightMode分别是ForwardBase和ShadowCaster。

这里写图片描述

Shader "Lit/Shadow Casting"
{
    SubShader
    {
        // very simple lighting pass, that only does non-textured ambient
        Pass
        {
            Tags {"LightMode"="ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            struct v2f
            {
                fixed4 diff : COLOR0;
                float4 vertex : SV_POSITION;
            };
            v2f vert (appdata_base v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                half3 worldNormal = UnityObjectToWorldNormal(v.normal);
                // only evaluate ambient
                o.diff.rgb = ShadeSH9(half4(worldNormal,1));
                o.diff.a = 1;
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                return i.diff;
            }
            ENDCG
        }

        // shadow caster rendering pass, implemented manually
        // using macros from UnityCG.cginc
        Pass
        {
            Tags {"LightMode"="ShadowCaster"}

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_shadowcaster
            #include "UnityCG.cginc"

            struct v2f { 
                V2F_SHADOW_CASTER;
            };

            v2f vert(appdata_base v)
            {
                v2f o;
                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
                return o;
            }

            float4 frag(v2f i) : SV_Target
            {
                SHADOW_CASTER_FRAGMENT(i)
            }
            ENDCG
        }
    }
}
0基础UnityURP渲染管线之阴影ShadowCaster-ShadowMask-Map傻傻分不清楚(代码向) 很多刚接触图形学渲染Renderer,特别是入门工具是Unity的同学很容易混淆各种Shadow概念; 第一眼看到这样的代码:Pass{ “ShadowCaster",就先入为主认为这是渲染Shadow的代码 投影的最基本原理就是 1.光源 2.遮挡者(投射源) 3.阴影绘制(Object Render) 一个Shader的结构长这样,不让人误解才怪呢 其实ShadowCaster Pass,才是投射源,而阴影的绘制和颜色的绘制没差,其实都在ForwardPass(或者DefferPass, 阅读详情

相关推荐

Unity昼夜变换(lightmap+天空球)

烘焙出两组lightmap,并在shader中进行采样;最后插值输出混合结果。天空球也是同理可得。

TingQiaoQiao的博客 1647

【计算机图形学/实时渲染】 阴影(GAMES202)

关于Light Map,Shadow Map,PCF,PCSS的介绍,参考GAMES202

qq_42885747的博客 1857

【Unity Shaders】Shader中的光照

写在前面自己写过Vertex & Fragment Shader的童鞋,大概都会对Unity的光照痛恨不已。当然,我相信这是因为我们写得少。。。不过这也是由于官方文档对这方面介绍很少的缘故,导致我们无法自如地处理很多常见的光照变量。这篇我们就来讨论下Unity内置的一些光照变量和函数到底怎么用。以下内容均建立在Forward Rendering Path的基础上。Forward Rendering

candycat 5万+

采样定理:信号还原的关键法则

采样是将连续信号转换为离散信号的过程,采样定理(奈奎斯特)指出采样频率必须大于信号最高频率的2倍才能避免混叠失真。混叠会导致高频分量被误认为低频,影响信号还原。采样过程包括信号输入、滤波、采样和离散化,广泛应用于音频、视频等领域。关键是要确保采样足够快,才能完整保留原始信号信息。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 2562

unity shader——unity中的光照设置

1.环境光 环境光通常是一个全局变量,即场景中的物体都使用这个环境光。() Window->Rendering->Lightting Setting 环境光来源有三种:Color、Skybox、Gradient 2.自发光 一个材质的自反光计算直接使用了它的自发光颜色() 大多数物体是没有自发光特性的,在unity中如果要计算自发光,只需要在片元着色器输出最后的颜色之前...

独孤易郎的博客 2701

GAMES104:05游戏引擎中的渲染系统2:渲染中的光照、材质和shader-学习笔记

PBR+IBL。

噗噗噗的博客 2136

《Unity Shader入门精要》学习笔记三(复杂的光照)

本文系统介绍了Unity中的渲染路径和光照处理技术。主要内容包括:1. 渲染路径类型及选择:包括前向渲染、延迟渲染和顶点光照渲染三种路径的特点和适用场景,强调通过LightMode标签指定路径的重要性。2. 前向渲染原理:详细解释逐物体逐像素的绘制流程,以及多光源处理时的性能优化策略。3. 延迟渲染特点:分析其两阶段处理(几何Pass和光照Pass)的优势与局限性。4. 光源类型处理:涵盖平行光、点光源和聚光灯的属性访问与衰减计算。5. 阴影实现技术:包括ShadowMap机制和屏幕空间阴影技术,以及使用S

benben044的专栏 1158

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

Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照本系列为UnityShader入门精要读书笔记总结, 原作者博客链接:http://blog.youkuaiyun.com/candycat1992/article/ 书籍链接:http://product.dangdang.com/23972910.html第6章 开始 Unity 中的基础光照6.1 我们是如何看到这个

那远远的云端 1949

Shader学习笔记(三)自定义光照模型,经典光照模型Lambert与HalfLambert

Unity Shader自定义光照模型,经典光照模型Lambert与HalfLambert

henger_的博客 3005

【unity shader】《unity shader入门精要》 光照模型

unity shader中的漫反射+高光反射光照模型 光照模型是shader的核心,它描述了光线同物体的交互方式。 对于非透明物体,光照模型一般包含两部分:漫反射和高光反射。 一个常见的包含漫反射与高光反射的shader程序如下: Shader "Unity Shaders Book/Chapter 6/Diffuse Pixel-Level" { Properties

CMOSTER的隐秘修行 1460

PRPD图谱分析从入门到精通:5种典型放电模式的识别手册

本文详细解析PRPD图谱分析技术,重点介绍电晕放电、悬浮放电等5种典型放电模式的识别方法。通过37组真实案例对比,提供关键识别区和诊断流程图模板,帮助工程师快速掌握变电站设备状态监测的核心技能,提升绝缘缺陷诊断准确率。

weixin_29214199的博客 467

u3d shader着色器学习笔记(三)——光照

光照模型就是一个公式,使用这个公式来计算在某个点的光照效果。标准光照模型(在标准光照模型里,我们把进入摄像机的光分为下面四个部分):自发光高光反射(类似镜子的反射)漫反射(类似石头) Diffuse = 直射光颜色 *  max(0,COS 夹角(光和法线的夹角))环境光(均匀反射)一些方法:normalize() 用来把一个向量,单位化(原来的方向保持不表,长度为1)即向量的方向向量max()用...

nihao561的博客 473

AD9371 官方例程构建及单音信号收发

项目构建基本流程和AD9361差不多,由于官方使用的ZCU102,记录下移植遇到的一些问题最终接收到正确的正弦波Errors: 0Errors: 0Errors: 0Errors: 0AD9361。

weixin_44630490的博客 2973

第五天 开始Unity Shader的学习之旅之Unity中的基础光照之漫反射光照模型

今天来介绍一下Unity Shader中的漫反射光照模型中的逐顶点光照,同时大致说一下环境光和自发光部分的计算.

qq_52276934的博客 1850

【SAP PO】SAP PO 接口配置完整教程之二REST服务对接

SAP PO 接口配置完整教程之二REST服务对接

XLevon的博客 1万+

载波同步技术(一):BPSK的Costas Loop 载波同步

Author:McCrocodile 2010/11/04          载波的提取在相干解调中往往比较重要,根据信号中是否包含载频分量,载波同步一般也可以分为两种方法。包含载频分量的可以采用窄带滤波或者基本的锁相环环路来实现,不包含的则比较麻烦需要采用特殊的环路实现载波的同步。这里介绍的BPSK的载波恢复就属于后面一种。 对于不包含载频分量的信号载波同步一般有:同相-正交环(就是常说的Costas环)、判决反馈环(几乎可以适用所有调制方式)、同相-正交环衍生环(QPSK松尾环、N相同相-正交环)。

McCrocodile Blog 1万+

Shader 学习笔记:光照

Shader以及背后的图形学我一直很感兴趣(比C#要感兴趣),而且《Shader 入门精要》也是我最喜欢的书之一。这篇文章开始写一写Shader,当然并不是作为一个教学的博客,而是当做学习的沉淀(所以不会写Shader语法基础),先从最基础的开始,光照。 我们在这篇文章中讲标准光照模型,一般来说标准光照模型中,射入摄像机的光线有以下四个部分: 自发光Emissive:描述当给定一个方向时,一个...

MEIGAZAMU 1695

C++五子棋人机对战

使用C++,开发五子棋人机对战,快速提升C++项目开发能力。

程序员Rock的博客 5万+

【Unity Shader入门】Shader基础光照:光照模型

光照介绍 BRDF 标准光照模型 自发光 漫反射 Lambert光照模型 Half Lambert光照模型 高光反射 Phong光照模型 Blinn-Phong光照模型 环境光 光照模型实现 漫反射 Lambert光照模型 逐顶点光照 逐像素光照 Half Lambert光照模型 高光反射 Phong光照模型 逐顶点光照 逐像素光照

承续缘 3067

态路小课堂丨三款800G光模块方案介绍—SR8/DR8/2FR4

800G QSFP-DD 2FR4光模块使用CWDM4波长(1271/1291/1311/1331nm),单通道速率为100G,通过MUX减小光纤的数目,其光学接口采用CS接口或双芯LC接口。

poposu的博客 2386

AI上推荐 之 NeuralCF与PNN模型(改变特征交叉方式)

1. 前言 随着信息技术和互联网的发展, 我们已经步入了一个信息过载的时代,这个时代,无论是信息消费者还是信息生产者都遇到了很大的挑战: 信息消费者:如何从大量的信息中找到自己感兴趣的信息? 信息生产者:如何让自己生产的信息脱颖而出, 受到广大用户的关注? 为了解决这个矛盾, 推荐系统应时而生, 并飞速前进,在用户和信息之间架起了一道桥梁,一方面帮助用户发现对自己有价值的信息, 一方面让信息能够展现在对它感兴趣的用户前面。 推荐系统近几年有了深度学习的助推发展之势迅猛, 从前深度学习的传统推荐模型(协

Miracle8070 1万+

《Unity Shader入门精要》学习笔记第6章 Unity中的基础光照

本文章用于帮助自己学习,因此只记录一些个人认为比较重要或者还不够熟悉的内容。 原作者:http://blog.youkuaiyun.com/candycat1992/article/ 第六章 Unity中的基础光照 6.1我们是如何看到这个世界的 6.1.1光源 在实时渲染中,我们通常把光源当成一 个没有体积的点,用l来表示它的方向。 在光学里,我们使用辐照度(irradiance)来量化光。对于平行光来说, 它的辐照度可通过计算在垂直于I的单位面积上单位时间内穿过的能量来得到。 物体表面和l不垂直的情况,我们可以使用

weixin_46124783的博客 2524

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Shader中的光照模型

本文详细介绍了计算机图形学中几种经典的光照模型及其实现方法。首先讲解了Lambert光照模型,它是基于理想漫反射的简单模型,通过法线与光线方向的点积计算光照强度。接着介绍了改进的Half-Lambert模型,解决了背光面过暗的问题。然后重点阐述了Phong光照模型,包含环境光、漫反射和镜面反射三部分,并对比了逐顶点光照和逐像素光照的区别。文章还介绍了Blinn-Phong模型,使用半角向量优化镜面反射计算。最后详细分析了Unity中的两种渲染路径:前向渲染和延迟渲染,包括它们的工作原理、性能特点和应用场景,

m0_63330263的博客 502

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

全局光照的实现Shader

如何创建自己的cginc文件?首先创建一个文件夹(Folder),用来存放自定义的cginc文件,然后再创建一个Shader然后右击Shader,选择在文件夹中打开Shader文件最后将文件重命名为.cginc后缀的文件即可如何引用自定义的cginc文件?自定义的cginc文件代码//将UnityGI的相关方法都添加到自定义的cginc文件中,并将unity中内置的函数名更改一下,以便区分// 计算Lambert光照模型的式子//SurfaceOutput表面的输出数据#endif。

2401_83878847的博客 1486

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Shader学习笔记(五)Unity中的基础光照

Hello World?????一、我们是如何看到这个世界的1.光源2.吸收和散射3.着色(shading)4.BRDF光照模型二、标准光照模型(1).自发光(emissive):Cmissive(2).高光反射(specular):Cspecular(3).漫反射(fiffuse):Cdiffuse(4).环境光(ambient):Cambient1.环境光2.自发光3.漫反射4.高光反射5.逐...

lyot的书桌 866
上一篇: Shader学习笔记(二):Vertex/Fragment Shader
下一篇: 《Unity游戏设计与实现》读书笔记
长三月
博客等级 码龄9年 228粉丝 80原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值