UnityShader实例07:在shader调用unity内置lightmap和light Probes

2024-05-28 23:32

本文主要是介绍UnityShader实例07:在shader调用unity内置lightmap和light Probes,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在shader调用unity内置lightmap和Light Probes


在编写unity shader的时候,有时候会有需求,希望写的shader能支持unity内置lightmap或者light probe (灯光探测器)。如果是用surface 编写的话,这些自然不用考虑,unity会自动编译支持,但如果是用vert&frag编写shader,这些需要自己添加相关代码调用了 。


unity内置lightmap的调用


为了使unity内置数据和各种宏定义(如本文的LIGHTMAP_OFF)起作用,需要添加#pragma指令:

#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON


在unity5.0之前的版本需要声明一下两个内置参数,unity5.0的话就不需要这两句了:

half4 unity_LightmapST;
sampler2D unity_Lightmap;

Lightmap是使用模型的uv2 ,因此接下来在顶点输入结构体里声明uv2:


float2 texcoord1 : TEXCOORD1;

在另一个顶点结构里面定义用来接收uv2的uv值:

#ifndef LIGHTMAP_OFF
half2 uvLM : TEXCOORD4;
#endif

在vert函数里面给uvLM赋值:

#ifndef LIGHTMAP_OFF
o.uvLM = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
#endif

然后frag函数里对lightmap贴图采样并叠加给主颜色:

#ifndef LIGHTMAP_OFF
fixed3 lm = DecodeLightmap (UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uvLM.xy));
col.rgb*=lm;
#endif
在上面的代码中使用了DecodeLightmap解码unity的内置光照贴图,这是因为 Unity烘焙的LightMap是32bit的HDR图,在桌面端,光照贴图的编码为RGBM,而在移动端,大部分情况下,光照贴图的编码为double-LDR,因此需要针对不同平台提供不同的编码方式。DecodeLightmap作用就在这里,它可以针对不同的平台对光照贴图进行解码


VF版本代码01:

Shader "PengLu/Unlit/TextureLM" {
Properties {_MainTex ("Base (RGB)", 2D) = "white" {}
}SubShader {Tags { "RenderType"="Opaque" }LOD 100Pass {  CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fog#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON#include "UnityCG.cginc"struct appdata_t {float4 vertex : POSITION;float2 texcoord : TEXCOORD0;float2 texcoord1 : TEXCOORD1;};struct v2f {float4 vertex : SV_POSITION;half2 texcoord : TEXCOORD0;#ifndef LIGHTMAP_OFFhalf2 uvLM : TEXCOORD1;#endif UNITY_FOG_COORDS(1)};sampler2D _MainTex;float4 _MainTex_ST;v2f vert (appdata_t v){v2f o;o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);#ifndef LIGHTMAP_OFFo.uvLM = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;#endifUNITY_TRANSFER_FOG(o,o.vertex);return o;}fixed4 frag (v2f i) : SV_Target{fixed4 col = tex2D(_MainTex, i.texcoord);UNITY_APPLY_FOG(i.fogCoord, col);UNITY_OPAQUE_ALPHA(col.a);#ifndef LIGHTMAP_OFFfixed3 lm = DecodeLightmap (UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uvLM.xy));col.rgb*=lm;#endifreturn col;}ENDCG}
}}

VF版本代码01效果:



unity内置Light Probes的调用


在shader中我们是通过unity定义的half3 ShadeSH9(half4 normal)来调用Light Probes的,Light Probes照明使用的是一种叫球谐光照(Sphere Harmonic)的模拟,简称SH,因此在ShadeSH9函数需要一个世界坐标中的Normal来决定物体表面的光照。

首先我们在顶点输出结构定义一个参数SHLighting:

fixed3  SHLighting : COLOR;

然后在顶点函数里为它赋值:

 

float3 worldNormal = mul((float3x3)_Object2World, v.normal);//获得世界坐标中的normalo.SHLighting= ShadeSH9(float4(worldNormal,1)) ;

VF版本代码02:

Shader "PengLu/Unlit/TextureLM" {
Properties {_MainTex ("Base (RGB)", 2D) = "white" {}_SHLightingScale("LightProbe influence scale",float) = 1
}SubShader {Tags { "Queue"="Geometry""LightMode"="ForwardBase""RenderType"="Opaque"   }LOD 100Pass {  CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fog#include "UnityCG.cginc"struct v2f {float4 vertex : SV_POSITION;half2 texcoord : TEXCOORD0;fixed3  SHLighting : COLOR;UNITY_FOG_COORDS(1)};sampler2D _MainTex;float4 _MainTex_ST;float _SHLightingScale;v2f vert (appdata_base v){v2f o;o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);float3 worldNormal = mul((float3x3)_Object2World, v.normal);o.SHLighting= ShadeSH9(float4(worldNormal,1)) ;UNITY_TRANSFER_FOG(o,o.vertex);return o;}fixed4 frag (v2f i) : SV_Target{fixed4 col = tex2D(_MainTex, i.texcoord);col.rgb*=i.SHLighting;UNITY_APPLY_FOG(i.fogCoord, col);UNITY_OPAQUE_ALPHA(col.a);return col*_SHLightingScale;}ENDCG}
}}

VF版本代码02效果




这篇关于UnityShader实例07:在shader调用unity内置lightmap和light Probes的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1011998

相关文章

PyQt6 键盘事件处理的实现及实例代码

《PyQt6键盘事件处理的实现及实例代码》本文主要介绍了PyQt6键盘事件处理的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起... 目录一、键盘事件处理详解1、核心事件处理器2、事件对象 QKeyEvent3、修饰键处理(1)、修饰键类

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

使用Go调用第三方API的方法详解

《使用Go调用第三方API的方法详解》在现代应用开发中,调用第三方API是非常常见的场景,比如获取天气预报、翻译文本、发送短信等,Go作为一门高效并发的编程语言,拥有强大的标准库和丰富的第三方库,可以... 目录引言一、准备工作二、案例1:调用天气查询 API1. 注册并获取 API Key2. 代码实现3

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

MySQL的配置文件详解及实例代码

《MySQL的配置文件详解及实例代码》MySQL的配置文件是服务器运行的重要组成部分,用于设置服务器操作的各种参数,下面:本文主要介绍MySQL配置文件的相关资料,文中通过代码介绍的非常详细,需要... 目录前言一、配置文件结构1.[mysqld]2.[client]3.[mysql]4.[mysqldum

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、

Nginx添加内置模块过程

《Nginx添加内置模块过程》文章指导如何检查并添加Nginx的with-http_gzip_static模块:确认该模块未默认安装后,需下载同版本源码重新编译,备份替换原有二进制文件,最后重启服务验... 目录1、查看Nginx已编辑的模块2、Nginx官网查看内置模块3、停止Nginx服务4、Nginx

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点

Python如何调用另一个类的方法和属性

《Python如何调用另一个类的方法和属性》在Python面向对象编程中,类与类之间的交互是非常常见的场景,本文将详细介绍在Python中一个类如何调用另一个类的方法和属性,大家可以根据需要进行选择... 目录一、前言二、基本调用方式通过实例化调用通过类继承调用三、高级调用方式通过组合方式调用通过类方法/静