Unity Shader 入门笔记(四)

这篇具有很好参考价值的文章主要介绍了Unity Shader 入门笔记(四)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

一、光照模型

1. 简介

2. 发展历程

3. 局部光照模型和全局光照模型

3.1. 局部光照模型

3.2. 全局光照模型

二、Unity Shader实现标准光照模型

1. 逐顶点的光照模型

1.1. 实现效果如下:

1.2. 实现代码参考:

2. 逐像素的光照

2.1. 实现效果:

2.2. 实现代码参考:

三、参考链接 

四、总结


Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

前言

在 Unity Shader 入门笔记(二)和 Unity Shader 入门笔记(三)中学习了Shader程序的基础用法,现在是时候写一个标准光照模型,作为实践Unity Shader的起点,不过在写光照模型Shader之前让我们先来了解什么是光照模型。

一、光照模型

1. 简介

当光照射到物体表面时,物体对光会发生反射、透射、吸收、衍射、折射、和干涉,其中被物体吸收的部分转化为热、反射、透射的光进入人的视觉系统,使我们能看见物体。为模拟这一现象,我们建立一些数学模型来替代复杂的物理模型,这些模型就称为明暗效应模型或者光照明模型

2. 发展历程

1967年Wylie等人第一次在显示物体时加进光照效果。Wylie认为,物体表面上一点的光强,与该点到光源的距离成反比。
1970年Bouknight提出第一个光反射模型,指出物体表面朝向是确定物体表面上一点光强的主要因素,用Lambert漫反射定律计算物体表面上各多边形的光强,对光照射不到的地方,用环境光代替。
1971年Gourand提出的基于“漫反射模型与插值”思想的Gourand模型。对多面体模型,用漫反射模型计算多边形顶点的光亮度,再用增量法插值计算。
1975年Bui Tuong Phong(裴祥风)提出图形学中第一个有影响的简单光照明模型。模型虽然只是一个经验模型,但是其真实度已达到可以接受的程度。在Phong光照模型的基础之上,相继出现了Goud明暗处理和Phong明暗处理两个增量式光照模型。
1980年,Whitted提出了一个光透射模型:Whitted模型并第一次给出光线跟踪算法的范例,实现了模型它综合考虑了光的反射、折射透射、阴影等。从本质上来说,whitted模型也只是一种经验模型,它仅考虑特定方向上的环境入射光对被照射点的光亮度共线,因而它仅能模拟理想的镜面反射和规则的投射效果。
1982年,Cook和Torrance为了克服Phong模型的缺点,提出了一个基于物理光学的表面反射模型—Cook-Torrance模型“使得模型中反射光的位置和分布与实际情况非常接近,因而用它绘制的图形具有很好的质感。
1983年,Hall和Greenbert在Whitted基础上此进一步给出Hall光透射模型,考虑了漫透射和规则透射光。改进了whitted中投射高光效果,并再环境光中加入距离衰减因子,使之能够更好的模拟物体表面的透射特性。
1986年,Kajiya统一了以前所有的光照模型,Kajiya首先提出使类似于随机采样的蒙特卡罗(Monte Carlo)方法求解绘制方程的光线追踪算法(Raytracing), 通过对到达图像平面上的光线路径进行采样,然后估计它们对最终图像的贡献来生成图像。

3. 局部光照模型和全局光照模型
3.1. 局部光照模型

局部光照模型(Local llumination Model)是场景中的光源直接照射到物体表面时,计算产生的反射或折射光的数学模型。

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

早期游戏引擎中往往只使用一个光照模型,这个光照模型被称为标准光照模型。标准光照模型只关心直接光照,也就是那些直接从光源发射出来照射到物体表面后经过物体表面一次反射直接进入摄像机的光线,基本方法是把进入到摄像机的光线分为4个部分,每个部分使用一种方法计算它的贡献度,如下:

  • 自发光(Emissive):描述当给定一个方向时,一个表面本身会向该方向发射多少辐射量。

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

  • 环境光(Ambient):描述标准模型中使用环境光来近似模拟间接光照。

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

  • 高光反射(Specular):描述当光线从光源照射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量。

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

