IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity前向渲染路径总结 -> 正文阅读

[游戏开发]Unity前向渲染路径总结

????????勿于浮沙筑高台。回顾总结一下Unity前向渲染路径。

一、前置知识:光照的基本框架

????????光照主要分为:直接光照、间接光照、(环境光是间接光的一部分)。

????????这其中直接光照占主导地位。而为了减少间接光照的计算,有很多种技术来表达间接光照。

比如:LightMap,Reflection probe(反射球,IBL基于图像的照明),Light Probe(球谐光照SH)

????????目前的光照计算中最完整的是BRDF(Bidirectional Reflectance Distribution Function)光照模型。但是这个模型较为复杂,所以有一些简化后的光照模型。比如:标准光照模型

二、标准光照模型(Phong光照模型)

????????只关心直接光照。把进入摄像机的光线分为4个部分:

????????i.自发光emissive

????????ii.漫反射diffuse。

????????????????Lambert定律, half Lambert定律。

????????以Lambert为例,就是求光照方向与法线夹角的cos值,注意这里的光照方向是从顶点指向光源,这里只是约定俗称的。

???????

????????iii.高光反射specular

?????????????? ??????? Phong光照模型和Blinn-Phong光照模型。

????????以Phone光照为例,这里是求反射光与视线的夹角的cos值。smoothness值来控制光线的衰减,也就是光斑的大小。

????????iv.环境光ambient(表示所有的间接光照)。

??????? 具体实现在实现前向渲染的光照shader中实现。

三、前向渲染路径

?????? 渲染路径是决定灯光数据传递方式的。

??????? 1.实时光的处理

????????对于前向渲染,在场景里有多少盏实时灯光。物体就会被渲染多少次。而在含光照的shader中,分为两个Pass。

????????一个Pass为ForwardBase。这个Pass主要渲染主1盏平行光(逐像素)(以及小于等于4盏的顶点光,和SH球谐光。)

??????? 另一个Pass为ForwardAdd,这个Pass里面会渲染其他逐像素光源(逐像素)。多少盏由下面这个设置决定。

??????? 其他光源的处理方式:1.ForwardBase的顶点光。2.SH球谐光照

????? 光源重要等级排序:forwardBase像素光源 > forwardAdd像素光源 > forwardBase顶点光源 > SH球谐光源

?? 2.怎么区分不同的光源

?

??????????????? 1.RenderMode的设置。Not Important 的光源为顶点光或 SH 光源。Important 的光源为每像素光源。

??????????????? 2.按照光的强度排序。

如果像素光源少于设置,还有其他光源的话,其他光源可以依次升级。同理,像素光源多了就会依次降级。

?

四、实现简单的光照Shader

??????? 使用phong光照模型和Lambert光照模型。

Shader "Awen_Unlit/LambertPhoneSimple"
{
    Properties
    {
		//最原始的数值上的光照模型
		_Shininess("Shininess",Range(0.01,100)) = 1.0
		_AmbientColor("Ambient Color",COLOR) = (0.0,0.0,0.0,0.0)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
			Tags{ "LightMode" = "ForwardBase"}

			CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
			#pragma multi_compile_fwdbase

            #include "UnityCG.cginc"
			#include "AutoLight.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
				float3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 pos : SV_POSITION;
				float3 normal_dir : TEXCOORD1;
				float3 pos_world : TEXCOORD2;
            };

			float4 _LightColor0;//定义了才能拿到光照颜色
			float _Shininess;//光照衰减
			float4 _AmbientColor;//环境光单纯使用的纯色

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;

				o.normal_dir = normalize(mul(float4(v.normal,0.0),unity_WorldToObject).xyz);
				o.pos_world = mul(unity_ObjectToWorld,v.vertex).xyz;

				//o.tangent_dir = normalize(mul(float4(v.tangent,0.0),))


                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
				half3 normal_dir = normalize(i.normal_dir);
				//观察方向
				half3 view_dir = normalize(_WorldSpaceCameraPos - i.pos_world);
                //平行光的灯光方向
				half3 light_dir = normalize(_WorldSpaceLightPos0.xyz);
				
				//Lambert漫反射
				half NdotL = dot(normal_dir,light_dir);
				//获取灯光颜色,需要定义_LightColor0变量
				half3 diffuse_color = max(0.0,NdotL) * _LightColor0.xyz;

				//Phone高光
				//注意这里的光照方向要加负号,因为灯光方向求的是顶点指向灯光
				half3 reflect_dir =  reflect(-light_dir,normal_dir);
				half RdotV = dot(reflect_dir,view_dir);
				half3 spec_color =  pow(max(0.0,RdotV),_Shininess) * _LightColor0.xyz;

				half3 final_color = diffuse_color + spec_color + _AmbientColor.xyz;
				// sample the texture
               // fixed4 col = tex2D(_MainTex, i.uv);
              
                return float4(final_color,1.0);
            }
            ENDCG
        }
		Pass
        {
			Tags{ "LightMode" = "ForwardAdd"}
			Blend One One
			CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
			#pragma multi_compile_fwdadd

            #include "UnityCG.cginc"
			#include "AutoLight.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
				float3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 pos : SV_POSITION;
				float3 normal_dir : TEXCOORD1;
				float3 pos_world : TEXCOORD2;
            };

			float4 _LightColor0;//定义了才能拿到光照颜色
			float _Shininess;//光照衰减
			float4 _AmbientColor;//环境光单纯使用的纯色

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;

				o.normal_dir = normalize(mul(float4(v.normal,0.0),unity_WorldToObject).xyz);
				o.pos_world = mul(unity_ObjectToWorld,v.vertex).xyz;

				//o.tangent_dir = normalize(mul(float4(v.tangent,0.0),))


                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
				half3 normal_dir = normalize(i.normal_dir);
				//观察方向
				half3 view_dir = normalize(_WorldSpaceCameraPos - i.pos_world);

				#if defined (DIRECTIONAL)
				half3 light_dir = normalize(_WorldSpaceLightPos0.xyz);//平行光
				half attenuation = 1.0;
				#elif defined (POINT)
				half3 light_dir = normalize(_WorldSpaceLightPos0.xyz - i.pos_world);
				half distance = length(_WorldSpaceLightPos0.xyz - i.pos_world);
				half range = 1.0 / unity_WorldToLight[0][0];
				//最原始简单的点光源计算衰减值的做法,现在Unity是使用渐变图来计算的衰减
				half attenuation = saturate((range - distance)/ range);
				#endif
				//Lambert漫反射
				half NdotL = dot(normal_dir,light_dir);
				//获取灯光颜色,需要定义_LightColor0变量
				half3 diffuse_color = max(0.0,NdotL) * _LightColor0.xyz * attenuation;

				//Phone高光
				//注意这里的光照方向要加负号,因为灯光方向求的是顶点指向灯光
				half3 reflect_dir =  reflect(-light_dir,normal_dir);
				half RdotV = dot(reflect_dir,view_dir);
				half3 spec_color =  pow(max(0.0,RdotV),_Shininess) * _LightColor0.xyz * attenuation;

				half3 final_color = diffuse_color + spec_color + _AmbientColor.xyz;       
                return float4(final_color,1.0);
            }
            ENDCG
        }
	}
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-12 17:53:59  更:2022-03-12 17:56:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/13 3:01:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码