UnityShader学习——不同光源及阴影

不同光源

最常使用的光源属性:

  • 光源的位置
  • 光源方向(更具体说就是,到某点的方向)
  • 颜色
  • 强度
  • 衰减(更具体说就是,到某点的衰减,与该点到光源的距离有关)

这些属性和光源的几何定义息息相关。

光源类型 位置 方向 颜色和强度 衰减
Unity代码 _WorldSpaceLightPos0 _LightColor0 unity_WorldToLight_LightTexture0UNITY_ATTEN_CHANNEL
平行光 × Transform的Rotation属性 面板控制 1.0(无衰减)
点光源 Transform的Position属性 点光源的位置减去某点的位置 面板控制 点光源球心处的光照强度最强,球体边界处的最弱,值为0
聚光灯 Transform的Position属性 聚光灯的位置减去某点的位置 面板控制 锥形的顶点处光照强度最强,在锥形的边界处强度为0

阴影

让场景中可以产生阴影:

我们首先需要让平行光可以收集阴影信息。这需要在光源的Light组件中开启阴影。

让物体投射或接收阴影:

在Unity中,我们可以选择是否让一个物体投射或接收阴影。这是通过设置Mesh Renderer组件中的Cast Shadows和Receive Shadows属性来实现的。

一个物体接收来自其他物体的阴影,以及它向其他物体投射阴影是两个过程。

  • 如果我们想要一个物体向其他物体投射阴影,就必须把该物体加入到光源的阴影映射纹理的计算中,从而让其他物体在对阴影映射纹理采样时可以得到该物体的相关信息。在Unity中,这个过程是通过为该物体执行LightMode为ShadowCaster的Pass来实现的。如果使用了屏幕空间的投影映射技术,Unity还会使用这个Pass产生一张摄像机的深度纹理。
  • 如果我们想要一个物体接收来自其他物体的阴影,就必须在Shader中对阴影映射纹理(包括屏幕空间的阴影图)进行采样,把采样结果和最后的光照结果相乘来产生阴影效果

我们的shader中没有定义这样一个Pass,但我们为它的Fallback指定了一个用于回调Unity Shader,即内置的Specular。虽然Specular本身也没有包含这样一个Pass,但是由于它的Fallback调用了VertexLit,它会继续回调,并最终回调到内置的VertexLit。

我们可以不依赖Fallback,而自行在SubShader中定义自己的LightMode为ShadowCaster的Pass。这种自定义的Pass可以让我们更加灵活地控制阴影的产生。但由于这个Pass的功能通常是可以在多个Unity Shader间通用的,因此直接Fallback是一个更加方便的用法。

在默认情况下,我们在计算光源的阴影映射纹理时会剔除掉物体的背面。但对于内置的平面来说,它只有一个面,因此在本例中当计算阴影映射纹理时,由于右侧的平面在光源空间下没有任何正面(frontface),因此就不会添加到阴影映射纹理中。我们可以将Cast Shadows设置为Two Sided来允许对物体的所有面都计算阴影信息。

实战

以下shader代码是渲染一个不透明物体在平行光、点光源下的阴影:

Shader "ShaderBook/Chapter9/ForwardRender" {
   
	Properties {
   
		......
	}
	SubShader {
   
		Tags {
    "RenderType"="Opaque" }
		
		Pass {
   
			// 环境光 & 第一个逐像素光照 (平行光)
			Tags {
    "LightMode"="ForwardBase" }		
			CGPROGRAM			
			#pragma multi_compile_fwdbase				
			#pragma vertex vert
			#pragma fragment frag
			
			#include "Lighting.cginc"
			//计算阴影时所用的宏都是在这个文件中声明
			#include "AutoLight.cginc"
			......
			struct v2f {
   
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				//【阴影一】声明一个用于对阴影纹理采样的坐标:_ShadowCoord
				SHADOW_COORDS(2)
				//需要注意的是,这个宏的参数需要是下一个可用的插值寄存器的索引值,在上面的例子中就是2
			};
			
			v2f vert(a2v v) {
   
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);				
				o.worldNormal = UnityObjectToWorldNormal(v.normal);				
				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				//【阴影二】在顶点着色器中计算上一步中声明的阴影纹理坐标	
				//根据平台不同而有所差异:把顶点坐标从模型空间变换到光源空间后存储到_ShadowCoord中						
				//TRANSFER_SHADOW会使用v.vertex或a.pos来计算坐标
				//a2v结构体中的顶点坐标变量名必须是vertex.
				//顶点着色器的输出结构体v2f必须命名为o,且v2f中的顶点位置变量必须命名为pos
				TRANSFER_SHADOW(o);
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {
   
				//环境光		
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz
### 关于 Unity URP 的概述 Unity Universal Render Pipeline (URP) 是一种轻量级渲染管线,旨在提供更高的性能更广泛的平台兼容性[^2]。它通过简化渲染过程并减少资源消耗来提升效率,同时保持高质量的视觉效果。 以下是关于 URP 设置使用的详细介绍: --- ### 创建自定义渲染管线资产 为了在项目中启用 URP,需要创建一个新的 `RenderPipelineAsset` 资产文件。这可以通过继承 `RenderPipeline` `RenderPipelineAsset` 类来自定义渲染逻辑[^1]。具体操作如下: #### 步骤说明 1. **安装包管理器中的 URP 插件** 打开 Package Manager 并搜索 “Universal RP”,然后点击 Install 安装插件。 2. **配置场景以使用 URP** 在菜栏中选择 `Window > Rendering > Lighting Settings`,然后切换到 URP 渲染模式。 3. **升级材质** 如果项目中有内置 Shader,则可以使用工具将其转换为适用于 URP 的版本。路径为: `Edit > Render Pipeline > Universal Render Pipeline`,随后可以选择批量升级选项[^3]。 --- ### 主要功能模块解析 URP 提供了一系列强大的特性用于增强游戏画面表现力,这些特性包括但不限于以下几个方面[^4]: - **阴影渲染**: 支持实时动态阴影计算以及烘焙静态光源阴影。 - **预通道渲染(pre-passes)**: 可以为特定对象执行额外的数据采集工作流。 - **G 缓冲区(G-buffer)**: 存储每像素的颜色、法线方向其他属性以便后期处理。 - **延迟灯光(Deferred Lights)**: 高效地应用复杂的全局照明方案而不增加过多成本。 - **天空盒(Skybox)**: 自动适配不同环境贴图生成逼真的背景视图。 - **透明物体绘制(transparents)**: 对半透表面进行精确排序从而避免伪影现象发生。 - **后置特效(Post Processing Effects)**: 实现诸如模糊、色调映射等功能进一步美化最终图像质量。 --- ### Visual Effect Graph 依赖关系 值得注意的是,如果计划利用 VFX Graph 创造粒子系统或其他高级视觉效果,则必须确保当前工程已激活 URP 或 HDRP 中的一种作为基础架构支持[^5]。不过需要注意的是,HDRP 不支持 Android 设备部署;因此对于移动开发而言推荐优先考虑采用 URP 方案。 --- ```csharp // 示例代码展示如何初始化一个简的 URP 场景脚本 using UnityEngine; using UnityEngine.Rendering.Universal; public class SimpleURPScript : MonoBehaviour { private void Start() { var volume = VolumeManager.instance.stack.GetComponent<CustomVolume>(); if (!volume.IsActive()) { Debug.Log("Custom Volume is inactive."); } } } ``` 上述片段演示了一个基本的操作方式——访问堆栈组件状态信息,并判断其活动情况。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值