注意:在硬件实现时,如果摄像机和光源距离模型足够近,Blinn模型会快于Phong模型,此时可以认为视角方向和光照方向是一个定值,所以半程向量是一个常量,反之,如果不是定值,Phong模型反而更快。

  • 漫反射(Diffuse):描述当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量。

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

从图片可以看出,漫反射光照符合兰伯特定律漫反射光线的强度与表面法线和光源方向之间的夹角的余弦成正比。那么在法线和光照方向均为单位向量的情况下漫反射部分计算如下:

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

3.2. 全局光照模型

全局光照(Global Illumination)简称 GI,或被称为Indirect Illumination;间接光照,是指既考虑场景中直接来自光源的光照(Direct Light)又考虑经过场景中其他物体反射后的光照(Indirect Light)的一种渲染技术。使用全局光照能够有效地增强场景的真实感。

即可以理解为:全局光照 = 直接光照(Direct Light) + 间接光照(Indirect Light)

全局光照涉及的知识非常多,本文主要记录标准光照模型,所以暂不展开深入学习,现阶段仅做了解。

二、Unity Shader实现标准光照模型

结合上文可知,标准光照模型 = 环境光 + 高光反射 + 漫反射,下文的Shader程序也是如此实现,主要实现了逐顶点的光照和逐像素光照。

1. 逐顶点的光照模型
1.1. 实现效果如下:

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

1.2. 实现代码参考:
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "My Shader/PhongLightModelVertex"
{
    Properties
    {
        _Diffuse("Diffuse", Color) = (1.0, 1.0, 1.0, 1.0)
        _Specular("Specular", Color) = (1.0, 1.0, 1.0, 1.0)
        _Gloss("Gloss", Range(8.0, 256)) = 20
    }
    
    SubShader
    {
        Pass
        {
            Tags { "LightMode" = "ForwardBase" }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "UnityLightingCommon.cginc"
            
            fixed4 _Diffuse;   //声明材质漫反射颜色
            fixed4 _Specular;  //声明材质高光反射颜色
            float _Gloss;      //声明材质高光反射范围

            struct appdata
            {
                float4 vertex : POSITION;  //获取到模型顶点信息
                float3 normal :NORMAL;     //获取到模型顶点法线信息,用于计算漫反射
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                fixed3 color : COLOR;
            };


            v2f vert (appdata v)
            {
                v2f o;
                //计算模型顶点在裁剪空间上的位置
                o.pos = UnityObjectToClipPos(v.vertex);

                //获得环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;

                //计算漫反射
                fixed3 worldNormal = normalize(UnityObjectToWorldNormal(v.normal)); //将模型空间法线转换到世界空间中
                fixed3 worldLight  = normalize(_WorldSpaceLightPos0.xyz); //获取光照方向
                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));

                //计算高光反射
                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex).xyz);

                //实现思路一:基于Phong模型的计算方式
                // fixed3 reflectDir = normalize(reflect(-worldLight, worldNormal)); //反射公式
                // fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
                
                //实现思路二:基于BilinPhong模型的计算方式
                fixed3 halfDir = normalize(worldLight + viewDir);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss);

                //光照模型
                o.color = ambient + diffuse + specular;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(i.color, 1.0);
            }
            ENDCG
        }
    }
}
2. 逐像素的光照
2.1. 实现效果:

Unity Shader 入门笔记(四),图形学,unity,笔记,游戏引擎

