[unity渲染管线]延迟渲染

本文介绍了Unity中的延迟渲染管线,包括准备工作、Gbuffer pass和光照计算。在Gbuffer阶段,存储了漫反射颜色、法线、金属度等信息。光照计算部分,遵循虚幻的PBR做法,详细探讨了BRDF、漫反射和镜面反射的计算,以及环境光的处理。文章还提供了参考资料和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

想了想还是写下电子日志做备忘,之后陆续将以前做过的龙书的笔记也码过来好了,顺便复习。

准备工作

把camera的clear flag改为don’t clear;culling mask改为nothing。把color space改为linear。

延迟渲染

原理已经有很多大佬写的很清楚了,这里就不细讲了,Gbuffer摆放是参照虚幻的。

Gbuffer pass

延迟渲染的第一步是Gbuffer pass:
首先定义rendertexture的结构

void Start()
    {
        rt = new RenderTexture(Screen.width, Screen.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
        GBufferTexture = new RenderTexture[]
        {
            new RenderTexture(Screen.width,Screen.height,0,RenderTextureFormat.ARGB32,RenderTextureReadWrite.Linear),
            new RenderTexture(Screen.width,Screen.height,0,RenderTextureFormat.ARGB32,RenderTextureReadWrite.Linear),
            new RenderTexture(Screen.width,Screen.height,0,RenderTextureFormat.ARGB2101010,RenderTextureReadWrite.Linear),
            new RenderTexture(Screen.width,Screen.height,0,RenderTextureFormat.ARGB2101010,RenderTextureReadWrite.Linear)
         };
        depthTexture = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.Depth, RenderTextureReadWrite.Linear);
        GBuffers = new RenderBuffer[GBufferTexture.Length];
        for (int i = 0; i < GBuffers.Length; i++)
        {
            GBuffers[i] = GBufferTexture[i].colorBuffer;
        }
        gbufferIDs = new int[] {
            Shader.PropertyToID("outGBuffer0"),
            Shader.PropertyToID("outGBuffer1"),
            Shader.PropertyToID("outGBuffer2"),
            Shader.PropertyToID("outEmission")
        };

    }

在shader里只需要简单地将当面帧的屏幕空间信息(漫反射颜色,金属度,法线等)写进多个rendertexture就行。

struct VertexInput
{
	float4 vertex   : POSITION;
	float2 uv0      : TEXCOORD0;
	float2 uv1      : TEXCOORD1;
	float2 uv2      : TEXCOORD2;
	float2 uv3      : TEXCOORD3;
	float4 tangent  : TANGENT;
	half3 normal    : NORMAL;
	
	
};


	    
	struct VertexOutputDeferred
	{
		float4 pos                            : SV_POSITION;
		float4 uv0                            : TEXCOORD0;
		float4 uv1                            : TEXCOORD1;
		float4 TtoW0                          : TEXCOORD2;
		float4 TtoW1                          : TEXCOORD3;
		float4 TtoW2                          : TEXCOORD4;
	};

	sampler2D _MainTex;
	float4 _MainTex_ST;
	sampler2D _BumpMap;
	float4 _BumpMap_ST;
	sampler2D _AORoughnessMetallic;
	float4 _AORoughnessMetallic_ST;
	sampler2D  _EmissionMap;
	float4 _EmissionMap_ST;

	VertexOutputDeferred vertDeferred(VertexInput v)
	{
		
		VertexOutputDeferred o;
		o.uv0.xy = TRANSFORM_TEX(v.uv0, _MainTex);
		o.uv0.zw = TRANSFORM_TEX(v.uv1, _BumpMap);
		o.uv1.xy = TRANSFORM_TEX(v.uv2, _AORoughnessMetallic);
		o.uv1.zw = TRANSFORM_TEX(v.uv3, _EmissionMap);
		
		o.pos = UnityObjectToClipPos(v.vertex);
		float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
		float3 worldNormal = UnityObjectToWorldNormal(v.normal);
		float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
		float3 worldBinormal = cross(worldNormal, worldTangent)*v.tangent.w;

		o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
		o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
		o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);

		return o;
	}

	void fragDeferred(
		VertexOutputDeferred i,
		out half4 outGBuffer0 : SV_Target0,
		out half4 outGBuffer1 : SV_Target1,
		out half4 outGBuffer2 : SV_Target2,
		out half4 outEmission : SV_Target3         

	)
	{
		float3 bump = UnpackNormal(tex2D(_BumpMap, i.uv0.zw));
		bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));
		bump = normalize(float3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
		half3 diffuse = tex2D(_MainTex, i.uv0.xy).xyz;
		half ao = tex2D(_AORoughnessMetallic, i.uv1.xy).x;
		half roughness = tex2D(_AORoughnessMetallic, i.uv1.xy).y;
		half metallic = tex2D(_AORoughnessMetallic, i.uv1.xy).z;
		half3 emissive = tex2D(_EmissionMap, i.uv1.zw).xyz;
		outGBuffer0 = half4(diffuse, ao);
		outGBuffer1 = half4(1.0, 1.0, 1.0, roughness);
		outGBuffer2 = half4(bump*0.5f + 0.5f, metallic);
		outEmission = half4(emissive, 1.0f);

	
		
	}

这里为了以后修改方便在顶点着色器里我还另外存了worldpos。
材质的属性有:
漫反射贴图,法线贴图,遮蔽粗糙金属贴图,自发光贴图。
gbuffer的结构为:
RT0:RGB(diffuse color) A(AO)
RT1:RG(motion vector) A(roughness)
RT2:RGB(world normal) A(metallic)
RT3:RGB(emissive)
AO和motion vector和emissve之后再实现。

光照计算

当前帧的各种信息存入RT之后,计算光照的时候直接对它们采样。这里在同学大佬的建议下没有用unity的PBR而是抄了下虚幻的做法。
关于PBR理论和解释可以看毛神的博客。

基础概念

光通量:单位时间内某一表面接受到的光子总数量,要注意的是光通量不是亮度,亮度应该是光通量的密度,也就是单位面积的光通量。
立体角:立体角在球面上覆盖的范围是就是球面积分里的微元。计算光照时,

<think>好的,用户想了解Unity引擎中不同的渲染管线HDRP、LWRP(现在叫URP)和Built-in的区别及使用场景。首先,我需要回忆这三种管线的特点。 首先,Built-in Render Pipeline是Unity传统的渲染管线,已经存在很长时间,适用于大部分项目,特别是需要跨平台兼容性的情况。它的优点在于稳定,支持各种功能,但可能不够灵活。 然后是HDRP,即高清渲染管线,专注于高画质,适合PC、主机等高性能平台。它支持复杂的光照和特效,比如体积光、屏幕空间反射等,但需要较高的硬件配置。 接下来是URP(以前叫LWRP),轻量级渲染管线,后来改名为通用渲染管线。它旨在优化性能,适合移动端和低端设备,同时保持一定的画质。URP的配置更灵活,适合需要跨平台但资源有限的项目。 用户可能需要知道它们的区别和使用场景,比如项目类型、目标平台、画质需求等。需要比较它们的性能、支持的功能以及适用情况。例如,HDRP适合高端游戏或影视项目,URP适合手机游戏,而Built-in适合需要传统支持或特定插件的情况。 还要注意引用用户提供的资料,特别是引用[2]中提到的渲染流程和Shader编写,这可能和渲染管线的选择有关。比如HDRP可能需要更复杂的Shader编写,而URP可能有更简化的流程。 需要确保回答结构清晰,分点说明每个管线的特点、区别和适用场景。同时,生成相关的问题,如如何迁移项目到URP,性能优化方法等。最后检查是否符合格式要求,使用正确的中文表达和LaTeX格式(虽然这个问题可能不太涉及数学公式,但如果有相关术语可能需要用行内格式)。</think>### Unity渲染管线类型对比:HDRP、URP、Built-in #### 1. **内置渲染管线(Built-in Render Pipeline)** - **核心特点**:Unity的传统渲染系统,支持固定功能着色器和可编程Shader[^2],包含前向渲染延迟渲染两种路径。 - **使用场景**: - 需要兼容旧版Unity项目(2019.3以前) - 依赖特定插件(如某些Asset Store资源) - 目标平台包含低端移动设备或WebGL - **局限性**:扩展性差,无法直接使用HDRP/URP专属功能(如Shader Graph)。 #### 2. **高清渲染管线(HDRP)** - **核心特点**: - 支持物理光源(每像素光照)、体积雾、光线追踪等高级特效 - 要求Shader必须符合HLSL语法标准 - 需要硬件支持Shader Model 5.0及以上 - **使用场景**: - 主机/PC平台的高画质游戏 - 影视级实时渲染(如虚拟制片) - 示例项目:提供的[俯视角森林场景](https://pan.baidu.com/s/1AAxfKWIIYdNgPZtuIVM1hQ?pwd=1234)即采用HDRP实现复杂光照效果[^1] - **硬件需求**:需DX11/12、Vulkan或Metal API,最低GTX 980级别显卡。 #### 3. **通用渲染管线(URP,原LWRP)** - **核心特点**: - 单pass前向渲染为主,支持GPU Instancing - 提供Shader Graph可视化编程工具 - 可配置2D/3D混合项目(如《原神》移动端) - **使用场景**: - 移动端游戏(60FPS性能优化) - VR/AR项目(需高帧率渲染) - 跨平台项目(支持Switch/Xbox等主机) #### 对比表格 | 特性 | Built-in | HDRP | URP | |---------------------|---------------|-----------------|-----------------| | **目标平台** | 全平台兼容 | PC/主机 | 移动/跨平台 | | **光照复杂度** | 中等 | 极高(1000+光源)| 中低(4-8主光源)| | **Shader开发** | Surface Shader| HLSL+Shader Graph| URP Shader Graph| | **安装包体积** | 最小 | 增加30-50MB | 增加10-20MB | #### 迁移建议 - 从Built-in转向URP需修改: ```shader // 原Shader头部声明需替换 #pragma surface surf Standard // Built-in -> #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" // URP ``` - HDRP项目推荐使用Shader Graph实现复杂材质,避免直接编写底层HLSL代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值