当前位置: 首页 > article >正文

【Unity Shader编程】之透明物体渲染

unity shader的透明物体渲染,主要是要控制好渲染队列以及是否开启深度写入,当遇到透明渲染队列需要关闭深度写入,以防半透明或者透明物体写入的时候,导致后面的不透明物体因为深度写入的判断杯丢弃,并且半透明或者透明物体,需要在不透明物体之后渲染,而半透明物体渲染,需要渲染前后两面,因而,需要两个pass,一个先渲染背面,另外一个再渲染正面,达到双面渲染的状态。

在 Unity 的渲染流程中,当使用 双 Pass 渲染半透明物体 时,两个 Pass 的深度处理逻辑如下:


  1. 第一个 Pass(深度写入)
  • 目标:仅将模型的 深度值 写入深度缓冲,不输出任何颜色(通过 ColorMask 0 实现)。
  • 原理:
    • 开启 ZWrite On,将模型的逐像素深度值(如顶点变换后的 SV_POSITION 深度)写入深度缓冲。
    • 结果:深度缓冲中记录了该模型所有可见片元的深度值,覆盖原有不透明物体的深度信息(若当前片元更近)。

  1. 第二个 Pass(半透明混合)
  • 目标:进行透明度混合,并依赖第一个 Pass 写入的深度信息。
  • 处理逻辑:
    • 深度测试:默认开启 ZTest LEqual,使用第一个 Pass 写入的深度缓冲值进行测试。
    • 深度写入:关闭 ZWrite Off,避免覆盖深度缓冲,确保后续物体的正确遮挡。
    • 颜色混合:通过 Blend 命令混合当前片元颜色与颜色缓冲中的颜色(如 Blend SrcAlpha OneMinusSrcAlpha)。

  1. 核心区别
    | Pass | 深度写入(ZWrite) | 颜色输出(ColorMask) | 作用 |
    |---------------|-------------------|----------------------|------------------------------------|
    | 第一个 Pass | On | 0(不输出颜色) | 仅记录模型深度到深度缓冲 |
    | 第二个 Pass | Off | 正常输出颜色 | 基于第一个 Pass 的深度进行混合 |

  1. 实际效果验证
  • 正确性:
    第一个 Pass 写入的深度值会被第二个 Pass 的深度测试使用。例如,当模型自交叉时,第一个 Pass 的逐像素深度写入能确保第二个 Pass 内部片元的正确遮挡关系。
  • 错误情况:
    若直接使用单 Pass 开启深度写入,会导致深度缓冲被半透明片元覆盖,后续不透明物体可能被错误遮挡]。

总结
第一个 Pass 的深度写入为第二个 Pass 提供了逐像素的深度基准,而第二个 Pass 仅依赖此基准进行混合(不修改深度缓冲)。这种设计平衡了半透明物体的正确遮挡与颜色混合需求]。这种做法没办法看到透明物体的背面,只能看到正面

而当两个pass都关闭深度写入,则会使另外一种效果
可以看到正反面

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shaders Book/Chapter 8/Blend Operations 0" {
	Properties {
		_Color ("Color Tint", Color) = (1, 1, 1, 1)
		_MainTex ("Main Tex", 2D) = "white" {}
		_AlphaScale ("Alpha Scale", Range(0, 1)) = 1
	}
	SubShader {
		Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
		
		Pass {
			Tags { "LightMode"="ForwardBase" }
			
			ZWrite Off
			
			Blend SrcAlpha OneMinusSrcAlpha, One Zero
			
			CGPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag
			
			#include "Lighting.cginc"
			
			fixed4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed _AlphaScale;
			
			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 texcoord : TEXCOORD0;
			};
			
			struct v2f {
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
			};
			
			v2f vert(a2v v) {
			 	v2f o;
			 	o.pos = UnityObjectToClipPos(v.vertex);

			 	o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
			 	
			 	return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {				
				fixed4 texColor = tex2D(_MainTex, i.uv);
			 	
				return fixed4(texColor.rgb * _Color.rgb, texColor.a * _AlphaScale);
			}
			
			ENDCG
		}
	} 
	FallBack "Transparent/VertexLit"
}


http://www.kler.cn/a/599638.html

相关文章:

  • 【VUE】day07 路由
  • FFmpeg6.1.1 MSYS2+GCC 源码编译
  • 【Java SE】单例设计模式
  • ngx_http_core_server_name
  • RocketMQ 面试备战指南
  • 在 IntelliJIDEA中实现Spring Boot多实例运行:修改配置与批量启动详解
  • java实现coze平台鉴权+工作流调用(踩坑记录)
  • Springboot的jak安装与配置教程
  • java版嘎嘎快充玉阳软件互联互通中电联云快充协议充电桩铁塔协议汽车单车一体充电系统源码uniapp
  • 0324-项目
  • 豆包AI插件:提升浏览器使用效率的智能助手
  • 10分钟打造专属AI助手!ToDesk云电脑/顺网云/海马云操作DeepSeek哪家强?
  • 笔记:代码随想录算法训练营day60:并查集理论基础、寻找存在的路径
  • vue2中引入elementui
  • Qt在ARM中,如何使用drmModeObjectSetProperty 设置 Plane 的 zpos 值
  • 在 Kubernetes 中部署 Trivy 漏洞扫描服务
  • 地理信息系统(GIS)在智慧城市中的40个应用场景案例
  • BSides Vancouver 2018靶机通关教学
  • ROS2下MoveIt+Rviz+MuJoCo 三剑合璧!Panda 机械臂联动仿真!
  • Box-Cox变换:让数据服从正态分布的数学魔法