2.2. 实现代码参考:
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "My Shader/PhongLightModelFragment"
{
    Properties
    {
        _Diffuse("Diffuse", Color) = (1.0, 1.0, 1.0, 1.0)
        _Specular("Specular", Color) = (1.0, 1.0, 1.0, 1.0)
        _Gloss("Gloss", Range(8.0, 256)) = 20
    }
    
    SubShader
    {
        Pass
        {
            Tags { "LightMode" = "ForwardBase" }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "UnityLightingCommon.cginc"

            
            fixed4 _Diffuse;   //声明材质漫反射颜色
            fixed4 _Specular;  //声明材质高光反射颜色
            float _Gloss;      //声明材质高光反射范围

            struct appdata
            {
                float4 vertex : POSITION;   //获取到模型顶点信息
                float3 normal : NORMAL;     //获取到模型顶点法线信息,用于计算漫反射
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0; //模型世界空间下的模型法线
                float3 worldPos : TEXCOORD1;    //模型世界空间下的模型顶点
            };


            v2f vert (appdata v)
            {
                v2f o;
                //计算模型顶点在裁剪空间上的位置
                o.pos = UnityObjectToClipPos(v.vertex);
                //模型空间法线转换到世界空间中
                o.worldNormal = normalize(UnityObjectToWorldNormal(v.normal));
                //模型空间坐标点转换到世界空间中
                o.worldPos = UnityObjectToWorldDir(v.vertex).xyz;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //获得环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;

                //计算漫反射
                fixed3 worldLight  = normalize(_WorldSpaceLightPos0.xyz); //获取光照方向
                //半兰伯特公式
                fixed3 halfLambert = dot(i.worldNormal, worldLight) * 0.5 + 0.5;
                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambert;

                //计算高光反射
                fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
                fixed3 halfDir = normalize(worldLight + viewDir);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(i.worldNormal, halfDir)), _Gloss);

                fixed3 color = ambient + diffuse + specular;
                return fixed4(color, 1.0);
            }

            ENDCG
        }
    }
}

三、参考链接 

什么是光照模型 - 知乎每个像素都是颜色值,但是要获得这个颜色值,你要观察这个像素所处的整个环境。一.综述本篇文章主要概述真实感渲染中光照模型的主要理论和技术手段,细节步骤等重要问题将再以后阐述。 真实感渲染和非真实感的区…https://zhuanlan.zhihu.com/p/49474631

【《Real-Time Rendering 3rd》 提炼总结】(八) 第九章 · 全局光照:光线追踪、路径追踪与GI技术进化编年史 - 知乎全局光照(Global Illumination,简称 GI), 作为图形学中比较酷的概念之一,是指既考虑场景中来自光源的直接光照,又考虑经过场景中其他物体反射后的间接光照的一种渲染技术。 大家常听到的光线追踪,路径追踪等…https://zhuanlan.zhihu.com/p/29418992

2.4传统经验光照模型详解 - 知乎一、光照模型光照模型(illumination model),也称为明暗模型,用于计算物体某点处的光强(颜色值)。从算法理论基础而言,光照模型分为两类:一种是基于物理理论的,另一种是基于经验模型的。 基于物理理论的光照模…https://zhuanlan.zhihu.com/p/470561372

四、总结

本文主要学习了标准光照模型的数学模型和shader实现,后面的大多数代码实现都是依赖此光照模型实现的,值得注意的是我们在实现时需要将法线、光照、视角方向都转为单位向量,并都处于同一坐标空间下才能得到正确结果。现在已经有基础的光照模型了,下一篇文章将会学习纹理的相关概念,并为模型实现更多的细节和效果。

关于光照相关知识补充,可以看参考链接,如果你也有较好的资料分享,欢迎在评论区留言。最后,非常感谢您能看到这里,如果该文章对你有所帮助和启发,也欢迎您能点赞👍支持,如果有任何疑问和优化建议也非常欢迎各位大佬能够在评论区友好交流,一起学习进步。文章来源地址https://www.toymoban.com/news/detail-826628.html

