文章目录
- 前言
- 一、在上一篇文章中,得到GI相关数据后,需要对其进行Lambert光照模型计算
- 二、在准备好上面步骤后,我们需要准备缺少的数据
- 1、准备上图中的 s.Normal
- 2、准备上图中的 s.Albedo
前言
Unity中Shader的GI的直接光实现,基于上一篇准备好的数据的基础上,继续实现GI的直接光效果
- Unity中Shader的烘培分支的判断
一、在上一篇文章中,得到GI相关数据后,需要对其进行Lambert光照模型计算
这是上一篇文章中得到 GI 数据的方法
LightingLambert_GI1(o,giInput,gi);
得到了之后,我们直接使用Unity自带的计算 Lambert 模型的函数计算即可,当然也可自己按照之前的文章实现 Lambert 光照模型
- Unity中Shader的Lambert光照的实现
这是在 Lighting.cginc 中Unity实现Lambert光照的方法
我们把它移植到我们自己的 cginc 中,方便管理修改(记着修改一下函数名,防止函数名冲突)
二、在准备好上面步骤后,我们需要准备缺少的数据
1、准备上图中的 s.Normal
这在之前的文章中,已经定义过很多次了,具体步骤如下
1.在appdata中,接受 half3 normal : NORMAL;
half3 normal : NORMAL;
2.在 v2f 中定义一个 half3 worldNormal :TEXCOORD;用于存放顶点法线数据
half3 worldNormal : TEXCOORD2;
3.在顶点着色器中,把 appdata 传入的数据转化到世界坐标下,存入 v2f 的worldNormal中
o.worldNormal = UnityObjectToWorldNormal(v.normal);
4.在片元着色器中,把 worldNormal 赋值给 SurfaceOutput 变量的 Normal
//1、准备 SurfaceOutput 的数据
SurfaceOutput o;
//目前先初始化为0,使用Unity自带的方法,把结构体中的内容初始化为0
UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o)
o.Normal = i.worldNormal;
然后,我们在UnityLambertLight1中,返回一下diff,看看结果
在片元着色器,返回计算结果
fixed4 c = LightingLambert1(o,gi);
return c;
这是烘培前的效果:
这是烘培后的效果:(我们可以看见已经有基本的光照效果了)
2、准备上图中的 s.Albedo
这个 Albedo 一般是用模型的贴图主纹理采样得到的,在这里我们没有使用,则一般给他赋值为1(不能为0,不然会导致输出的结果为黑色)
以下是修改后的完整代码:
//在这里里面使用 自定义的 cginc 来实现全局GI
//GI数据的准备
//烘培分支的判断
//GI的直接光实现
//GI的间接光实现
Shader "MyShader/P1_8_6"
{
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
Tags{"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile DYNAMICLIGHTMAP_ON
#pragma multi_compile LIGHTMAP_ON
#include "UnityCG.cginc"
#include "AutoLight.cginc"
#include "Lighting.cginc"
#include "CGIncludes/MyGlobalIllumination.cginc"
struct appdata
{
float4 vertex : POSITION;
//定义第二套 UV ,appdata 对应的固定语义为 TEXCOORD1
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
float4 lightmapUV : TEXCOORD1;
#endif
half3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 worldPos : TEXCOORD0;
//定义第二套UV
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
float4 lightmapUV : TEXCOORD1;
#endif
half3 worldNormal : TEXCOORD2;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld,v.vertex);
//对第二套UV进行纹理采样
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
o.lightmapUV.xy = v.lightmapUV * unity_LightmapST.xy + unity_LightmapST.zw;
#endif
o.worldNormal = UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//1、准备 SurfaceOutput 的数据
SurfaceOutput o;
//目前先初始化为0,使用Unity自带的方法,把结构体中的内容初始化为0
UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o)
o.Albedo = 1;
o.Normal = i.worldNormal;
//2、准备 UnityGIInput 的数据
UnityGIInput giInput;
//初始化
UNITY_INITIALIZE_OUTPUT(UnityGIInput,giInput);
//修改用到的数据
giInput.light.color = _LightColor0;
giInput.light.dir = _WorldSpaceLightPos0;
giInput.worldPos = i.worldPos;
giInput.worldViewDir = normalize(_WorldSpaceCameraPos - i.worldPos);
giInput.atten = 1;
giInput.ambient = 0;
#if defined(DYNAMICLIGHTMAP_ON) || defined(LIGHTMAP_ON)
giInput.lightmapUV = i.lightmapUV;
#endif
//3、准备 UnityGI 的数据
UnityGI gi;
//直接光照数据(主平行光)
gi.light.color = _LightColor0;
gi.light.dir = _WorldSpaceLightPos0;
//间接光照数据(目前先给0)
gi.indirect.diffuse = 0;
gi.indirect.specular = 0;
LightingLambert_GI1(o,giInput,gi);
//我们在得到GI的数据后,对其进行Lambert光照模型计算,即可得到结果
fixed4 c = LightingLambert1(o,gi);
return c;
//return fixed4(gi.indirect.diffuse,1);
//return 1;
}
ENDCG
}
}
}
这是修改后的效果: