网站地图 html,电子商务公司设计网站建设,网站全站模板,网络营销网站推广方案文章目录 一、自定义烘培光照1. 烘培光照贴图2. 获取光照贴图3. 获取物体在光照贴图上的UV坐标4. 采样光照贴图 二、自定义光照探针三、 Light Probe Proxy Volumes#xff08;LPPV#xff09;四、Meta Pass五、 自发光烘培 一、自定义烘培光照
细节内容详见catlikecoding.c… 文章目录 一、自定义烘培光照1. 烘培光照贴图2. 获取光照贴图3. 获取物体在光照贴图上的UV坐标4. 采样光照贴图 二、自定义光照探针三、 Light Probe Proxy VolumesLPPV四、Meta Pass五、 自发光烘培 一、自定义烘培光照
细节内容详见catlikecoding.com 这里只做效果展示
1. 烘培光照贴图
在Lighting中设置LightingSettingsAsset并且将需要烘培的物体设置为ContributeGI将光照设置为Mixed或Baked最后点击GenerateLighting烘培得到光照贴图
2. 获取光照贴图
通过定义unity_Lightmap纹理即可获取光照贴图整个场景的光照贴图全部集成在一张贴图中。
TEXTURE2D(unity_Lightmap);
SAMPLER(samplerunity_Lightmap);因为整个场景的光照贴图都在一张贴图上所以物体的UV坐标也不再是原本的UV坐标
3. 获取物体在光照贴图上的UV坐标
首先需要Unity将每个烘培了光照的物体的光照贴图UV发送到GPU。 我们在CameraRenderer中设置drawingSettings 中的perObjectData 为PerObjectData.Lightmaps
var drawingSettings new DrawingSettings(unlitShaderTagID, sortingSettings)//使用哪个ShaderTagID以什么一定顺序渲染的设定
{//动态合批enableDynamicBatching useDynamicBatching,//实例化enableInstancing useGPUInstancing,//光照贴图UV坐标perObjectData PerObjectData.Lightmaps,
};当开启 Lighting 窗口下的Baked Global Illumination按钮时Unity会对打开Comtribute Global Illumination的物体写入宏_LIGHTMAP_ON 因此需要在需要光照烘培的Shader中定义
#pragma multi_compile _ LIGHTMAP_ONUnity会将UV坐标作为顶点数据发送到顶点着色器 顶点着色器中作为TEXCOORD1第二个纹理通道进行输入
以下定义宏来避免未开启光照烘培时的UV计算和输入
#if defined(LIGHTMAP_ON)#define GI_ATTRIBUTE_DATA float2 lightMapUV : TEXCOORD1;#define GI_VARYINGS_DATA float2 lightMapUV : VAR_LIGHT_MAP_UV;#define TRANSFER_GI_DATA(input, output) output.lightMapUV input.lightMapUV;#define GI_FRAGMENT_DATA(input) input.lightMapUV
#else#define GI_ATTRIBUTE_DATA #define GI_VARYINGS_DATA #define TRANSFER_GI_DATA(input, output) #define GI_FRAGMENT_DATA(input) 0.0
#endif并在着色器输入输出中添加GI_ATTRIBUTE_DATA、GI_VARYINGS_DATA
struct Attributes
{float3 positionOS : POSITION;float2 baseUV : TEXCOORD0;float3 normalOS : NORMAL;GI_ATTRIBUTE_DATAUNITY_VERTEX_INPUT_INSTANCE_ID
};struct Varyings{float4 positionCS : SV_POSITION;float2 baseUV : VAR_BASE_UV;float3 normalWS : VAR_NORMAL;float3 positionWS : VAR_POSITION;GI_VARYINGS_DATAUNITY_VERTEX_INPUT_INSTANCE_ID
};将UV坐标传入片元着色器
Varyings LitPassVertex(Attributes input)
{Varyings output;....// 全局光照TRANSFER_GI_DATA(input, output);return output;
}在片元着色器中获取UV坐标
// 全局光照
#if defined(LIGHTMAP_ON)float2 LightMapUV GI_FRAGMENT_DATA(input);
#endif然而这获取的UV并不是该物体在LightMap上的UV而是LightMap局部空间上的UV。 每个物体均匀且不重叠的按照缩放和偏移放置在这张LightMap中所以每一个物体都有一个对应的UV缩放和偏移数据。 我们通过在Shader的Input文件中添加unity_LightmapST得到该数据该数据由Unity直接提供。
CBUFFER_START(UnityPerDraw)...float4 unity_LightmapST;
CBUFFER_END教程中引入了动态光照贴图UV float4 unity_DynamicLightmaoST; 防止因为兼容性导致的SRP批处理中断 这里我们不引入 unity_DynamicLightmaoST 4. 采样光照贴图
光照贴图的采样函数由render-pipelines.core提供因为Unity有可能对LightMap进行了压缩所以使用内置函数可以帮我们解决这个问题。
其中是否压缩LightMap在Light窗口下的Lightmap Compression来设置 设置压缩会在Shader中输入关键字 UNITY_LIGHTMAP_FULL_HDR。
#include Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl里面有关于
球谐采样光照探针采样遮蔽探针采样解码/编码LightMap解码/编码HDR环境贴图采样光照贴图的函数
的函数
其中使用SampleSingleLightmap对单一LightMap进行采样
real3 SampleSingleLightmap(TEXTURE2D_LIGHTMAP_PARAM(lightmapTex, lightmapSampler), LIGHTMAP_EXTRA_ARGS, float4 transform, bool encodedLightmap, real4 decodeInstructions)
{// transform is scale and biasuv uv * transform.xy transform.zw;real3 illuminance real3(0.0, 0.0, 0.0);// Remark: baked lightmap is RGBM for now, dynamic lightmap is RGB9E5if (encodedLightmap){real4 encodedIlluminance SAMPLE_TEXTURE2D_LIGHTMAP(lightmapTex, lightmapSampler, LIGHTMAP_EXTRA_ARGS_USE).rgba;illuminance DecodeLightmap(encodedIlluminance, decodeInstructions);}else{illuminance SAMPLE_TEXTURE2D_LIGHTMAP(lightmapTex, lightmapSampler, LIGHTMAP_EXTRA_ARGS_USE).rgb;}return illuminance;
}我们使用该函数对LightMap进行采样并根据是否开启LIGHTMAP_ON决定是否调用函数。
float3 SampleLightMap(float2 lightMapUV)
{
#if defined(LIGHTMAP_ON)return SampleSingleLightmap(TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap), lightMapUV, unity_LightmapST, #if defined(UNITY_LIGHTMAP_FULL_HDR)false,#elsetrue,#endiffloat4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0, 0.0));
#elsereturn 0.0;
#endif
}返回数据
struct GI{float3 diffuse;
};GI GetGI(float2 lightMapUV){GI gi;gi.diffuse SampleLightMap(lightMapUV);return gi;
}在FragmentShader中调用函数获取LightMap采样的数据。
// 全局光照float2 LightMapUV GI_FRAGMENT_DATA(input);GI gi GetGI(LightMapUV);计算光照 float3 color GetLighting(surface, brdf, gi);将全局光照作为基础色
float3 GetLighting(Surface surfaceWS, BRDF brdf, GI gi)
{// 得到表面级联阴影数据CascadeShadowData cascadeShadowData GetCascadeShadowData(surfaceWS);// 将全局光照作为基础色float3 color gi.diffuse;// 对可见光照结果进行累加for(int i 0; i GetDirectionalLightCount();i){Light light GetDirectionalLight(i, surfaceWS, cascadeShadowData);color GetLighting(surfaceWS, brdf, light);}return color;
}烘培光照 烘培光照直接光照 注意这里烘培光照只计算间接光照不计算直接光照
但为什么是白色呢不应该有绿色映射吗
将代码中计算GI的光照修改为
float3 color gi.diffuse * brdf.diffuse;变为 间接光照烘培 烘培光照烘培直接光照 效果好了但是仍然没有得到正确的间接光照
所以光照贴图保存的到底是什么 似乎只是一个强度但没有颜色 我们将直接光照颜色设为红色再次查看间接光照数据。 可以看到间接光照变成了红色也就是说光照烘培得到的数据并不是实际光照经过物体表面反射得到的间接光照而是光照在弹射过程中按照一定比例衰减的结果。
因此GI最终结果与BRDF相乘得到的才是间接光照的结果没有反射物体颜色的映射
如果要获取间接光照见 4.Meta Pass
二、自定义光照探针
使用光照探针前 使用光照探针后
三、 Light Probe Proxy VolumesLPPV
四、Meta Pass
因为间接漫射光从表面反射它应该受到这些表面漫反射的影响。这种情况目前还没有发生。Unity将我们的表面视为均匀的白色。Unity使用一个特殊的Meta通道来确定烘焙时的反射光。因为我们还没有定义这样的通道Unity使用默认的通道它最终是白色的。
增加Meta文件前 增加Meta文件后 间接光照效果 加上动态物体光照探针效果
五、 自发光烘培