到了这里,关于Unity Shader 入门笔记(四)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 十八、Unity游戏引擎入门

    1、下载     首先需要下载Unity Hub,下载网址:https://unity.com/cn。     然后在其中下载Unity编辑器并安装,可选择最新版本。     接着需要选择适合的开发环境,例如Android Studio或Xcode,以便进行手机游戏开发。在安装完Unity后,需要根据项目需求下载对应的模块和插件,例

    2024年02月16日
    浏览(73)
  • 【UnityShader入门精要学习笔记】第三章(1)Unity Shader介绍

    本系列为作者学习UnityShader入门精要而作的笔记,内容将包括: 书本中句子照抄 + 个人批注 项目源码 一堆新手会犯的错误 潜在的太监断更,有始无终 总之适用于同样开始学习Shader的同学们进行有取舍的参考。 从本章节开始我们要学习Shader相关的知识了,诸位看客可能有的

    2024年02月02日
    浏览(66)
  • 【UnityShader入门精要学习笔记】第三章(2)Unity Shader的形式,章节答疑

    本系列为作者学习UnityShader入门精要而作的笔记,内容将包括: 书本中句子照抄 + 个人批注 项目源码 一堆新手会犯的错误 潜在的太监断更,有始无终 总之适用于同样开始学习Shader的同学们进行有取舍的参考。 (该系列笔记中大多数都会复习前文的知识,特别是前文知识非

    2024年02月02日
    浏览(50)
  • Unity Physics2D 2d物理引擎游戏 笔记

    2d 材质 里面可以设置 摩擦力 和 弹力 Simulated:是否在当前的物理环境中模拟,取消勾选该框类似于Disable Rigidbody,但使用这个参数更加高效,因为Disable会销毁内部产生的GameObject,而取消勾选Simulated只是禁用。 Kinematic 动力学刚体 动力学刚体不受重力和力的影响,而受用户的

    2023年04月24日
    浏览(121)
  • (五·二)计算机图形学 之 Unity代码调用Shader并修改属性值

    直接划重点: 在C#代码中,要先引用材质球(Material),然后通过材质球提供的方法比如: 我这里使用material.SetColor(\\\"_Color\\\", Color.red); 结构是SetColor(shader属性名称,属性值设置); _Color是在shader中,Properties{}里定义好的属性,名称要一直,然后就是给他赋值。 Shader代码: C#代码

    2024年02月15日
    浏览(39)
  • Unity Shader入门精要 第六章——Unity中的基础光照

    目录 一、标准光照模型(Phong光照模型) 1、环境光  2、自发光 3、漫反射 4、高光反射 (1)Phong模型 (2)Blinn模型 5、光照模型实现方法——逐顶点和逐像素 二、Unity Shader 漫反射光照模型的实现 1、实践:逐顶点 2、实践:逐像素 3、半兰伯特模型 4、漫反射光照模型效果展

    2024年02月04日
    浏览(48)
  • Unity_Shader入门详解

    在Unity中创建Shader,有Stander Shader、Unlit Shader、Image Effect Shader、Compute Shader、Ray Tracing Shader Stander Shader :Unity内置的标准着色器,支持高光、透明度、法线贴图等特性,比如金属,塑料,木材,皮肤,也支持光照、阴影、反射、折射、透明雾化等... Unlit Shader :不受光照影响的着

    2024年02月10日
    浏览(38)
  • Unity Shader 入门(零基础到敢上手敲Shader)

    目录  创建Shader 一.Standard Surface Shader 二.Unlit Shader 三.Image Effect Shader 四.Compute Shader 五.Ray Tracing Shader 着色器语言 Shader默认代码格式和一些常用API讲解 标准表面着色器,它是一种基于物理的着色系统,可以理解为 它是通过对物理现象的简单模拟,可以实现生活中各种物品的效

    2024年02月04日
    浏览(40)
  • 2023-08-22 Unity Shader 开发入门2 —— Shader 开发介绍

    ​ 计算机图形程序接口(Graphics API)是一套可编程的开放标准,不论 2D 还是 3D 游戏都需要这部分的底层 API 支持。 ​ 它本质上是软件,并不是硬件,是前人提前写好的调用系统硬件(GPU)绘制图形的代码。可以简单理解成是显卡厂商定义的一系列的底层的进行图形操作的加

    2024年02月11日
    浏览(36)
  • Unity Shader入门精要学习——透明效果

    要么完全透明,要么完全不透明。 实现简单,实质上是一种剔除机制,通过将不满足条件(通常使用小于某个阈值来判定,一般使用clip方法)的片元舍弃的方法来达到完全透明效果。这些被舍弃的片元不会再进行任何的处理,也不会对颜色缓冲产生任何影响,其余满足条件

    2024年02月17日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包